From 624963eadecd21515b04c0e9e6dc5ff5c274c676 Mon Sep 17 00:00:00 2001
From: renovate <renovate-bot@autistici.org>
Date: Sun, 17 Jan 2021 16:57:31 +0000
Subject: [PATCH] Update module miekg/dns to v1.1.35

---
 go.mod                                        |    2 +-
 go.sum                                        |    5 +
 vendor/github.com/miekg/dns/.travis.yml       |   11 +-
 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         |   76 +-
 vendor/github.com/miekg/dns/acceptfunc.go     |   61 +
 vendor/github.com/miekg/dns/client.go         |  306 +--
 vendor/github.com/miekg/dns/clientconfig.go   |    8 +-
 vendor/github.com/miekg/dns/defaults.go       |  132 +-
 vendor/github.com/miekg/dns/dns.go            |   61 +-
 vendor/github.com/miekg/dns/dnssec.go         |  163 +-
 vendor/github.com/miekg/dns/dnssec_keygen.go  |   46 +-
 vendor/github.com/miekg/dns/dnssec_keyscan.go |   70 +-
 vendor/github.com/miekg/dns/dnssec_privkey.go |   33 +-
 vendor/github.com/miekg/dns/doc.go            |  108 +-
 vendor/github.com/miekg/dns/duplicate.go      |   32 +-
 vendor/github.com/miekg/dns/edns.go           |  131 +-
 vendor/github.com/miekg/dns/format.go         |    8 +-
 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         |   71 +-
 vendor/github.com/miekg/dns/msg.go            |  789 +++---
 vendor/github.com/miekg/dns/msg_helpers.go    |  402 +++-
 vendor/github.com/miekg/dns/msg_truncate.go   |  112 +
 vendor/github.com/miekg/dns/nsecx.go          |   49 +-
 vendor/github.com/miekg/dns/privaterr.go      |  126 +-
 vendor/github.com/miekg/dns/rawmsg.go         |   49 -
 vendor/github.com/miekg/dns/reverse.go        |   14 +
 vendor/github.com/miekg/dns/sanitize.go       |    7 +-
 vendor/github.com/miekg/dns/scan.go           |  307 +--
 vendor/github.com/miekg/dns/scan_rr.go        | 1509 ++++--------
 vendor/github.com/miekg/dns/serve_mux.go      |   37 +-
 vendor/github.com/miekg/dns/server.go         |  407 ++--
 vendor/github.com/miekg/dns/sig0.go           |   38 +-
 vendor/github.com/miekg/dns/singleinflight.go |   10 +-
 vendor/github.com/miekg/dns/smimea.go         |    5 +-
 vendor/github.com/miekg/dns/svcb.go           |  744 ++++++
 vendor/github.com/miekg/dns/tlsa.go           |    5 +-
 vendor/github.com/miekg/dns/tsig.go           |  111 +-
 vendor/github.com/miekg/dns/types.go          |  330 ++-
 vendor/github.com/miekg/dns/udp_windows.go    |    6 +-
 vendor/github.com/miekg/dns/update.go         |   14 +-
 vendor/github.com/miekg/dns/version.go        |    8 +-
 vendor/github.com/miekg/dns/xfr.go            |   64 +-
 vendor/github.com/miekg/dns/zcompress.go      |  152 --
 vendor/github.com/miekg/dns/zduplicate.go     |  858 +++++--
 vendor/github.com/miekg/dns/zmsg.go           | 2118 ++++++-----------
 vendor/github.com/miekg/dns/ztypes.go         |  407 ++--
 vendor/modules.txt                            |    2 +-
 54 files changed, 5178 insertions(+), 5024 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/acceptfunc.go
 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/msg_truncate.go
 delete mode 100644 vendor/github.com/miekg/dns/rawmsg.go
 create mode 100644 vendor/github.com/miekg/dns/svcb.go
 delete mode 100644 vendor/github.com/miekg/dns/zcompress.go

diff --git a/go.mod b/go.mod
index 771ca66e..14d65294 100644
--- a/go.mod
+++ b/go.mod
@@ -5,7 +5,7 @@ go 1.14
 require (
 	git.autistici.org/ai3/go-common v0.0.0-20210110180225-a05c683cfe23
 	git.autistici.org/ai3/tools/replds v0.0.0-20210117164327-f8f2820a3407
-	github.com/miekg/dns v1.0.14
+	github.com/miekg/dns v1.1.35
 	github.com/prometheus/client_golang v1.9.0
 	golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
 	gopkg.in/yaml.v2 v2.3.0
diff --git a/go.sum b/go.sum
index 90b5b875..04aa0645 100644
--- a/go.sum
+++ b/go.sum
@@ -192,6 +192,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0j
 github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
 github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA=
 github.com/miekg/dns v1.0.14/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/miscreant/miscreant.go v0.0.0-20200214223636-26d376326b75/go.mod h1:pBbZyGwC5i16IBkjVKoy/sznA8jPD/K9iedwe1ESE6w=
 github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
 github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
@@ -350,6 +352,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=
@@ -376,6 +379,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/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -403,6 +407,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/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/.travis.yml b/vendor/github.com/miekg/dns/.travis.yml
index 18259374..7d9b1727 100644
--- a/vendor/github.com/miekg/dns/.travis.yml
+++ b/vendor/github.com/miekg/dns/.travis.yml
@@ -2,16 +2,15 @@ language: go
 sudo: false
 
 go:
-  - 1.10.x
-  - 1.11.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 7f1aaa5d..fc8394e2 100644
--- a/vendor/github.com/miekg/dns/README.md
+++ b/vendor/github.com/miekg/dns/README.md
@@ -7,10 +7,10 @@
 
 > Less is more.
 
-Complete and usable DNS library. All widely used Resource Records are supported, including the
-DNSSEC types. It follows a lean and mean philosophy. If there is stuff you should know as a DNS
-programmer there isn't a convenience function for it. Server side and client side programming is
-supported, i.e. you can build servers and resolvers with it.
+Complete and usable DNS library. All Resource Records are supported, including the DNSSEC types.
+It follows a lean and mean philosophy. If there is stuff you should know as a DNS programmer there
+isn't a convenience function for it. Server side and client side programming is supported, i.e. you
+can build servers and resolvers with it.
 
 We try to keep the "master" branch as sane as possible and at the bleeding edge of standards,
 avoiding breaking changes wherever reasonable. We support the last two versions of Go.
@@ -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,12 +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://play.google.com/store/apps/details?id=com.turbobytes.dig
 * 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/corny/dnscheck for <http://public-dns.info/>
 * https://github.com/miekg/unbound
 * https://github.com/miekg/exdns
 * https://dnslookup.org
@@ -55,55 +52,57 @@ 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 (JD.COM)
+* 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.
 
 # Features
 
-* UDP/TCP queries, IPv4 and IPv6;
-* RFC 1035 zone file parsing ($INCLUDE, $ORIGIN, $TTL and $GENERATE (for all record types) are supported;
-* Fast:
-    * Reply speed around ~ 80K qps (faster hardware results in more qps);
-    * Parsing RRs ~ 100K RR/s, that's 5M records in about 50 seconds;
-* Server side programming (mimicking the net/http package);
-* Client side programming;
-* DNSSEC: signing, validating and key generation for DSA, RSA, ECDSA and Ed25519;
-* EDNS0, NSID, Cookies;
-* AXFR/IXFR;
-* TSIG, SIG(0);
-* DNS over TLS: optional encrypted connection between client and server;
-* DNS name compression;
-* Depends only on the standard library.
+* UDP/TCP queries, IPv4 and IPv6
+* RFC 1035 zone file parsing ($INCLUDE, $ORIGIN, $TTL and $GENERATE (for all record types) are supported
+* Fast
+* Server side programming (mimicking the net/http package)
+* Client side programming
+* DNSSEC: signing, validating and key generation for DSA, RSA, ECDSA and Ed25519
+* EDNS0, NSID, Cookies
+* AXFR/IXFR
+* TSIG, SIG(0)
+* DNS over TLS (DoT): encrypted connection between client and server over TCP
+* DNS name compression
 
 Have fun!
 
 Miek Gieben  -  2010-2012  -  <miek@miek.nl>
+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
 
 ## Examples
 
-A short "how to use the API" is at the beginning of doc.go (this also will show
-when you call `godoc github.com/miekg/dns`).
+A short "how to use the API" is at the beginning of doc.go (this also will show when you call `godoc
+github.com/miekg/dns`).
 
 Example programs can be found in the `github.com/miekg/exdns` repository.
 
@@ -127,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
@@ -153,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
@@ -161,12 +162,13 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
 * 7553 - URI record
 * 7858 - DNS over TLS: Initiation and Performance Considerations
 * 7871 - EDNS0 Client Subnet
-* 7873 - Domain Name System (DNS) Cookies (draft-ietf-dnsop-cookies)
+* 7873 - Domain Name System (DNS) Cookies
 * 8080 - EdDSA for DNSSEC
+* 8499 - DNS Terminology
 
-## Loosely based upon
+## Loosely Based Upon
 
-* `ldns`
-* `NSD`
-* `Net::DNS`
-* `GRONG`
+* ldns - <https://nlnetlabs.nl/projects/ldns/about/>
+* NSD - <https://nlnetlabs.nl/projects/nsd/about/>
+* Net::DNS - <http://www.net-dns.org/>
+* GRONG - <https://github.com/bortzmeyer/grong>
diff --git a/vendor/github.com/miekg/dns/acceptfunc.go b/vendor/github.com/miekg/dns/acceptfunc.go
new file mode 100644
index 00000000..825617fe
--- /dev/null
+++ b/vendor/github.com/miekg/dns/acceptfunc.go
@@ -0,0 +1,61 @@
+package dns
+
+// MsgAcceptFunc is used early in the server code to accept or reject a message with RcodeFormatError.
+// It returns a MsgAcceptAction to indicate what should happen with the message.
+type MsgAcceptFunc func(dh Header) MsgAcceptAction
+
+// DefaultMsgAcceptFunc checks the request and will reject if:
+//
+// * 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.
+	MsgRejectNotImplemented                        // Reject the message with a RcodeNotImplemented
+)
+
+func defaultMsgAcceptFunc(dh Header) MsgAcceptAction {
+	if isResponse := dh.Bits&_QR != 0; isResponse {
+		return MsgIgnore
+	}
+
+	// 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 MsgRejectNotImplemented
+	}
+
+	if dh.Qdcount != 1 {
+		return MsgReject
+	}
+	// NOTIFY requests can have a SOA in the ANSWER section. See RFC 1996 Section 3.7 and 3.11.
+	if dh.Ancount > 1 {
+		return MsgReject
+	}
+	// IXFR request could have one SOA RR in the NS section. See RFC 1995, section 3.
+	if dh.Nscount > 1 {
+		return MsgReject
+	}
+	if dh.Arcount > 2 {
+		return MsgReject
+	}
+	return MsgAccept
+}
diff --git a/vendor/github.com/miekg/dns/client.go b/vendor/github.com/miekg/dns/client.go
index 63ced2bd..e7ff786a 100644
--- a/vendor/github.com/miekg/dns/client.go
+++ b/vendor/github.com/miekg/dns/client.go
@@ -3,15 +3,12 @@ package dns
 // A client implementation.
 
 import (
-	"bytes"
 	"context"
 	"crypto/tls"
 	"encoding/binary"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"net"
-	"net/http"
 	"strings"
 	"time"
 )
@@ -19,8 +16,6 @@ import (
 const (
 	dnsTimeout     time.Duration = 2 * time.Second
 	tcpIdleTimeout time.Duration = 8 * time.Second
-
-	dohMimeType = "application/dns-message"
 )
 
 // A Conn represents a connection to a DNS server.
@@ -39,12 +34,11 @@ 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
 	WriteTimeout   time.Duration     // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
-	HTTPClient     *http.Client      // The http.Client to use for DNS-over-HTTPS
 	TsigSecret     map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
 	SingleInflight bool              // if true suppress multiple outstanding queries for the same Qname, Qtype and Qclass
 	group          singleflight
@@ -112,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
 }
 
@@ -130,47 +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 {
-		if c.Net == "https" {
-			// TODO(tmthrgd): pipe timeouts into exchangeDOH
-			return c.exchangeDOH(context.TODO(), m, address)
-		}
+	co, err := c.Dial(address)
 
-		return c.exchange(m, address)
+	if err != nil {
+		return nil, 0, err
 	}
+	defer co.Close()
+	return c.ExchangeWithConn(m, co)
+}
 
-	t := "nop"
-	if t1, ok := TypeToString[m.Question[0].Qtype]; ok {
-		t = t1
-	}
-	cl := "nop"
-	if cl1, ok := ClassToString[m.Question[0].Qclass]; ok {
-		cl = cl1
+// 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) {
-		if c.Net == "https" {
-			// TODO(tmthrgd): pipe timeouts into exchangeDOH
-			return c.exchangeDOH(context.TODO(), m, address)
-		}
 
-		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.
@@ -191,75 +185,25 @@ 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
 }
 
-func (c *Client) exchangeDOH(ctx context.Context, m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
-	p, err := m.Pack()
-	if err != nil {
-		return nil, 0, err
-	}
-
-	req, err := http.NewRequest(http.MethodPost, a, bytes.NewReader(p))
-	if err != nil {
-		return nil, 0, err
-	}
-
-	req.Header.Set("Content-Type", dohMimeType)
-	req.Header.Set("Accept", dohMimeType)
-
-	hc := http.DefaultClient
-	if c.HTTPClient != nil {
-		hc = c.HTTPClient
-	}
-
-	if ctx != context.Background() && ctx != context.TODO() {
-		req = req.WithContext(ctx)
-	}
-
-	t := time.Now()
-
-	resp, err := hc.Do(req)
-	if err != nil {
-		return nil, 0, err
-	}
-	defer closeHTTPBody(resp.Body)
-
-	if resp.StatusCode != http.StatusOK {
-		return nil, 0, fmt.Errorf("dns: server returned HTTP %d error: %q", resp.StatusCode, resp.Status)
-	}
-
-	if ct := resp.Header.Get("Content-Type"); ct != dohMimeType {
-		return nil, 0, fmt.Errorf("dns: unexpected Content-Type %q; expected %q", ct, dohMimeType)
-	}
-
-	p, err = ioutil.ReadAll(resp.Body)
-	if err != nil {
-		return nil, 0, err
-	}
-
-	rtt = time.Since(t)
-
-	r = new(Msg)
-	if err := r.Unpack(p); err != nil {
-		return r, 0, err
-	}
-
-	// TODO: TSIG? Is it even supported over DoH?
-
-	return r, rtt, nil
-}
-
-func closeHTTPBody(r io.ReadCloser) error {
-	io.Copy(ioutil.Discard, io.LimitReader(r, 8<<20))
-	return r.Close()
-}
-
 // ReadMsg reads a message from the connection co.
 // If the received message contains a TSIG record the transaction signature
 // is verified. This method always tries to return the message, however if an
@@ -298,24 +242,21 @@ func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) {
 		err error
 	)
 
-	switch t := co.Conn.(type) {
-	case *net.TCPConn, *tls.Conn:
-		r := t.(io.Reader)
-
-		// First two bytes specify the length of the entire message.
-		l, err := tcpMsgLen(r)
-		if err != nil {
-			return nil, err
-		}
-		p = make([]byte, l)
-		n, err = tcpRead(r, 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 {
@@ -335,78 +276,26 @@ func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) {
 	return p, err
 }
 
-// tcpMsgLen is a helper func to read first two bytes of stream as uint16 packet length.
-func tcpMsgLen(t io.Reader) (int, error) {
-	p := []byte{0, 0}
-	n, err := t.Read(p)
-	if err != nil {
-		return 0, err
-	}
-
-	// As seen with my local router/switch, returns 1 byte on the above read,
-	// resulting a a ShortRead. Just write it out (instead of loop) and read the
-	// other byte.
-	if n == 1 {
-		n1, err := t.Read(p[1:])
-		if err != nil {
-			return 0, err
-		}
-		n += n1
-	}
-
-	if n != 2 {
-		return 0, ErrShortRead
-	}
-	l := binary.BigEndian.Uint16(p)
-	if l == 0 {
-		return 0, ErrShortRead
-	}
-	return int(l), nil
-}
-
-// tcpRead calls TCPConn.Read enough times to fill allocated buffer.
-func tcpRead(t io.Reader, p []byte) (int, error) {
-	n, err := t.Read(p)
-	if err != nil {
-		return n, err
-	}
-	for n < len(p) {
-		j, err := t.Read(p[n:])
-		if err != nil {
-			return n, err
-		}
-		n += j
-	}
-	return n, err
-}
-
 // Read implements the net.Conn read method.
 func (co *Conn) Read(p []byte) (n int, err error) {
 	if co.Conn == nil {
 		return 0, ErrConnEmpty
 	}
-	if len(p) < 2 {
-		return 0, io.ErrShortBuffer
+
+	if _, ok := co.Conn.(net.PacketConn); ok {
+		// UDP connection
+		return co.Conn.Read(p)
 	}
-	switch t := co.Conn.(type) {
-	case *net.TCPConn, *tls.Conn:
-		r := t.(io.Reader)
 
-		l, err := tcpMsgLen(r)
-		if err != nil {
-			return 0, err
-		}
-		if l > len(p) {
-			return int(l), io.ErrShortBuffer
-		}
-		return tcpRead(r, p[:l])
+	var length uint16
+	if err := binary.Read(co.Conn, binary.BigEndian, &length); err != nil {
+		return 0, err
 	}
-	// UDP connection
-	n, err = co.Conn.Read(p)
-	if err != nil {
-		return n, err
+	if int(length) > len(p) {
+		return 0, io.ErrShortBuffer
 	}
-	return n, err
+
+	return io.ReadFull(co.Conn, p[:length])
 }
 
 // WriteMsg sends a message through the connection co.
@@ -428,33 +317,25 @@ func (co *Conn) WriteMsg(m *Msg) (err error) {
 	if err != nil {
 		return err
 	}
-	if _, err = co.Write(out); err != nil {
-		return err
-	}
-	return nil
+	_, err = co.Write(out)
+	return err
 }
 
 // Write implements the net.Conn Write method.
-func (co *Conn) Write(p []byte) (n int, err error) {
-	switch t := co.Conn.(type) {
-	case *net.TCPConn, *tls.Conn:
-		w := t.(io.Writer)
-
-		lp := len(p)
-		if lp < 2 {
-			return 0, io.ErrShortBuffer
-		}
-		if lp > MaxMsgSize {
-			return 0, &Error{err: "message too large"}
-		}
-		l := make([]byte, 2, lp+2)
-		binary.BigEndian.PutUint16(l, uint16(lp))
-		p = append(l, p...)
-		n, err := io.Copy(w, bytes.NewReader(p))
-		return int(n), err
-	}
-	n, err = co.Conn.Write(p)
-	return n, err
+func (co *Conn) Write(p []byte) (int, error) {
+	if len(p) > MaxMsgSize {
+		return 0, &Error{err: "message too large"}
+	}
+
+	if _, ok := co.Conn.(net.PacketConn); ok {
+		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
@@ -497,7 +378,7 @@ func ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, err error)
 
 // ExchangeConn performs a synchronous query. It sends the message m via the connection
 // c and waits for a reply. The connection c is not closed by ExchangeConn.
-// This function is going away, but can easily be mimicked:
+// Deprecated: This function is going away, but can easily be mimicked:
 //
 //	co := &dns.Conn{Conn: c} // c is your net.Conn
 //	co.WriteMsg(m)
@@ -521,11 +402,7 @@ func ExchangeConn(c net.Conn, m *Msg) (r *Msg, err error) {
 // DialTimeout acts like Dial but takes a timeout.
 func DialTimeout(network, address string, timeout time.Duration) (conn *Conn, err error) {
 	client := Client{Net: network, Dialer: &net.Dialer{Timeout: timeout}}
-	conn, err = client.Dial(address)
-	if err != nil {
-		return nil, err
-	}
-	return conn, nil
+	return client.Dial(address)
 }
 
 // DialWithTLS connects to the address on the named network with TLS.
@@ -534,12 +411,7 @@ func DialWithTLS(network, address string, tlsConfig *tls.Config) (conn *Conn, er
 		network += "-tls"
 	}
 	client := Client{Net: network, TLSConfig: tlsConfig}
-	conn, err = client.Dial(address)
-
-	if err != nil {
-		return nil, err
-	}
-	return conn, nil
+	return client.Dial(address)
 }
 
 // DialTimeoutWithTLS acts like DialWithTLS but takes a timeout.
@@ -548,21 +420,13 @@ func DialTimeoutWithTLS(network, address string, tlsConfig *tls.Config, timeout
 		network += "-tls"
 	}
 	client := Client{Net: network, Dialer: &net.Dialer{Timeout: timeout}, TLSConfig: tlsConfig}
-	conn, err = client.Dial(address)
-	if err != nil {
-		return nil, err
-	}
-	return conn, nil
+	return client.Dial(address)
 }
 
 // ExchangeContext acts like Exchange, but honors the deadline on the provided
 // context, if present. If there is both a context deadline and a configured
 // timeout on the client, the earliest of the two takes effect.
 func (c *Client) ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
-	if !c.SingleInflight && c.Net == "https" {
-		return c.exchangeDOH(ctx, m, a)
-	}
-
 	var timeout time.Duration
 	if deadline, ok := ctx.Deadline(); !ok {
 		timeout = 0
@@ -571,7 +435,7 @@ func (c *Client) ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg,
 	}
 	// not passing the context to the underlying calls, as the API does not support
 	// context. For timeouts you should set up Client.Dialer and call Client.Exchange.
-	// TODO(tmthrgd): this is a race condition
+	// TODO(tmthrgd,miekg): this is a race condition.
 	c.Dialer = &net.Dialer{Timeout: timeout}
 	return c.Exchange(m, a)
 }
diff --git a/vendor/github.com/miekg/dns/clientconfig.go b/vendor/github.com/miekg/dns/clientconfig.go
index f13cfa30..e11b630d 100644
--- a/vendor/github.com/miekg/dns/clientconfig.go
+++ b/vendor/github.com/miekg/dns/clientconfig.go
@@ -68,14 +68,10 @@ func ClientConfigFromReader(resolvconf io.Reader) (*ClientConfig, error) {
 			}
 
 		case "search": // set search path to given servers
-			c.Search = make([]string, len(f)-1)
-			for i := 0; i < len(c.Search); i++ {
-				c.Search[i] = f[i+1]
-			}
+			c.Search = append([]string(nil), f[1:]...)
 
 		case "options": // magic options
-			for i := 1; i < len(f); i++ {
-				s := f[i]
+			for _, s := range f[1:] {
 				switch {
 				case len(s) >= 6 && s[:6] == "ndots:":
 					n, _ := strconv.Atoi(s[6:])
diff --git a/vendor/github.com/miekg/dns/defaults.go b/vendor/github.com/miekg/dns/defaults.go
index 14e18b0b..d874e300 100644
--- a/vendor/github.com/miekg/dns/defaults.go
+++ b/vendor/github.com/miekg/dns/defaults.go
@@ -4,6 +4,7 @@ import (
 	"errors"
 	"net"
 	"strconv"
+	"strings"
 )
 
 const hexDigit = "0123456789abcdef"
@@ -104,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}
@@ -145,10 +146,9 @@ func (dns *Msg) IsTsig() *TSIG {
 // record in the additional section will do. It returns the OPT record
 // found or nil.
 func (dns *Msg) IsEdns0() *OPT {
-	// EDNS0 is at the end of the additional section, start there.
-	// We might want to change this to *only* look at the last two
-	// records. So we see TSIG and/or OPT - this a slightly bigger
-	// change though.
+	// RFC 6891, Section 6.1.1 allows the OPT record to appear
+	// anywhere in the additional record section, but it's usually at
+	// the end so start there.
 	for i := len(dns.Extra) - 1; i >= 0; i-- {
 		if dns.Extra[i].Header().Rrtype == TypeOPT {
 			return dns.Extra[i].(*OPT)
@@ -157,17 +157,93 @@ func (dns *Msg) IsEdns0() *OPT {
 	return nil
 }
 
+// popEdns0 is like IsEdns0, but it removes the record from the message.
+func (dns *Msg) popEdns0() *OPT {
+	// RFC 6891, Section 6.1.1 allows the OPT record to appear
+	// anywhere in the additional record section, but it's usually at
+	// the end so start there.
+	for i := len(dns.Extra) - 1; i >= 0; i-- {
+		if dns.Extra[i].Header().Rrtype == TypeOPT {
+			opt := dns.Extra[i].(*OPT)
+			dns.Extra = append(dns.Extra[:i], dns.Extra[i+1:]...)
+			return opt
+		}
+	}
+	return nil
+}
+
 // IsDomainName checks if s is a valid domain name, it returns the number of
 // labels and true, when a domain name is valid.  Note that non fully qualified
 // domain name is considered valid, in this case the last label is counted in
 // the number of labels.  When false is returned the number of labels is not
 // defined.  Also note that this function is extremely liberal; almost any
 // string is a valid domain name as the DNS is 8 bit protocol. It checks if each
-// label fits in 63 characters, but there is no length check for the entire
-// string s. I.e.  a domain name longer than 255 characters is considered valid.
+// label fits in 63 characters and that the entire name will fit into the 255
+// octet wire format limit.
 func IsDomainName(s string) (labels int, ok bool) {
-	_, labels, err := packDomainName(s, nil, 0, nil, false)
-	return labels, err == nil
+	// XXX: The logic in this function was copied from packDomainName and
+	// should be kept in sync with that function.
+
+	const lenmsg = 256
+
+	if len(s) == 0 { // Ok, for instance when dealing with update RR without any rdata.
+		return 0, false
+	}
+
+	s = Fqdn(s)
+
+	// Each dot ends a segment of the name. Except for escaped dots (\.), which
+	// are normal dots.
+
+	var (
+		off    int
+		begin  int
+		wasDot bool
+	)
+	for i := 0; i < len(s); i++ {
+		switch s[i] {
+		case '\\':
+			if off+1 > lenmsg {
+				return labels, false
+			}
+
+			// check for \DDD
+			if i+3 < len(s) && isDigit(s[i+1]) && isDigit(s[i+2]) && isDigit(s[i+3]) {
+				i += 3
+				begin += 3
+			} else {
+				i++
+				begin++
+			}
+
+			wasDot = false
+		case '.':
+			if wasDot {
+				// two dots back to back is not legal
+				return labels, false
+			}
+			wasDot = true
+
+			labelLen := i - begin
+			if labelLen >= 1<<6 { // top two bits of length must be clear
+				return labels, false
+			}
+
+			// off can already (we're in a loop) be bigger than lenmsg
+			// this happens when a name isn't fully qualified
+			off += 1 + labelLen
+			if off > lenmsg {
+				return labels, false
+			}
+
+			labels++
+			begin = i + 1
+		default:
+			wasDot = false
+		}
+	}
+
+	return labels, true
 }
 
 // IsSubDomain checks if child is indeed a child of the parent. If child and parent
@@ -181,7 +257,7 @@ func IsSubDomain(parent, child string) bool {
 // The checking is performed on the binary payload.
 func IsMsg(buf []byte) error {
 	// Header
-	if len(buf) < 12 {
+	if len(buf) < headerSize {
 		return errors.New("dns: bad message header")
 	}
 	// Header: Opcode
@@ -191,11 +267,18 @@ func IsMsg(buf []byte) error {
 
 // IsFqdn checks if a domain name is fully qualified.
 func IsFqdn(s string) bool {
-	l := len(s)
-	if l == 0 {
+	s2 := strings.TrimSuffix(s, ".")
+	if s == s2 {
 		return false
 	}
-	return s[l-1] == '.'
+
+	i := strings.LastIndexFunc(s2, func(r rune) bool {
+		return r != '\\'
+	})
+
+	// Test whether we have an even number of escape sequences before
+	// the dot or none.
+	return (len(s2)-i)%2 != 0
 }
 
 // IsRRset checks if a set of RRs is a valid RRset as defined by RFC 2181.
@@ -234,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
@@ -244,12 +333,19 @@ func ReverseAddr(addr string) (arpa string, err error) {
 	if ip == nil {
 		return "", &Error{err: "unrecognized address: " + addr}
 	}
-	if ip.To4() != nil {
-		return strconv.Itoa(int(ip[15])) + "." + strconv.Itoa(int(ip[14])) + "." + strconv.Itoa(int(ip[13])) + "." +
-			strconv.Itoa(int(ip[12])) + ".in-addr.arpa.", nil
+	if v4 := ip.To4(); v4 != nil {
+		buf := make([]byte, 0, net.IPv4len*4+len("in-addr.arpa."))
+		// Add it, in reverse, to the buffer
+		for i := len(v4) - 1; i >= 0; i-- {
+			buf = strconv.AppendInt(buf, int64(v4[i]), 10)
+			buf = append(buf, '.')
+		}
+		// Append "in-addr.arpa." and return (buf already has the final .)
+		buf = append(buf, "in-addr.arpa."...)
+		return string(buf), nil
 	}
 	// Must be IPv6
-	buf := make([]byte, 0, len(ip)*4+len("ip6.arpa."))
+	buf := make([]byte, 0, net.IPv6len*4+len("ip6.arpa."))
 	// Add it, in reverse, to the buffer
 	for i := len(ip) - 1; i >= 0; i-- {
 		v := ip[i]
@@ -274,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 e7557f51..ad83a27e 100644
--- a/vendor/github.com/miekg/dns/dns.go
+++ b/vendor/github.com/miekg/dns/dns.go
@@ -34,10 +34,30 @@ type RR interface {
 
 	// copy returns a copy of the RR
 	copy() RR
-	// len returns the length (in octets) of the uncompressed RR in wire format.
-	len() int
-	// pack packs an RR into wire format.
-	pack([]byte, int, map[string]int, bool) (int, error)
+
+	// len returns the length (in octets) of the compressed or uncompressed RR in wire format.
+	//
+	// If compression is nil, the uncompressed size will be returned, otherwise the compressed
+	// size will be returned and domain names will be added to the map for future compression.
+	len(off int, compression map[string]struct{}) int
+
+	// pack packs the records RDATA into wire format. The header will
+	// already have been packed into msg.
+	pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error)
+
+	// unpack unpacks an RR from wire format.
+	//
+	// This will only be called on a new and empty RR type with only the header populated. It
+	// will only be called if the record's RDATA is non-empty.
+	unpack(msg []byte, off int) (off1 int, err error)
+
+	// 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 string) *ParseError
+
+	// isDuplicate returns whether the two RRs are duplicates.
+	isDuplicate(r2 RR) bool
 }
 
 // RR_Header is the header all DNS resource records share.
@@ -70,28 +90,45 @@ func (h *RR_Header) String() string {
 	return s
 }
 
-func (h *RR_Header) len() int {
-	l := len(h.Name) + 1
+func (h *RR_Header) len(off int, compression map[string]struct{}) int {
+	l := domainNameLen(h.Name, off, compression, true)
 	l += 10 // rrtype(2) + class(2) + ttl(4) + rdlength(2)
 	return l
 }
 
+func (h *RR_Header) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
+	// RR_Header has no RDATA to pack.
+	return off, nil
+}
+
+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 string) *ParseError {
+	panic("dns: internal error: parse should never be called on RR_Header")
+}
+
 // ToRFC3597 converts a known RR to the unknown RR representation from RFC 3597.
 func (rr *RFC3597) ToRFC3597(r RR) error {
-	buf := make([]byte, r.len()*2)
-	off, err := PackRR(r, buf, 0, nil, false)
+	buf := make([]byte, Len(r)*2)
+	headerEnd, off, err := packRR(r, buf, 0, compressionMap{}, false)
 	if err != nil {
 		return err
 	}
 	buf = buf[:off]
-	if int(r.Header().Rdlength) > off {
-		return ErrBuf
+
+	*rr = RFC3597{Hdr: *r.Header()}
+	rr.Hdr.Rdlength = uint16(off - headerEnd)
+
+	if noRdata(rr.Hdr) {
+		return nil
 	}
 
-	rfc3597, _, err := unpackRFC3597(*r.Header(), buf, off-int(r.Header().Rdlength))
+	_, err = rr.unpack(buf, headerEnd)
 	if err != nil {
 		return err
 	}
-	*rr = *rfc3597.(*RFC3597)
+
 	return nil
 }
diff --git a/vendor/github.com/miekg/dns/dnssec.go b/vendor/github.com/miekg/dns/dnssec.go
index 26b512e7..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"
@@ -67,9 +65,6 @@ var AlgorithmToString = map[uint8]string{
 	PRIVATEOID:       "PRIVATEOID",
 }
 
-// StringToAlgorithm is the reverse of AlgorithmToString.
-var StringToAlgorithm = reverseInt8(AlgorithmToString)
-
 // AlgorithmToHash is a map of algorithm crypto hash IDs to crypto.Hash's.
 var AlgorithmToHash = map[uint8]crypto.Hash{
 	RSAMD5:           crypto.MD5, // Deprecated in RFC 6725
@@ -102,9 +97,6 @@ var HashToString = map[uint8]string{
 	SHA512: "SHA512",
 }
 
-// StringToHash is a map of names to hash IDs.
-var StringToHash = reverseInt8(HashToString)
-
 // DNSKEY flag values.
 const (
 	SEP    = 1
@@ -147,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:])
@@ -206,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
 	}
@@ -268,16 +260,17 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
 		return ErrKey
 	}
 
+	h0 := rrset[0].Header()
 	rr.Hdr.Rrtype = TypeRRSIG
-	rr.Hdr.Name = rrset[0].Header().Name
-	rr.Hdr.Class = rrset[0].Header().Class
+	rr.Hdr.Name = h0.Name
+	rr.Hdr.Class = h0.Class
 	if rr.OrigTtl == 0 { // If set don't override
-		rr.OrigTtl = rrset[0].Header().Ttl
+		rr.OrigTtl = h0.Ttl
 	}
-	rr.TypeCovered = rrset[0].Header().Rrtype
-	rr.Labels = uint8(CountLabel(rrset[0].Header().Name))
+	rr.TypeCovered = h0.Rrtype
+	rr.Labels = uint8(CountLabel(h0.Name))
 
-	if strings.HasPrefix(rrset[0].Header().Name, "*") {
+	if strings.HasPrefix(h0.Name, "*") {
 		rr.Labels-- // wildcard, remove from label count
 	}
 
@@ -290,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)
@@ -323,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)
@@ -334,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) {
@@ -348,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
@@ -368,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
@@ -401,7 +387,7 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
 	if rr.Algorithm != k.Algorithm {
 		return ErrKey
 	}
-	if strings.ToLower(rr.SignerName) != strings.ToLower(k.Hdr.Name) {
+	if !strings.EqualFold(rr.SignerName, k.Hdr.Name) {
 		return ErrKey
 	}
 	if k.Protocol != 3 {
@@ -411,10 +397,7 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
 	// IsRRset checked that we have at least one RR and that the RRs in
 	// the set have consistent type, class, and name. Also check that type and
 	// class matches the RRSIG record.
-	if rrset[0].Header().Class != rr.Hdr.Class {
-		return ErrRRset
-	}
-	if rrset[0].Header().Rrtype != rr.TypeCovered {
+	if h0 := rrset[0].Header(); h0.Class != rr.Hdr.Class || h0.Rrtype != rr.TypeCovered {
 		return ErrRRset
 	}
 
@@ -428,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)
@@ -453,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 {
@@ -563,20 +546,19 @@ func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey {
 
 	pubkey := new(rsa.PublicKey)
 
-	expo := uint64(0)
-	for i := 0; i < int(explen); i++ {
+	var expo uint64
+	// The exponent of length explen is between keyoff and modoff.
+	for _, v := range keybuf[keyoff:modoff] {
 		expo <<= 8
-		expo |= uint64(keybuf[keyoff+i])
+		expo |= uint64(v)
 	}
 	if expo > 1<<31-1 {
 		// Larger exponent than supported by the crypto package.
 		return nil
 	}
-	pubkey.E = int(expo)
-
-	pubkey.N = big.NewInt(0)
-	pubkey.N.SetBytes(keybuf[modoff:])
 
+	pubkey.E = int(expo)
+	pubkey.N = new(big.Int).SetBytes(keybuf[modoff:])
 	return pubkey
 }
 
@@ -601,34 +583,8 @@ func (k *DNSKEY) publicKeyECDSA() *ecdsa.PublicKey {
 			return nil
 		}
 	}
-	pubkey.X = big.NewInt(0)
-	pubkey.X.SetBytes(keybuf[:len(keybuf)/2])
-	pubkey.Y = big.NewInt(0)
-	pubkey.Y.SetBytes(keybuf[len(keybuf)/2:])
-	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 = big.NewInt(0).SetBytes(q)
-	pubkey.Parameters.P = big.NewInt(0).SetBytes(p)
-	pubkey.Parameters.G = big.NewInt(0).SetBytes(g)
-	pubkey.Y = big.NewInt(0).SetBytes(y)
+	pubkey.X = new(big.Int).SetBytes(keybuf[:len(keybuf)/2])
+	pubkey.Y = new(big.Int).SetBytes(keybuf[len(keybuf)/2:])
 	return pubkey
 }
 
@@ -658,15 +614,16 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
 	wires := make(wireSlice, len(rrset))
 	for i, r := range rrset {
 		r1 := r.copy()
-		r1.Header().Ttl = s.OrigTtl
-		labels := SplitDomainName(r1.Header().Name)
+		h := r1.Header()
+		h.Ttl = s.OrigTtl
+		labels := SplitDomainName(h.Name)
 		// 6.2. Canonical RR Form. (4) - wildcards
 		if len(labels) > int(s.Labels) {
 			// Wildcard
-			r1.Header().Name = "*." + strings.Join(labels[len(labels)-int(s.Labels):], ".") + "."
+			h.Name = "*." + strings.Join(labels[len(labels)-int(s.Labels):], ".") + "."
 		}
 		// RFC 4034: 6.2.  Canonical RR Form. (2) - domain name to lowercase
-		r1.Header().Name = strings.ToLower(r1.Header().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,
@@ -679,52 +636,52 @@ 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, r1.len()+1) // +1 to be safe(r)
+		wire := make([]byte, Len(r1)+1) // +1 to be safe(r)
 		off, err1 := PackRR(r1, wire, 0, nil, false)
 		if err1 != nil {
 			return nil, err1
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 5e654223..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
 	}
 }
 
@@ -109,21 +85,16 @@ func readPrivateKeyRSA(m map[string]string) (*rsa.PrivateKey, error) {
 			}
 			switch k {
 			case "modulus":
-				p.PublicKey.N = big.NewInt(0)
-				p.PublicKey.N.SetBytes(v1)
+				p.PublicKey.N = new(big.Int).SetBytes(v1)
 			case "publicexponent":
-				i := big.NewInt(0)
-				i.SetBytes(v1)
+				i := new(big.Int).SetBytes(v1)
 				p.PublicKey.E = int(i.Int64()) // int64 should be large enough
 			case "privateexponent":
-				p.D = big.NewInt(0)
-				p.D.SetBytes(v1)
+				p.D = new(big.Int).SetBytes(v1)
 			case "prime1":
-				p.Primes[0] = big.NewInt(0)
-				p.Primes[0].SetBytes(v1)
+				p.Primes[0] = new(big.Int).SetBytes(v1)
 			case "prime2":
-				p.Primes[1] = big.NewInt(0)
-				p.Primes[1].SetBytes(v1)
+				p.Primes[1] = new(big.Int).SetBytes(v1)
 			}
 		case "exponent1", "exponent2", "coefficient":
 			// not used in Go (yet)
@@ -134,27 +105,9 @@ 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 = big.NewInt(0)
-	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 = big.NewInt(0)
+	p.D = new(big.Int)
 	// TODO: validate that the required flags are present
 	for k, v := range m {
 		switch k {
@@ -322,6 +275,11 @@ func (kl *klexer) Next() (lex, bool) {
 				commt = false
 			}
 
+			if kl.key && str.Len() == 0 {
+				// ignore empty lines
+				break
+			}
+
 			kl.key = true
 
 			l.value = zValue
diff --git a/vendor/github.com/miekg/dns/dnssec_privkey.go b/vendor/github.com/miekg/dns/dnssec_privkey.go
index 0c65be17..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"
@@ -13,10 +12,12 @@ import (
 
 const format = "Private-key-format: v1.3\n"
 
+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] + ")"
@@ -31,12 +32,11 @@ func (r *DNSKEY) PrivateKeyString(p crypto.PrivateKey) string {
 		prime2 := toBase64(p.Primes[1].Bytes())
 		// Calculate Exponent1/2 and Coefficient as per: http://en.wikipedia.org/wiki/RSA#Using_the_Chinese_remainder_algorithm
 		// and from: http://code.google.com/p/go/issues/detail?id=987
-		one := big.NewInt(1)
-		p1 := big.NewInt(0).Sub(p.Primes[0], one)
-		q1 := big.NewInt(0).Sub(p.Primes[1], one)
-		exp1 := big.NewInt(0).Mod(p.D, p1)
-		exp2 := big.NewInt(0).Mod(p.D, q1)
-		coeff := big.NewInt(0).ModInverse(p.Primes[1], p.Primes[0])
+		p1 := new(big.Int).Sub(p.Primes[0], bigIntOne)
+		q1 := new(big.Int).Sub(p.Primes[1], bigIntOne)
+		exp1 := new(big.Int).Mod(p.D, p1)
+		exp2 := new(big.Int).Mod(p.D, q1)
+		coeff := new(big.Int).ModInverse(p.Primes[1], p.Primes[0])
 
 		exponent1 := toBase64(exp1.Bytes())
 		exponent2 := toBase64(exp2.Bytes())
@@ -66,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 0389d724..6861de77 100644
--- a/vendor/github.com/miekg/dns/doc.go
+++ b/vendor/github.com/miekg/dns/doc.go
@@ -1,20 +1,20 @@
 /*
 Package dns implements a full featured interface to the Domain Name System.
-Server- and client-side programming is supported.
-The package allows complete control over what is sent out to the DNS. The package
-API follows the less-is-more principle, by presenting a small, clean interface.
+Both server- and client-side programming is supported. The package allows
+complete control over what is sent out to the DNS. The API follows the
+less-is-more principle, by presenting a small, clean interface.
 
-The package dns supports (asynchronous) querying/replying, incoming/outgoing zone transfers,
+It supports (asynchronous) querying/replying, incoming/outgoing zone transfers,
 TSIG, EDNS0, dynamic updates, notifies and DNSSEC validation/signing.
-Note that domain names MUST be fully qualified, before sending them, unqualified
+
+Note that domain names MUST be fully qualified before sending them, unqualified
 names in a message will result in a packing failure.
 
-Resource records are native types. They are not stored in wire format.
-Basic usage pattern for creating a new resource record:
+Resource records are native types. They are not stored in wire format. Basic
+usage pattern for creating a new resource record:
 
      r := new(dns.MX)
-     r.Hdr = dns.RR_Header{Name: "miek.nl.", Rrtype: dns.TypeMX,
-     Class: dns.ClassINET, Ttl: 3600}
+     r.Hdr = dns.RR_Header{Name: "miek.nl.", Rrtype: dns.TypeMX, Class: dns.ClassINET, Ttl: 3600}
      r.Preference = 10
      r.Mx = "mx.miek.nl."
 
@@ -30,8 +30,8 @@ Or even:
 
      mx, err := dns.NewRR("$ORIGIN nl.\nmiek 1H IN MX 10 mx.miek")
 
-In the DNS messages are exchanged, these messages contain resource
-records (sets). Use pattern for creating a message:
+In the DNS messages are exchanged, these messages contain resource records
+(sets). Use pattern for creating a message:
 
      m := new(dns.Msg)
      m.SetQuestion("miek.nl.", dns.TypeMX)
@@ -40,8 +40,8 @@ Or when not certain if the domain name is fully qualified:
 
 	m.SetQuestion(dns.Fqdn("miek.nl"), dns.TypeMX)
 
-The message m is now a message with the question section set to ask
-the MX records for the miek.nl. zone.
+The message m is now a message with the question section set to ask the MX
+records for the miek.nl. zone.
 
 The following is slightly more verbose, but more flexible:
 
@@ -51,9 +51,8 @@ The following is slightly more verbose, but more flexible:
      m1.Question = make([]dns.Question, 1)
      m1.Question[0] = dns.Question{"miek.nl.", dns.TypeMX, dns.ClassINET}
 
-After creating a message it can be sent.
-Basic use pattern for synchronous querying the DNS at a
-server configured on 127.0.0.1 and port 53:
+After creating a message it can be sent. Basic use pattern for synchronous
+querying the DNS at a server configured on 127.0.0.1 and port 53:
 
      c := new(dns.Client)
      in, rtt, err := c.Exchange(m1, "127.0.0.1:53")
@@ -84,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.
@@ -99,25 +98,24 @@ the Answer section:
 
 Domain Name and TXT Character String Representations
 
-Both domain names and TXT character strings are converted to presentation
-form both when unpacked and when converted to strings.
+Both domain names and TXT character strings are converted to presentation form
+both when unpacked and when converted to strings.
 
 For TXT character strings, tabs, carriage returns and line feeds will be
-converted to \t, \r and \n respectively. Back slashes and quotations marks
-will be escaped. Bytes below 32 and above 127 will be converted to \DDD
-form.
+converted to \t, \r and \n respectively. Back slashes and quotations marks will
+be escaped. Bytes below 32 and above 127 will be converted to \DDD form.
 
-For domain names, in addition to the above rules brackets, periods,
-spaces, semicolons and the at symbol are escaped.
+For domain names, in addition to the above rules brackets, periods, spaces,
+semicolons and the at symbol are escaped.
 
 DNSSEC
 
-DNSSEC (DNS Security Extension) adds a layer of security to the DNS. It
-uses public key cryptography to sign resource records. The
-public keys are stored in DNSKEY records and the signatures in RRSIG records.
+DNSSEC (DNS Security Extension) adds a layer of security to the DNS. It uses
+public key cryptography to sign resource records. The public keys are stored in
+DNSKEY records and the signatures in RRSIG records.
 
-Requesting DNSSEC information for a zone is done by adding the DO (DNSSEC OK) bit
-to a request.
+Requesting DNSSEC information for a zone is done by adding the DO (DNSSEC OK)
+bit to a request.
 
      m := new(dns.Msg)
      m.SetEdns0(4096, true)
@@ -126,9 +124,9 @@ Signature generation, signature verification and key generation are all supporte
 
 DYNAMIC UPDATES
 
-Dynamic updates reuses the DNS message format, but renames three of
-the sections. Question is Zone, Answer is Prerequisite, Authority is
-Update, only the Additional is not renamed. See RFC 2136 for the gory details.
+Dynamic updates reuses the DNS message format, but renames three of the
+sections. Question is Zone, Answer is Prerequisite, Authority is Update, only
+the Additional is not renamed. See RFC 2136 for the gory details.
 
 You can set a rather complex set of rules for the existence of absence of
 certain resource records or names in a zone to specify if resource records
@@ -145,10 +143,9 @@ DNS function shows which functions exist to specify the prerequisites.
   NONE     rrset    empty    RRset does not exist       dns.RRsetNotUsed
   zone     rrset    rr       RRset exists (value dep)   dns.Used
 
-The prerequisite section can also be left empty.
-If you have decided on the prerequisites you can tell what RRs should
-be added or deleted. The next table shows the options you have and
-what functions to call.
+The prerequisite section can also be left empty. If you have decided on the
+prerequisites you can tell what RRs should be added or deleted. The next table
+shows the options you have and what functions to call.
 
  3.4.2.6 - Table Of Metavalues Used In Update Section
 
@@ -181,10 +178,10 @@ changes to the RRset after calling SetTsig() the signature will be incorrect.
 	...
 	// When sending the TSIG RR is calculated and filled in before sending
 
-When requesting an zone transfer (almost all TSIG usage is when requesting zone transfers), with
-TSIG, this is the basic use pattern. In this example we request an AXFR for
-miek.nl. with TSIG key named "axfr." and secret "so6ZGir4GPAqINNh9U5c3A=="
-and using the server 176.58.119.54:
+When requesting an zone transfer (almost all TSIG usage is when requesting zone
+transfers), with TSIG, this is the basic use pattern. In this example we
+request an AXFR for miek.nl. with TSIG key named "axfr." and secret
+"so6ZGir4GPAqINNh9U5c3A==" and using the server 176.58.119.54:
 
 	t := new(dns.Transfer)
 	m := new(dns.Msg)
@@ -194,8 +191,8 @@ and using the server 176.58.119.54:
 	c, err := t.In(m, "176.58.119.54:53")
 	for r := range c { ... }
 
-You can now read the records from the transfer as they come in. Each envelope is checked with TSIG.
-If something is not correct an error is returned.
+You can now read the records from the transfer as they come in. Each envelope
+is checked with TSIG. If something is not correct an error is returned.
 
 Basic use pattern validating and replying to a message that has TSIG set.
 
@@ -212,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)
@@ -220,28 +217,28 @@ Basic use pattern validating and replying to a message that has TSIG set.
 
 PRIVATE RRS
 
-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
+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 http://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
 
-EDNS0 is an extension mechanism for the DNS defined in RFC 2671 and updated
-by RFC 6891. It defines an new RR type, the OPT RR, which is then completely
+EDNS0 is an extension mechanism for the DNS defined in RFC 2671 and updated by
+RFC 6891. It defines an new RR type, the OPT RR, which is then completely
 abused.
+
 Basic use pattern for creating an (empty) OPT RR:
 
 	o := new(dns.OPT)
 	o.Hdr.Name = "." // MUST be the root zone, per definition.
 	o.Hdr.Rrtype = dns.TypeOPT
 
-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.
+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 (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
@@ -262,10 +259,9 @@ From RFC 2931:
     ... protection for glue records, DNS requests, protection for message headers
     on requests and responses, and protection of the overall integrity of a response.
 
-It works like TSIG, except that SIG(0) uses public key cryptography, instead of the shared
-secret approach in TSIG.
-Supported algorithms: DSA, ECDSAP256SHA256, ECDSAP384SHA384, RSASHA1, RSASHA256 and
-RSASHA512.
+It works like TSIG, except that SIG(0) uses public key cryptography, instead of
+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 6372e8a1..d21ae1ca 100644
--- a/vendor/github.com/miekg/dns/duplicate.go
+++ b/vendor/github.com/miekg/dns/duplicate.go
@@ -3,23 +3,35 @@ 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 {
-	if r1.Header().Class != r2.Header().Class {
+	// Check whether the record header is identical.
+	if !r1.Header().isDuplicate(r2.Header()) {
 		return false
 	}
-	if r1.Header().Rrtype != r2.Header().Rrtype {
+
+	// Check whether the RDATA is identical.
+	return r1.isDuplicate(r2)
+}
+
+func (r1 *RR_Header) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*RR_Header)
+	if !ok {
+		return false
+	}
+	if r1.Class != r2.Class {
+		return false
+	}
+	if r1.Rrtype != r2.Rrtype {
 		return false
 	}
-	if !isDulicateName(r1.Header().Name, r2.Header().Name) {
+	if !isDuplicateName(r1.Name, r2.Name) {
 		return false
 	}
 	// ignore TTL
-
-	return isDuplicateRdata(r1, r2)
+	return true
 }
 
-// isDulicateName checks if the domain names s1 and s2 are equal.
-func isDulicateName(s1, s2 string) bool { return equal(s1, s2) }
+// isDuplicateName checks if the domain names s1 and s2 are equal.
+func isDuplicateName(s1, s2 string) bool { return equal(s1, s2) }
diff --git a/vendor/github.com/miekg/dns/edns.go b/vendor/github.com/miekg/dns/edns.go
index 18d05413..04808d57 100644
--- a/vendor/github.com/miekg/dns/edns.go
+++ b/vendor/github.com/miekg/dns/edns.go
@@ -78,16 +78,22 @@ func (rr *OPT) String() string {
 	return s
 }
 
-func (rr *OPT) len() int {
-	l := rr.Hdr.len()
-	for i := 0; i < len(rr.Option); i++ {
+func (rr *OPT) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	for _, o := range rr.Option {
 		l += 4 // Account for 2-byte option code and 2-byte option length.
-		lo, _ := rr.Option[i].pack()
+		lo, _ := o.pack()
 		l += len(lo)
 	}
 	return l
 }
 
+func (rr *OPT) parse(c *zlexer, origin string) *ParseError {
+	panic("dns: internal error: parse should never be called on OPT")
+}
+
+func (r1 *OPT) isDuplicate(r2 RR) bool { return false }
+
 // return the old value -> delete SetVersion?
 
 // Version returns the EDNS version used. Only zero is defined.
@@ -102,15 +108,14 @@ func (rr *OPT) SetVersion(v uint8) {
 
 // ExtendedRcode returns the EDNS extended RCODE field (the upper 8 bits of the TTL).
 func (rr *OPT) ExtendedRcode() int {
-	return int(rr.Hdr.Ttl&0xFF000000>>24) + 15
+	return int(rr.Hdr.Ttl&0xFF000000>>24) << 4
 }
 
 // SetExtendedRcode sets the EDNS extended RCODE field.
-func (rr *OPT) SetExtendedRcode(v uint8) {
-	if v < RcodeBadVers { // Smaller than 16.. Use the 4 bits you have!
-		return
-	}
-	rr.Hdr.Ttl = rr.Hdr.Ttl&0x00FFFFFF | uint32(v-15)<<24
+//
+// If the RCODE is not an extended RCODE, will reset the extended RCODE field to 0.
+func (rr *OPT) SetExtendedRcode(v uint16) {
+	rr.Hdr.Ttl = rr.Hdr.Ttl&0x00FFFFFF | uint32(v>>4)<<24
 }
 
 // UDPSize returns the UDP buffer size.
@@ -154,6 +159,8 @@ type EDNS0 interface {
 	unpack([]byte) error
 	// String returns the string representation of the option.
 	String() string
+	// copy returns a deep-copy of the option.
+	copy() EDNS0
 }
 
 // EDNS0_NSID option is used to retrieve a nameserver
@@ -184,7 +191,8 @@ func (e *EDNS0_NSID) pack() ([]byte, error) {
 // Option implements the EDNS0 interface.
 func (e *EDNS0_NSID) Option() uint16        { return EDNS0NSID } // Option returns the option code.
 func (e *EDNS0_NSID) unpack(b []byte) error { e.Nsid = hex.EncodeToString(b); return nil }
-func (e *EDNS0_NSID) String() string        { return string(e.Nsid) }
+func (e *EDNS0_NSID) String() string        { return e.Nsid }
+func (e *EDNS0_NSID) copy() EDNS0           { return &EDNS0_NSID{e.Code, e.Nsid} }
 
 // EDNS0_SUBNET is the subnet option that is used to give the remote nameserver
 // an idea of where the client lives. See RFC 7871. It can then give back a different
@@ -274,22 +282,16 @@ func (e *EDNS0_SUBNET) unpack(b []byte) error {
 		if e.SourceNetmask > net.IPv4len*8 || e.SourceScope > net.IPv4len*8 {
 			return errors.New("dns: bad netmask")
 		}
-		addr := make([]byte, net.IPv4len)
-		for i := 0; i < net.IPv4len && 4+i < len(b); i++ {
-			addr[i] = b[4+i]
-		}
-		e.Address = net.IPv4(addr[0], addr[1], addr[2], addr[3])
+		addr := make(net.IP, net.IPv4len)
+		copy(addr, b[4:])
+		e.Address = addr.To16()
 	case 2:
 		if e.SourceNetmask > net.IPv6len*8 || e.SourceScope > net.IPv6len*8 {
 			return errors.New("dns: bad netmask")
 		}
-		addr := make([]byte, net.IPv6len)
-		for i := 0; i < net.IPv6len && 4+i < len(b); i++ {
-			addr[i] = b[4+i]
-		}
-		e.Address = net.IP{addr[0], addr[1], addr[2], addr[3], addr[4],
-			addr[5], addr[6], addr[7], addr[8], addr[9], addr[10],
-			addr[11], addr[12], addr[13], addr[14], addr[15]}
+		addr := make(net.IP, net.IPv6len)
+		copy(addr, b[4:])
+		e.Address = addr
 	default:
 		return errors.New("dns: bad address family")
 	}
@@ -308,6 +310,16 @@ func (e *EDNS0_SUBNET) String() (s string) {
 	return
 }
 
+func (e *EDNS0_SUBNET) copy() EDNS0 {
+	return &EDNS0_SUBNET{
+		e.Code,
+		e.Family,
+		e.SourceNetmask,
+		e.SourceScope,
+		e.Address,
+	}
+}
+
 // The EDNS0_COOKIE option is used to add a DNS Cookie to a message.
 //
 //	o := new(dns.OPT)
@@ -343,11 +355,12 @@ func (e *EDNS0_COOKIE) pack() ([]byte, error) {
 func (e *EDNS0_COOKIE) Option() uint16        { return EDNS0COOKIE }
 func (e *EDNS0_COOKIE) unpack(b []byte) error { e.Cookie = hex.EncodeToString(b); return nil }
 func (e *EDNS0_COOKIE) String() string        { return e.Cookie }
+func (e *EDNS0_COOKIE) copy() EDNS0           { return &EDNS0_COOKIE{e.Code, e.Cookie} }
 
 // 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 = "."
@@ -357,23 +370,36 @@ func (e *EDNS0_COOKIE) String() string        { return e.Cookie }
 //	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) 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)
@@ -418,10 +444,13 @@ func (e *EDNS0_LLQ) unpack(b []byte) error {
 
 func (e *EDNS0_LLQ) String() string {
 	s := strconv.FormatUint(uint64(e.Version), 10) + " " + strconv.FormatUint(uint64(e.Opcode), 10) +
-		" " + strconv.FormatUint(uint64(e.Error), 10) + " " + strconv.FormatUint(uint64(e.Id), 10) +
+		" " + strconv.FormatUint(uint64(e.Error), 10) + " " + strconv.FormatUint(e.Id, 10) +
 		" " + strconv.FormatUint(uint64(e.LeaseLife), 10)
 	return s
 }
+func (e *EDNS0_LLQ) copy() EDNS0 {
+	return &EDNS0_LLQ{e.Code, e.Version, e.Opcode, e.Error, e.Id, e.LeaseLife}
+}
 
 // EDNS0_DUA implements the EDNS0 "DNSSEC Algorithm Understood" option. See RFC 6975.
 type EDNS0_DAU struct {
@@ -436,15 +465,16 @@ func (e *EDNS0_DAU) unpack(b []byte) error { e.AlgCode = b; return nil }
 
 func (e *EDNS0_DAU) String() string {
 	s := ""
-	for i := 0; i < len(e.AlgCode); i++ {
-		if a, ok := AlgorithmToString[e.AlgCode[i]]; ok {
+	for _, alg := range e.AlgCode {
+		if a, ok := AlgorithmToString[alg]; ok {
 			s += " " + a
 		} else {
-			s += " " + strconv.Itoa(int(e.AlgCode[i]))
+			s += " " + strconv.Itoa(int(alg))
 		}
 	}
 	return s
 }
+func (e *EDNS0_DAU) copy() EDNS0 { return &EDNS0_DAU{e.Code, e.AlgCode} }
 
 // EDNS0_DHU implements the EDNS0 "DS Hash Understood" option. See RFC 6975.
 type EDNS0_DHU struct {
@@ -459,15 +489,16 @@ func (e *EDNS0_DHU) unpack(b []byte) error { e.AlgCode = b; return nil }
 
 func (e *EDNS0_DHU) String() string {
 	s := ""
-	for i := 0; i < len(e.AlgCode); i++ {
-		if a, ok := HashToString[e.AlgCode[i]]; ok {
+	for _, alg := range e.AlgCode {
+		if a, ok := HashToString[alg]; ok {
 			s += " " + a
 		} else {
-			s += " " + strconv.Itoa(int(e.AlgCode[i]))
+			s += " " + strconv.Itoa(int(alg))
 		}
 	}
 	return s
 }
+func (e *EDNS0_DHU) copy() EDNS0 { return &EDNS0_DHU{e.Code, e.AlgCode} }
 
 // EDNS0_N3U implements the EDNS0 "NSEC3 Hash Understood" option. See RFC 6975.
 type EDNS0_N3U struct {
@@ -483,15 +514,16 @@ func (e *EDNS0_N3U) unpack(b []byte) error { e.AlgCode = b; return nil }
 func (e *EDNS0_N3U) String() string {
 	// Re-use the hash map
 	s := ""
-	for i := 0; i < len(e.AlgCode); i++ {
-		if a, ok := HashToString[e.AlgCode[i]]; ok {
+	for _, alg := range e.AlgCode {
+		if a, ok := HashToString[alg]; ok {
 			s += " " + a
 		} else {
-			s += " " + strconv.Itoa(int(e.AlgCode[i]))
+			s += " " + strconv.Itoa(int(alg))
 		}
 	}
 	return s
 }
+func (e *EDNS0_N3U) copy() EDNS0 { return &EDNS0_N3U{e.Code, e.AlgCode} }
 
 // EDNS0_EXPIRE implementes the EDNS0 option as described in RFC 7314.
 type EDNS0_EXPIRE struct {
@@ -502,17 +534,19 @@ type EDNS0_EXPIRE struct {
 // Option implements the EDNS0 interface.
 func (e *EDNS0_EXPIRE) Option() uint16 { return EDNS0EXPIRE }
 func (e *EDNS0_EXPIRE) String() string { return strconv.FormatUint(uint64(e.Expire), 10) }
+func (e *EDNS0_EXPIRE) copy() EDNS0    { return &EDNS0_EXPIRE{e.Code, e.Expire} }
 
 func (e *EDNS0_EXPIRE) pack() ([]byte, error) {
 	b := make([]byte, 4)
-	b[0] = byte(e.Expire >> 24)
-	b[1] = byte(e.Expire >> 16)
-	b[2] = byte(e.Expire >> 8)
-	b[3] = byte(e.Expire)
+	binary.BigEndian.PutUint32(b, e.Expire)
 	return b, nil
 }
 
 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
 	}
@@ -543,6 +577,11 @@ func (e *EDNS0_LOCAL) Option() uint16 { return e.Code }
 func (e *EDNS0_LOCAL) String() string {
 	return strconv.FormatInt(int64(e.Code), 10) + ":0x" + hex.EncodeToString(e.Data)
 }
+func (e *EDNS0_LOCAL) copy() EDNS0 {
+	b := make([]byte, len(e.Data))
+	copy(b, e.Data)
+	return &EDNS0_LOCAL{e.Code, b}
+}
 
 func (e *EDNS0_LOCAL) pack() ([]byte, error) {
 	b := make([]byte, len(e.Data))
@@ -615,6 +654,7 @@ func (e *EDNS0_TCP_KEEPALIVE) String() (s string) {
 	}
 	return
 }
+func (e *EDNS0_TCP_KEEPALIVE) copy() EDNS0 { return &EDNS0_TCP_KEEPALIVE{e.Code, e.Length, e.Timeout} }
 
 // EDNS0_PADDING option is used to add padding to a request/response. The default
 // value of padding SHOULD be 0x0 but other values MAY be used, for instance if
@@ -628,3 +668,8 @@ func (e *EDNS0_PADDING) Option() uint16        { return EDNS0PADDING }
 func (e *EDNS0_PADDING) pack() ([]byte, error) { return e.Padding, nil }
 func (e *EDNS0_PADDING) unpack(b []byte) error { e.Padding = b; return nil }
 func (e *EDNS0_PADDING) String() string        { return fmt.Sprintf("%0X", e.Padding) }
+func (e *EDNS0_PADDING) copy() EDNS0 {
+	b := make([]byte, len(e.Padding))
+	copy(b, e.Padding)
+	return &EDNS0_PADDING{b}
+}
diff --git a/vendor/github.com/miekg/dns/format.go b/vendor/github.com/miekg/dns/format.go
index 3f5303c2..0ec79f2f 100644
--- a/vendor/github.com/miekg/dns/format.go
+++ b/vendor/github.com/miekg/dns/format.go
@@ -20,7 +20,7 @@ func Field(r RR, i int) string {
 		return ""
 	}
 	d := reflect.ValueOf(r).Elem().Field(i)
-	switch k := d.Kind(); k {
+	switch d.Kind() {
 	case reflect.String:
 		return d.String()
 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
@@ -31,6 +31,9 @@ func Field(r RR, i int) string {
 		switch reflect.ValueOf(r).Elem().Type().Field(i).Tag {
 		case `dns:"a"`:
 			// TODO(miek): Hmm store this as 16 bytes
+			if d.Len() < net.IPv4len {
+				return ""
+			}
 			if d.Len() < net.IPv6len {
 				return net.IPv4(byte(d.Index(0).Uint()),
 					byte(d.Index(1).Uint()),
@@ -42,6 +45,9 @@ func Field(r RR, i int) string {
 				byte(d.Index(14).Uint()),
 				byte(d.Index(15).Uint())).String()
 		case `dns:"aaaa"`:
+			if d.Len() < net.IPv6len {
+				return ""
+			}
 			return net.IP{
 				byte(d.Index(0).Uint()),
 				byte(d.Index(1).Uint()),
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 577fc59d..df1675df 100644
--- a/vendor/github.com/miekg/dns/labels.go
+++ b/vendor/github.com/miekg/dns/labels.go
@@ -16,7 +16,7 @@ func SplitDomainName(s string) (labels []string) {
 	fqdnEnd := 0 // offset of the final '.' or the length of the name
 	idx := Split(s)
 	begin := 0
-	if s[len(s)-1] == '.' {
+	if IsFqdn(s) {
 		fqdnEnd = len(s) - 1
 	} else {
 		fqdnEnd = len(s)
@@ -28,16 +28,13 @@ func SplitDomainName(s string) (labels []string) {
 	case 1:
 		// no-op
 	default:
-		end := 0
-		for i := 1; i < len(idx); i++ {
-			end = idx[i]
+		for _, end := range idx[1:] {
 			labels = append(labels, s[begin:end-1])
 			begin = end
 		}
 	}
 
-	labels = append(labels, s[begin:fqdnEnd])
-	return labels
+	return append(labels, s[begin:fqdnEnd])
 }
 
 // CompareDomainName compares the names s1 and s2 and
@@ -86,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 == "." {
@@ -129,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
 }
@@ -152,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 47ac6cf2..7001f6da 100644
--- a/vendor/github.com/miekg/dns/msg.go
+++ b/vendor/github.com/miekg/dns/msg.go
@@ -9,21 +9,41 @@
 package dns
 
 //go:generate go run msg_generate.go
-//go:generate go run compress_generate.go
 
 import (
-	crand "crypto/rand"
+	"crypto/rand"
 	"encoding/binary"
 	"fmt"
 	"math/big"
-	"math/rand"
 	"strconv"
-	"sync"
+	"strings"
 )
 
 const (
 	maxCompressionOffset    = 2 << 13 // We have 14 bits for the compression pointer
 	maxDomainNameWireOctets = 255     // See RFC 1035 section 2.3.4
+
+	// This is the maximum number of compression pointers that should occur in a
+	// semantically valid message. Each label in a domain name must be at least one
+	// octet and is separated by a period. The root label won't be represented by a
+	// compression pointer to a compression pointer, hence the -2 to exclude the
+	// smallest valid root label.
+	//
+	// It is possible to construct a valid message that has more compression pointers
+	// than this, and still doesn't loop, by pointing to a previous pointer. This is
+	// not something a well written implementation should ever do, so we leave them
+	// to trip the maximum compression pointer check.
+	maxCompressionPointers = (maxDomainNameWireOctets+1)/2 - 2
+
+	// This is the maximum length of a domain name in presentation format. The
+	// maximum wire length of a domain name is 255 octets (see above), with the
+	// maximum label length being 63. The wire format requires one extra byte over
+	// the presentation format, reducing the number of octets by 1. Each label in
+	// the name will be separated by a single period, with each octet in the label
+	// expanding to at most 4 bytes (\DDD). If all other labels are of the maximum
+	// length, then the final label can only be 61 octets long to not exceed the
+	// maximum allowed wire length.
+	maxDomainNamePresentationLength = 61*4 + 1 + 63*4 + 1 + 63*4 + 1 + 63*4 + 1
 )
 
 // Errors defined in this package.
@@ -46,59 +66,28 @@ var (
 	ErrRRset         error = &Error{err: "bad rrset"}
 	ErrSecret        error = &Error{err: "no secrets defined"}
 	ErrShortRead     error = &Error{err: "short read"}
-	ErrSig           error = &Error{err: "bad signature"}                      // ErrSig indicates that a signature can not be cryptographically validated.
-	ErrSoa           error = &Error{err: "no SOA"}                             // ErrSOA indicates that no SOA RR was seen when doing zone transfers.
-	ErrTime          error = &Error{err: "bad time"}                           // ErrTime indicates a timing error in TSIG authentication.
-	ErrTruncated     error = &Error{err: "failed to unpack truncated message"} // ErrTruncated indicates that we failed to unpack a truncated message. We unpacked as much as we had so Msg can still be used, if desired.
+	ErrSig           error = &Error{err: "bad signature"} // ErrSig indicates that a signature can not be cryptographically validated.
+	ErrSoa           error = &Error{err: "no SOA"}        // ErrSOA indicates that no SOA RR was seen when doing zone transfers.
+	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).
@@ -151,7 +140,7 @@ var RcodeToString = map[int]string{
 	RcodeFormatError:    "FORMERR",
 	RcodeServerFailure:  "SERVFAIL",
 	RcodeNameError:      "NXDOMAIN",
-	RcodeNotImplemented: "NOTIMPL",
+	RcodeNotImplemented: "NOTIMP",
 	RcodeRefused:        "REFUSED",
 	RcodeYXDomain:       "YXDOMAIN", // See RFC 2136
 	RcodeYXRrset:        "YXRRSET",
@@ -169,6 +158,39 @@ var RcodeToString = map[int]string{
 	RcodeBadCookie: "BADCOOKIE",
 }
 
+// compressionMap is used to allow a more efficient compression map
+// to be used for internal packDomainName calls without changing the
+// signature or functionality of public API.
+//
+// In particular, map[string]uint16 uses 25% less per-entry memory
+// than does map[string]int.
+type compressionMap struct {
+	ext map[string]int    // external callers
+	int map[string]uint16 // internal callers
+}
+
+func (m compressionMap) valid() bool {
+	return m.int != nil || m.ext != nil
+}
+
+func (m compressionMap) insert(s string, pos int) {
+	if m.ext != nil {
+		m.ext[s] = pos
+	} else {
+		m.int[s] = uint16(pos)
+	}
+}
+
+func (m compressionMap) find(s string) (int, bool) {
+	if m.ext != nil {
+		pos, ok := m.ext[s]
+		return pos, ok
+	}
+
+	pos, ok := m.int[s]
+	return int(pos), ok
+}
+
 // Domain names are a sequence of counted strings
 // split at the dots. They end with a zero-length string.
 
@@ -177,149 +199,156 @@ var RcodeToString = map[int]string{
 // map needs to hold a mapping between domain names and offsets
 // pointing into msg.
 func PackDomainName(s string, msg []byte, off int, compression map[string]int, compress bool) (off1 int, err error) {
-	off1, _, err = packDomainName(s, msg, off, compression, compress)
-	return
+	return packDomainName(s, msg, off, compressionMap{ext: compression}, compress)
 }
 
-func packDomainName(s string, msg []byte, off int, compression map[string]int, compress bool) (off1 int, labels int, err error) {
-	// special case if msg == nil
-	lenmsg := 256
-	if msg != nil {
-		lenmsg = len(msg)
-	}
+func packDomainName(s string, msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
+	// XXX: A logical copy of this function exists in IsDomainName and
+	// should be kept in sync with this function.
+
 	ls := len(s)
 	if ls == 0 { // Ok, for instance when dealing with update RR without any rdata.
-		return off, 0, nil
-	}
-	// If not fully qualified, error out, but only if msg == nil #ugly
-	switch {
-	case msg == nil:
-		if s[ls-1] != '.' {
-			s += "."
-			ls++
-		}
-	case msg != nil:
-		if s[ls-1] != '.' {
-			return lenmsg, 0, ErrFqdn
-		}
+		return off, nil
 	}
+
+	// If not fully qualified, error out.
+	if !IsFqdn(s) {
+		return len(msg), ErrFqdn
+	}
+
 	// Each dot ends a segment of the name.
 	// We trade each dot byte for a length byte.
 	// Except for escaped dots (\.), which are normal dots.
 	// There is also a trailing zero.
 
 	// Compression
-	nameoffset := -1
 	pointer := -1
+
 	// Emit sequence of counted strings, chopping at dots.
-	begin := 0
-	bs := []byte(s)
-	roBs, bsFresh, escapedDot := s, true, false
+	var (
+		begin     int
+		compBegin int
+		compOff   int
+		bs        []byte
+		wasDot    bool
+	)
+loop:
 	for i := 0; i < ls; i++ {
-		if bs[i] == '\\' {
-			for j := i; j < ls-1; j++ {
-				bs[j] = bs[j+1]
+		var c byte
+		if bs == nil {
+			c = s[i]
+		} else {
+			c = bs[i]
+		}
+
+		switch c {
+		case '\\':
+			if off+1 > len(msg) {
+				return len(msg), ErrBuf
 			}
-			ls--
-			if off+1 > lenmsg {
-				return lenmsg, labels, ErrBuf
+
+			if bs == nil {
+				bs = []byte(s)
 			}
+
 			// check for \DDD
-			if i+2 < ls && isDigit(bs[i]) && isDigit(bs[i+1]) && isDigit(bs[i+2]) {
-				bs[i] = dddToByte(bs[i:])
-				for j := i + 1; j < ls-2; j++ {
-					bs[j] = bs[j+2]
-				}
-				ls -= 2
+			if i+3 < ls && isDigit(bs[i+1]) && isDigit(bs[i+2]) && isDigit(bs[i+3]) {
+				bs[i] = dddToByte(bs[i+1:])
+				copy(bs[i+1:ls-3], bs[i+4:])
+				ls -= 3
+				compOff += 3
+			} else {
+				copy(bs[i:ls-1], bs[i+1:])
+				ls--
+				compOff++
 			}
-			escapedDot = bs[i] == '.'
-			bsFresh = false
-			continue
-		}
 
-		if bs[i] == '.' {
-			if i > 0 && bs[i-1] == '.' && !escapedDot {
+			wasDot = false
+		case '.':
+			if wasDot {
 				// two dots back to back is not legal
-				return lenmsg, labels, ErrRdata
+				return len(msg), ErrRdata
 			}
-			if i-begin >= 1<<6 { // top two bits of length must be clear
-				return lenmsg, labels, ErrRdata
+			wasDot = true
+
+			labelLen := i - begin
+			if labelLen >= 1<<6 { // top two bits of length must be clear
+				return len(msg), ErrRdata
 			}
+
 			// off can already (we're in a loop) be bigger than len(msg)
 			// this happens when a name isn't fully qualified
-			if off+1 > lenmsg {
-				return lenmsg, labels, ErrBuf
-			}
-			if msg != nil {
-				msg[off] = byte(i - begin)
-			}
-			offset := off
-			off++
-			for j := begin; j < i; j++ {
-				if off+1 > lenmsg {
-					return lenmsg, labels, ErrBuf
-				}
-				if msg != nil {
-					msg[off] = bs[j]
-				}
-				off++
-			}
-			if compress && !bsFresh {
-				roBs = string(bs)
-				bsFresh = true
+			if off+1+labelLen > len(msg) {
+				return len(msg), ErrBuf
 			}
+
 			// Don't try to compress '.'
-			// We should only compress when compress it true, but we should also still pick
+			// We should only compress when compress is true, but we should also still pick
 			// up names that can be used for *future* compression(s).
-			if compression != nil && roBs[begin:] != "." {
-				if p, ok := compression[roBs[begin:]]; !ok {
-					// Only offsets smaller than this can be used.
-					if offset < maxCompressionOffset {
-						compression[roBs[begin:]] = offset
-					}
-				} else {
+			if compression.valid() && !isRootLabel(s, bs, begin, ls) {
+				if p, ok := compression.find(s[compBegin:]); ok {
 					// The first hit is the longest matching dname
 					// keep the pointer offset we get back and store
 					// the offset of the current name, because that's
 					// where we need to insert the pointer later
 
 					// If compress is true, we're allowed to compress this dname
-					if pointer == -1 && compress {
-						pointer = p         // Where to point to
-						nameoffset = offset // Where to point from
-						break
+					if compress {
+						pointer = p // Where to point to
+						break loop
 					}
+				} else if off < maxCompressionOffset {
+					// Only offsets smaller than maxCompressionOffset can be used.
+					compression.insert(s[compBegin:], off)
 				}
 			}
-			labels++
+
+			// The following is covered by the length check above.
+			msg[off] = byte(labelLen)
+
+			if bs == nil {
+				copy(msg[off+1:], s[begin:i])
+			} else {
+				copy(msg[off+1:], bs[begin:i])
+			}
+			off += 1 + labelLen
+
 			begin = i + 1
+			compBegin = begin + compOff
+		default:
+			wasDot = false
 		}
-		escapedDot = false
 	}
+
 	// Root label is special
-	if len(bs) == 1 && bs[0] == '.' {
-		return off, labels, nil
+	if isRootLabel(s, bs, 0, ls) {
+		return off, nil
 	}
+
 	// If we did compression and we find something add the pointer here
 	if pointer != -1 {
-		// Clear the msg buffer after the pointer location, otherwise
-		// packDataNsec writes the wrong data to msg.
-		tainted := msg[nameoffset:off]
-		for i := range tainted {
-			tainted[i] = 0
-		}
 		// We have two bytes (14 bits) to put the pointer in
-		// if msg == nil, we will never do compression
-		binary.BigEndian.PutUint16(msg[nameoffset:], uint16(pointer^0xC000))
-		off = nameoffset + 1
-		goto End
+		binary.BigEndian.PutUint16(msg[off:], uint16(pointer^0xC000))
+		return off + 2, nil
 	}
-	if msg != nil && off < len(msg) {
+
+	if off < len(msg) {
 		msg[off] = 0
 	}
-End:
-	off++
-	return off, labels, nil
+
+	return off + 1, nil
+}
+
+// isRootLabel returns whether s or bs, from off to end, is the root
+// label ".".
+//
+// If bs is nil, s will be checked, otherwise bs will be checked.
+func isRootLabel(s string, bs []byte, off, end int) bool {
+	if bs == nil {
+		return s[off:end] == "."
+	}
+
+	return end-off == 1 && bs[off] == '.'
 }
 
 // Unpack a domain name.
@@ -336,12 +365,16 @@ End:
 // In theory, the pointers are only allowed to jump backward.
 // We let them jump anywhere and stop jumping after a while.
 
-// UnpackDomainName unpacks a domain name into a string.
+// UnpackDomainName unpacks a domain name into a string. It returns
+// the name, the new offset into msg and any error that occurred.
+//
+// When an error is encountered, the unpacked name will be discarded
+// and len(msg) will be returned as the offset.
 func UnpackDomainName(msg []byte, off int) (string, int, error) {
-	s := make([]byte, 0, 64)
+	s := make([]byte, 0, maxDomainNamePresentationLength)
 	off1 := 0
 	lenmsg := len(msg)
-	maxLen := maxDomainNameWireOctets
+	budget := maxDomainNameWireOctets
 	ptr := 0 // number of pointers followed
 Loop:
 	for {
@@ -360,28 +393,17 @@ Loop:
 			if off+c > lenmsg {
 				return "", lenmsg, ErrBuf
 			}
-			for j := off; j < off+c; j++ {
-				switch b := msg[j]; b {
-				case '.', '(', ')', ';', ' ', '@':
-					fallthrough
-				case '"', '\\':
+			budget -= c + 1 // +1 for the label separator
+			if budget <= 0 {
+				return "", lenmsg, ErrLongDomain
+			}
+			for _, b := range msg[off : off+c] {
+				if isDomainNameLabelSpecial(b) {
 					s = append(s, '\\', b)
-					// presentation-format \X escapes add an extra byte
-					maxLen++
-				default:
-					if b < 32 || b >= 127 { // unprintable, use \DDD
-						var buf [3]byte
-						bufs := strconv.AppendInt(buf[:0], int64(b), 10)
-						s = append(s, '\\')
-						for i := len(bufs); i < 3; i++ {
-							s = append(s, '0')
-						}
-						s = append(s, bufs...)
-						// presentation-format \DDD escapes add 3 extra bytes
-						maxLen += 3
-					} else {
-						s = append(s, b)
-					}
+				} else if b < ' ' || b > '~' {
+					s = append(s, escapeByte(b)...)
+				} else {
+					s = append(s, b)
 				}
 			}
 			s = append(s, '.')
@@ -400,7 +422,7 @@ Loop:
 			if ptr == 0 {
 				off1 = off
 			}
-			if ptr++; ptr > 10 {
+			if ptr++; ptr > maxCompressionPointers {
 				return "", lenmsg, &Error{err: "too many compression pointers"}
 			}
 			// pointer should guarantee that it advances and points forwards at least
@@ -416,10 +438,7 @@ Loop:
 		off1 = off
 	}
 	if len(s) == 0 {
-		s = []byte(".")
-	} else if len(s) >= maxLen {
-		// error if the name is too long, but don't throw it away
-		return string(s), lenmsg, ErrLongDomain
+		return ".", off1, nil
 	}
 	return string(s), off1, nil
 }
@@ -433,11 +452,11 @@ func packTxt(txt []string, msg []byte, offset int, tmp []byte) (int, error) {
 		return offset, nil
 	}
 	var err error
-	for i := range txt {
-		if len(txt[i]) > len(tmp) {
+	for _, s := range txt {
+		if len(s) > len(tmp) {
 			return offset, ErrBuf
 		}
-		offset, err = packTxtString(txt[i], msg, offset, tmp)
+		offset, err = packTxtString(s, msg, offset, tmp)
 		if err != nil {
 			return offset, err
 		}
@@ -528,10 +547,12 @@ func unpackTxt(msg []byte, off0 int) (ss []string, off int, err error) {
 func isDigit(b byte) bool { return b >= '0' && b <= '9' }
 
 func dddToByte(s []byte) byte {
+	_ = s[2] // bounds check hint to compiler; see golang.org/issue/14808
 	return byte((s[0]-'0')*100 + (s[1]-'0')*10 + (s[2] - '0'))
 }
 
 func dddStringToByte(s string) byte {
+	_ = s[2] // bounds check hint to compiler; see golang.org/issue/14808
 	return byte((s[0]-'0')*100 + (s[1]-'0')*10 + (s[2] - '0'))
 }
 
@@ -549,19 +570,38 @@ func intToBytes(i *big.Int, length int) []byte {
 // PackRR packs a resource record rr into msg[off:].
 // See PackDomainName for documentation about the compression.
 func PackRR(rr RR, msg []byte, off int, compression map[string]int, compress bool) (off1 int, err error) {
+	headerEnd, off1, err := packRR(rr, msg, off, compressionMap{ext: compression}, compress)
+	if err == nil {
+		// packRR no longer sets the Rdlength field on the rr, but
+		// callers might be expecting it so we set it here.
+		rr.Header().Rdlength = uint16(off1 - headerEnd)
+	}
+	return off1, err
+}
+
+func packRR(rr RR, msg []byte, off int, compression compressionMap, compress bool) (headerEnd int, off1 int, err error) {
 	if rr == nil {
-		return len(msg), &Error{err: "nil rr"}
+		return len(msg), len(msg), &Error{err: "nil rr"}
+	}
+
+	headerEnd, err = rr.Header().packHeader(msg, off, compression, compress)
+	if err != nil {
+		return headerEnd, len(msg), err
 	}
 
-	off1, err = rr.pack(msg, off, compression, compress)
+	off1, err = rr.pack(msg, headerEnd, compression, compress)
 	if err != nil {
-		return len(msg), err
+		return headerEnd, len(msg), err
 	}
-	// TODO(miek): Not sure if this is needed? If removed we can remove rawmsg.go as well.
-	if rawSetRdlength(msg, off, off1) {
-		return off1, nil
+
+	rdlength := off1 - headerEnd
+	if int(uint16(rdlength)) != rdlength { // overflow
+		return headerEnd, len(msg), ErrRdata
 	}
-	return off, ErrRdata
+
+	// The RDLENGTH field is the last field in the header and we set it here.
+	binary.BigEndian.PutUint16(msg[headerEnd-2:], uint16(rdlength))
+	return headerEnd, off1, nil
 }
 
 // UnpackRR unpacks msg[off:] into an RR.
@@ -577,17 +617,28 @@ func UnpackRR(msg []byte, off int) (rr RR, off1 int, err error) {
 // UnpackRRWithHeader unpacks the record type specific payload given an existing
 // RR_Header.
 func UnpackRRWithHeader(h RR_Header, msg []byte, off int) (rr RR, off1 int, err error) {
+	if newFn, ok := TypeToRR[h.Rrtype]; ok {
+		rr = newFn()
+		*rr.Header() = h
+	} else {
+		rr = &RFC3597{Hdr: h}
+	}
+
+	if noRdata(h) {
+		return rr, off, nil
+	}
+
 	end := off + int(h.Rdlength)
 
-	if fn, known := typeToUnpack[h.Rrtype]; !known {
-		rr, off, err = unpackRFC3597(h, msg, off)
-	} else {
-		rr, off, err = fn(h, msg, off)
+	off, err = rr.unpack(msg, off)
+	if err != nil {
+		return nil, end, err
 	}
 	if off != end {
 		return &h, end, &Error{err: "bad rdlength"}
 	}
-	return rr, off, err
+
+	return rr, off, nil
 }
 
 // unpackRRslice unpacks msg[off:] into an []RR.
@@ -605,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)
@@ -668,32 +718,33 @@ func (dns *Msg) Pack() (msg []byte, err error) {
 
 // PackBuffer packs a Msg, using the given buffer buf. If buf is too small a new buffer is allocated.
 func (dns *Msg) PackBuffer(buf []byte) (msg []byte, err error) {
-	var compression map[string]int
-	if dns.Compress {
-		compression = make(map[string]int) // Compression pointer mappings.
+	// If this message can't be compressed, avoid filling the
+	// compression map and creating garbage.
+	if dns.Compress && dns.isCompressible() {
+		compression := make(map[string]uint16) // Compression pointer mappings.
+		return dns.packBufferWithCompressionMap(buf, compressionMap{int: compression}, true)
 	}
-	return dns.packBufferWithCompressionMap(buf, compression)
+
+	return dns.packBufferWithCompressionMap(buf, compressionMap{}, false)
 }
 
 // packBufferWithCompressionMap packs a Msg, using the given buffer buf.
-func (dns *Msg) packBufferWithCompressionMap(buf []byte, compression map[string]int) (msg []byte, err error) {
-	// We use a similar function in tsig.go's stripTsig.
-
-	var dh Header
-
+func (dns *Msg) packBufferWithCompressionMap(buf []byte, compression compressionMap, compress bool) (msg []byte, err error) {
 	if dns.Rcode < 0 || dns.Rcode > 0xFFF {
 		return nil, ErrRcode
 	}
-	if dns.Rcode > 0xF {
-		// Regular RCODE field is 4 bits
-		opt := dns.IsEdns0()
-		if opt == nil {
-			return nil, ErrExtendedRcode
-		}
-		opt.SetExtendedRcode(uint8(dns.Rcode >> 4))
+
+	// Set extended rcode unconditionally if we have an opt, this will allow
+	// reseting the extended rcode bits if they need to.
+	if opt := dns.IsEdns0(); opt != nil {
+		opt.SetExtendedRcode(uint16(dns.Rcode))
+	} else if dns.Rcode > 0xF {
+		// If Rcode is an extended one and opt is nil, error out.
+		return nil, ErrExtendedRcode
 	}
 
 	// Convert convenient Msg into wire-like Header.
+	var dh Header
 	dh.Id = dns.Id
 	dh.Bits = uint16(dns.Opcode)<<11 | uint16(dns.Rcode&0xF)
 	if dns.Response {
@@ -721,50 +772,44 @@ func (dns *Msg) packBufferWithCompressionMap(buf []byte, compression map[string]
 		dh.Bits |= _CD
 	}
 
-	// Prepare variable sized arrays.
-	question := dns.Question
-	answer := dns.Answer
-	ns := dns.Ns
-	extra := dns.Extra
-
-	dh.Qdcount = uint16(len(question))
-	dh.Ancount = uint16(len(answer))
-	dh.Nscount = uint16(len(ns))
-	dh.Arcount = uint16(len(extra))
+	dh.Qdcount = uint16(len(dns.Question))
+	dh.Ancount = uint16(len(dns.Answer))
+	dh.Nscount = uint16(len(dns.Ns))
+	dh.Arcount = uint16(len(dns.Extra))
 
 	// We need the uncompressed length here, because we first pack it and then compress it.
 	msg = buf
-	uncompressedLen := compressedLen(dns, false)
+	uncompressedLen := msgLenWithCompressionMap(dns, nil)
 	if packLen := uncompressedLen + 1; len(msg) < packLen {
 		msg = make([]byte, packLen)
 	}
 
 	// Pack it in: header and then the pieces.
 	off := 0
-	off, err = dh.pack(msg, off, compression, dns.Compress)
+	off, err = dh.pack(msg, off, compression, compress)
 	if err != nil {
 		return nil, err
 	}
-	for i := 0; i < len(question); i++ {
-		off, err = question[i].pack(msg, off, compression, dns.Compress)
+	for _, r := range dns.Question {
+		off, err = r.pack(msg, off, compression, compress)
 		if err != nil {
 			return nil, err
 		}
 	}
-	for i := 0; i < len(answer); i++ {
-		off, err = PackRR(answer[i], msg, off, compression, dns.Compress)
+	for _, r := range dns.Answer {
+		_, off, err = packRR(r, msg, off, compression, compress)
 		if err != nil {
 			return nil, err
 		}
 	}
-	for i := 0; i < len(ns); i++ {
-		off, err = PackRR(ns[i], msg, off, compression, dns.Compress)
+	for _, r := range dns.Ns {
+		_, off, err = packRR(r, msg, off, compression, compress)
 		if err != nil {
 			return nil, err
 		}
 	}
-	for i := 0; i < len(extra); i++ {
-		off, err = PackRR(extra[i], msg, off, compression, dns.Compress)
+	for _, r := range dns.Extra {
+		_, off, err = packRR(r, msg, off, compression, compress)
 		if err != nil {
 			return nil, err
 		}
@@ -772,28 +817,7 @@ func (dns *Msg) packBufferWithCompressionMap(buf []byte, compression map[string]
 	return msg[:off], nil
 }
 
-// Unpack unpacks a binary message to a Msg structure.
-func (dns *Msg) Unpack(msg []byte) (err error) {
-	var (
-		dh  Header
-		off int
-	)
-	if dh, off, err = unpackMsgHdr(msg, off); err != nil {
-		return err
-	}
-
-	dns.Id = dh.Id
-	dns.Response = dh.Bits&_QR != 0
-	dns.Opcode = int(dh.Bits>>11) & 0xF
-	dns.Authoritative = dh.Bits&_AA != 0
-	dns.Truncated = dh.Bits&_TC != 0
-	dns.RecursionDesired = dh.Bits&_RD != 0
-	dns.RecursionAvailable = dh.Bits&_RA != 0
-	dns.Zero = dh.Bits&_Z != 0
-	dns.AuthenticatedData = dh.Bits&_AD != 0
-	dns.CheckingDisabled = dh.Bits&_CD != 0
-	dns.Rcode = int(dh.Bits & 0xF)
-
+func (dns *Msg) unpack(dh Header, msg []byte, off int) (err error) {
 	// If we are at the end of the message we should return *just* the
 	// header. This can still be useful to the caller. 9.9.9.9 sends these
 	// when responding with REFUSED for instance.
@@ -812,8 +836,6 @@ func (dns *Msg) Unpack(msg []byte) (err error) {
 		var q Question
 		q, off, err = unpackQuestion(msg, off)
 		if err != nil {
-			// Even if Truncated is set, we only will set ErrTruncated if we
-			// actually got the questions
 			return err
 		}
 		if off1 == off { // Offset does not increase anymore, dh.Qdcount is a lie!
@@ -837,16 +859,29 @@ func (dns *Msg) Unpack(msg []byte) (err error) {
 	// The header counts might have been wrong so we need to update it
 	dh.Arcount = uint16(len(dns.Extra))
 
+	// Set extended Rcode
+	if opt := dns.IsEdns0(); opt != nil {
+		dns.Rcode |= opt.ExtendedRcode()
+	}
+
 	if off != len(msg) {
 		// TODO(miek) make this an error?
 		// use PackOpt to let people tell how detailed the error reporting should be?
 		// println("dns: extra bytes in dns packet", off, "<", len(msg))
-	} else if dns.Truncated {
-		// Whether we ran into a an error or not, we want to return that it
-		// was truncated
-		err = ErrTruncated
 	}
 	return err
+
+}
+
+// Unpack unpacks a binary message to a Msg structure.
+func (dns *Msg) Unpack(msg []byte) (err error) {
+	dh, off, err := unpackMsgHdr(msg, 0)
+	if err != nil {
+		return err
+	}
+
+	dns.setHdr(dh)
+	return dns.unpack(dh, msg, off)
 }
 
 // Convert a complete message to a string with dig-like output.
@@ -861,182 +896,148 @@ func (dns *Msg) String() string {
 	s += "ADDITIONAL: " + strconv.Itoa(len(dns.Extra)) + "\n"
 	if len(dns.Question) > 0 {
 		s += "\n;; QUESTION SECTION:\n"
-		for i := 0; i < len(dns.Question); i++ {
-			s += dns.Question[i].String() + "\n"
+		for _, r := range dns.Question {
+			s += r.String() + "\n"
 		}
 	}
 	if len(dns.Answer) > 0 {
 		s += "\n;; ANSWER SECTION:\n"
-		for i := 0; i < len(dns.Answer); i++ {
-			if dns.Answer[i] != nil {
-				s += dns.Answer[i].String() + "\n"
+		for _, r := range dns.Answer {
+			if r != nil {
+				s += r.String() + "\n"
 			}
 		}
 	}
 	if len(dns.Ns) > 0 {
 		s += "\n;; AUTHORITY SECTION:\n"
-		for i := 0; i < len(dns.Ns); i++ {
-			if dns.Ns[i] != nil {
-				s += dns.Ns[i].String() + "\n"
+		for _, r := range dns.Ns {
+			if r != nil {
+				s += r.String() + "\n"
 			}
 		}
 	}
 	if len(dns.Extra) > 0 {
 		s += "\n;; ADDITIONAL SECTION:\n"
-		for i := 0; i < len(dns.Extra); i++ {
-			if dns.Extra[i] != nil {
-				s += dns.Extra[i].String() + "\n"
+		for _, r := range dns.Extra {
+			if r != nil {
+				s += r.String() + "\n"
 			}
 		}
 	}
 	return s
 }
 
+// isCompressible returns whether the msg may be compressible.
+func (dns *Msg) isCompressible() bool {
+	// If we only have one question, there is nothing we can ever compress.
+	return len(dns.Question) > 1 || len(dns.Answer) > 0 ||
+		len(dns.Ns) > 0 || len(dns.Extra) > 0
+}
+
 // Len returns the message length when in (un)compressed wire format.
 // If dns.Compress is true compression it is taken into account. Len()
 // is provided to be a faster way to get the size of the resulting packet,
 // than packing it, measuring the size and discarding the buffer.
-func (dns *Msg) Len() int { return compressedLen(dns, dns.Compress) }
-
-func compressedLenWithCompressionMap(dns *Msg, compression map[string]int) int {
-	l := 12 // Message header is always 12 bytes
-	for _, r := range dns.Question {
-		compressionLenHelper(compression, r.Name, l)
-		l += r.len()
+func (dns *Msg) Len() int {
+	// If this message can't be compressed, avoid filling the
+	// compression map and creating garbage.
+	if dns.Compress && dns.isCompressible() {
+		compression := make(map[string]struct{})
+		return msgLenWithCompressionMap(dns, compression)
 	}
-	l += compressionLenSlice(l, compression, dns.Answer)
-	l += compressionLenSlice(l, compression, dns.Ns)
-	l += compressionLenSlice(l, compression, dns.Extra)
-	return l
+
+	return msgLenWithCompressionMap(dns, nil)
 }
 
-// compressedLen returns the message length when in compressed wire format
-// when compress is true, otherwise the uncompressed length is returned.
-func compressedLen(dns *Msg, compress bool) int {
-	// We always return one more than needed.
-	if compress {
-		compression := map[string]int{}
-		return compressedLenWithCompressionMap(dns, compression)
-	}
-	l := 12 // Message header is always 12 bytes
+func msgLenWithCompressionMap(dns *Msg, compression map[string]struct{}) int {
+	l := headerSize
 
 	for _, r := range dns.Question {
-		l += r.len()
+		l += r.len(l, compression)
 	}
 	for _, r := range dns.Answer {
 		if r != nil {
-			l += r.len()
+			l += r.len(l, compression)
 		}
 	}
 	for _, r := range dns.Ns {
 		if r != nil {
-			l += r.len()
+			l += r.len(l, compression)
 		}
 	}
 	for _, r := range dns.Extra {
 		if r != nil {
-			l += r.len()
+			l += r.len(l, compression)
 		}
 	}
 
 	return l
 }
 
-func compressionLenSlice(lenp int, c map[string]int, rs []RR) int {
-	initLen := lenp
-	for _, r := range rs {
-		if r == nil {
-			continue
-		}
-		// TmpLen is to track len of record at 14bits boudaries
-		tmpLen := lenp
-
-		x := r.len()
-		// track this length, and the global length in len, while taking compression into account for both.
-		k, ok, _ := compressionLenSearch(c, r.Header().Name)
-		if ok {
-			// Size of x is reduced by k, but we add 1 since k includes the '.' and label descriptor take 2 bytes
-			// so, basically x:= x - k - 1 + 2
-			x += 1 - k
-		}
+func domainNameLen(s string, off int, compression map[string]struct{}, compress bool) int {
+	if s == "" || s == "." {
+		return 1
+	}
+
+	escaped := strings.Contains(s, "\\")
 
-		tmpLen += compressionLenHelper(c, r.Header().Name, tmpLen)
-		k, ok, _ = compressionLenSearchType(c, r)
-		if ok {
-			x += 1 - k
+	if compression != nil && (compress || off < maxCompressionOffset) {
+		// compressionLenSearch will insert the entry into the compression
+		// map if it doesn't contain it.
+		if l, ok := compressionLenSearch(compression, s, off); ok && compress {
+			if escaped {
+				return escapedNameLen(s[:l]) + 2
+			}
+
+			return l + 2
 		}
-		lenp += x
-		tmpLen = lenp
-		tmpLen += compressionLenHelperType(c, r, tmpLen)
+	}
 
+	if escaped {
+		return escapedNameLen(s) + 1
 	}
-	return lenp - initLen
+
+	return len(s) + 1
 }
 
-// Put the parts of the name in the compression map, return the size in bytes added in payload
-func compressionLenHelper(c map[string]int, s string, currentLen int) int {
-	if currentLen > maxCompressionOffset {
-		// We won't be able to add any label that could be re-used later anyway
-		return 0
-	}
-	if _, ok := c[s]; ok {
-		return 0
-	}
-	initLen := currentLen
-	pref := ""
-	prev := s
-	lbs := Split(s)
-	for j := 0; j < len(lbs); j++ {
-		pref = s[lbs[j]:]
-		currentLen += len(prev) - len(pref)
-		prev = pref
-		if _, ok := c[pref]; !ok {
-			// If first byte label is within the first 14bits, it might be re-used later
-			if currentLen < maxCompressionOffset {
-				c[pref] = currentLen
-			}
+func escapedNameLen(s string) int {
+	nameLen := len(s)
+	for i := 0; i < len(s); i++ {
+		if s[i] != '\\' {
+			continue
+		}
+
+		if i+3 < len(s) && isDigit(s[i+1]) && isDigit(s[i+2]) && isDigit(s[i+3]) {
+			nameLen -= 3
+			i += 3
 		} else {
-			added := currentLen - initLen
-			if j > 0 {
-				// We added a new PTR
-				added += 2
-			}
-			return added
+			nameLen--
+			i++
 		}
 	}
-	return currentLen - initLen
+
+	return nameLen
 }
 
-// Look for each part in the compression map and returns its length,
-// keep on searching so we get the longest match.
-// Will return the size of compression found, whether a match has been
-// found and the size of record if added in payload
-func compressionLenSearch(c map[string]int, s string) (int, bool, int) {
-	off := 0
-	end := false
-	if s == "" { // don't bork on bogus data
-		return 0, false, 0
-	}
-	fullSize := 0
-	for {
+func compressionLenSearch(c map[string]struct{}, s string, msgOff int) (int, bool) {
+	for off, end := 0, false; !end; off, end = NextLabel(s, off) {
 		if _, ok := c[s[off:]]; ok {
-			return len(s[off:]), true, fullSize + off
+			return off, true
 		}
-		if end {
-			break
+
+		if msgOff+off < maxCompressionOffset {
+			c[s[off:]] = struct{}{}
 		}
-		// Each label descriptor takes 2 bytes, add it
-		fullSize += 2
-		off, end = NextLabel(s, off)
 	}
-	return 0, false, fullSize + len(s)
+
+	return 0, false
 }
 
 // Copy returns a new RR which is a deep-copy of r.
-func Copy(r RR) RR { r1 := r.copy(); return r1 }
+func Copy(r RR) RR { return r.copy() }
 
 // Len returns the length (in octets) of the uncompressed RR in wire format.
-func Len(r RR) int { return r.len() }
+func Len(r RR) int { return r.len(0, nil) }
 
 // Copy returns a new *Msg which is a deep-copy of dns.
 func (dns *Msg) Copy() *Msg { return dns.CopyTo(new(Msg)) }
@@ -1052,40 +1053,27 @@ func (dns *Msg) CopyTo(r1 *Msg) *Msg {
 	}
 
 	rrArr := make([]RR, len(dns.Answer)+len(dns.Ns)+len(dns.Extra))
-	var rri int
+	r1.Answer, rrArr = rrArr[:0:len(dns.Answer)], rrArr[len(dns.Answer):]
+	r1.Ns, rrArr = rrArr[:0:len(dns.Ns)], rrArr[len(dns.Ns):]
+	r1.Extra = rrArr[:0:len(dns.Extra)]
 
-	if len(dns.Answer) > 0 {
-		rrbegin := rri
-		for i := 0; i < len(dns.Answer); i++ {
-			rrArr[rri] = dns.Answer[i].copy()
-			rri++
-		}
-		r1.Answer = rrArr[rrbegin:rri:rri]
+	for _, r := range dns.Answer {
+		r1.Answer = append(r1.Answer, r.copy())
 	}
 
-	if len(dns.Ns) > 0 {
-		rrbegin := rri
-		for i := 0; i < len(dns.Ns); i++ {
-			rrArr[rri] = dns.Ns[i].copy()
-			rri++
-		}
-		r1.Ns = rrArr[rrbegin:rri:rri]
+	for _, r := range dns.Ns {
+		r1.Ns = append(r1.Ns, r.copy())
 	}
 
-	if len(dns.Extra) > 0 {
-		rrbegin := rri
-		for i := 0; i < len(dns.Extra); i++ {
-			rrArr[rri] = dns.Extra[i].copy()
-			rri++
-		}
-		r1.Extra = rrArr[rrbegin:rri:rri]
+	for _, r := range dns.Extra {
+		r1.Extra = append(r1.Extra, r.copy())
 	}
 
 	return r1
 }
 
-func (q *Question) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := PackDomainName(q.Name, msg, off, compression, compress)
+func (q *Question) pack(msg []byte, off int, compression compressionMap, compress bool) (int, error) {
+	off, err := packDomainName(q.Name, msg, off, compression, compress)
 	if err != nil {
 		return off, err
 	}
@@ -1126,7 +1114,7 @@ func unpackQuestion(msg []byte, off int) (Question, int, error) {
 	return q, off, err
 }
 
-func (dh *Header) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+func (dh *Header) pack(msg []byte, off int, compression compressionMap, compress bool) (int, error) {
 	off, err := packUint16(dh.Id, msg, off)
 	if err != nil {
 		return off, err
@@ -1148,7 +1136,10 @@ func (dh *Header) pack(msg []byte, off int, compression map[string]int, compress
 		return off, err
 	}
 	off, err = packUint16(dh.Arcount, msg, off)
-	return off, err
+	if err != nil {
+		return off, err
+	}
+	return off, nil
 }
 
 func unpackMsgHdr(msg []byte, off int) (Header, int, error) {
@@ -1177,5 +1168,23 @@ func unpackMsgHdr(msg []byte, off int) (Header, int, error) {
 		return dh, off, err
 	}
 	dh.Arcount, off, err = unpackUint16(msg, off)
-	return dh, off, err
+	if err != nil {
+		return dh, off, err
+	}
+	return dh, off, nil
+}
+
+// setHdr set the header in the dns using the binary data in dh.
+func (dns *Msg) setHdr(dh Header) {
+	dns.Id = dh.Id
+	dns.Response = dh.Bits&_QR != 0
+	dns.Opcode = int(dh.Bits>>11) & 0xF
+	dns.Authoritative = dh.Bits&_AA != 0
+	dns.Truncated = dh.Bits&_TC != 0
+	dns.RecursionDesired = dh.Bits&_RD != 0
+	dns.RecursionAvailable = dh.Bits&_RA != 0
+	dns.Zero = dh.Bits&_Z != 0 // _Z covers the zero bit, which should be zero; not sure why we set it to the opposite.
+	dns.AuthenticatedData = dh.Bits&_AD != 0
+	dns.CheckingDisabled = dh.Bits&_CD != 0
+	dns.Rcode = int(dh.Bits & 0xF)
 }
diff --git a/vendor/github.com/miekg/dns/msg_helpers.go b/vendor/github.com/miekg/dns/msg_helpers.go
index 81fc2b1b..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"
 )
 
@@ -25,12 +26,13 @@ func unpackDataA(msg []byte, off int) (net.IP, int, error) {
 }
 
 func packDataA(a net.IP, msg []byte, off int) (int, error) {
-	// It must be a slice of 4, even if it is 16, we encode only the first 4
-	if off+net.IPv4len > len(msg) {
-		return len(msg), &Error{err: "overflow packing a"}
-	}
 	switch len(a) {
 	case net.IPv4len, net.IPv6len:
+		// It must be a slice of 4, even if it is 16, we encode only the first 4
+		if off+net.IPv4len > len(msg) {
+			return len(msg), &Error{err: "overflow packing a"}
+		}
+
 		copy(msg[off:], a.To4())
 		off += net.IPv4len
 	case 0:
@@ -51,12 +53,12 @@ func unpackDataAAAA(msg []byte, off int) (net.IP, int, error) {
 }
 
 func packDataAAAA(aaaa net.IP, msg []byte, off int) (int, error) {
-	if off+net.IPv6len > len(msg) {
-		return len(msg), &Error{err: "overflow packing aaaa"}
-	}
-
 	switch len(aaaa) {
 	case net.IPv6len:
+		if off+net.IPv6len > len(msg) {
+			return len(msg), &Error{err: "overflow packing aaaa"}
+		}
+
 		copy(msg[off:], aaaa)
 		off += net.IPv6len
 	case 0:
@@ -99,14 +101,14 @@ func unpackHeader(msg []byte, off int) (rr RR_Header, off1 int, truncmsg []byte,
 	return hdr, off, msg, err
 }
 
-// pack packs an RR header, returning the offset to the end of the header.
+// packHeader packs an RR header, returning the offset to the end of the header.
 // See PackDomainName for documentation about the compression.
-func (hdr RR_Header) pack(msg []byte, off int, compression map[string]int, compress bool) (off1 int, err error) {
+func (hdr RR_Header) packHeader(msg []byte, off int, compression compressionMap, compress bool) (int, error) {
 	if off == len(msg) {
 		return off, nil
 	}
 
-	off, err = PackDomainName(hdr.Name, msg, off, compression, compress)
+	off, err := packDomainName(hdr.Name, msg, off, compression, compress)
 	if err != nil {
 		return len(msg), err
 	}
@@ -122,7 +124,7 @@ func (hdr RR_Header) pack(msg []byte, off int, compression map[string]int, compr
 	if err != nil {
 		return len(msg), err
 	}
-	off, err = packUint16(hdr.Rdlength, msg, off)
+	off, err = packUint16(0, msg, off) // The RDLENGTH field will be set later in packRR.
 	if err != nil {
 		return len(msg), err
 	}
@@ -177,14 +179,14 @@ func unpackUint8(msg []byte, off int) (i uint8, off1 int, err error) {
 	if off+1 > len(msg) {
 		return 0, len(msg), &Error{err: "overflow unpacking uint8"}
 	}
-	return uint8(msg[off]), off + 1, nil
+	return msg[off], off + 1, nil
 }
 
 func packUint8(i uint8, msg []byte, off int) (off1 int, err error) {
 	if off+1 > len(msg) {
 		return len(msg), &Error{err: "overflow packing uint8"}
 	}
-	msg[off] = byte(i)
+	msg[off] = i
 	return off + 1, nil
 }
 
@@ -223,8 +225,8 @@ func unpackUint48(msg []byte, off int) (i uint64, off1 int, err error) {
 		return 0, len(msg), &Error{err: "overflow unpacking uint64 as uint48"}
 	}
 	// Used in TSIG where the last 48 bits are occupied, so for now, assume a uint48 (6 bytes)
-	i = uint64(uint64(msg[off])<<40 | uint64(msg[off+1])<<32 | uint64(msg[off+2])<<24 | uint64(msg[off+3])<<16 |
-		uint64(msg[off+4])<<8 | uint64(msg[off+5]))
+	i = uint64(msg[off])<<40 | uint64(msg[off+1])<<32 | uint64(msg[off+2])<<24 | uint64(msg[off+3])<<16 |
+		uint64(msg[off+4])<<8 | uint64(msg[off+5])
 	off += 6
 	return i, off, nil
 }
@@ -264,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
-			writeEscapedByte(&s, b)
-		default:
-			s.WriteByte(b)
+			if consumed == 0 {
+				s.Grow(l * 2)
+			}
+			s.Write(msg[off+consumed : off+i])
+			s.WriteString(escapeByte(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) {
@@ -363,6 +377,22 @@ func packStringHex(s string, msg []byte, off int) (int, error) {
 	return off, nil
 }
 
+func unpackStringAny(msg []byte, off, end int) (string, int, error) {
+	if end > len(msg) {
+		return "", len(msg), &Error{err: "overflow unpacking anything"}
+	}
+	return string(msg[off:end]), end, nil
+}
+
+func packStringAny(s string, msg []byte, off int) (int, error) {
+	if off+len(s) > len(msg) {
+		return len(msg), &Error{err: "overflow packing anything"}
+	}
+	copy(msg[off:off+len(s)], s)
+	off += len(s)
+	return off, nil
+}
+
 func unpackStringTxt(msg []byte, off int) ([]string, int, error) {
 	txt, off, err := unpackTxt(msg, off)
 	if err != nil {
@@ -383,7 +413,7 @@ func packStringTxt(s []string, msg []byte, off int) (int, error) {
 func unpackDataOpt(msg []byte, off int) ([]EDNS0, int, error) {
 	var edns []EDNS0
 Option:
-	code := uint16(0)
+	var code uint16
 	if off+4 > len(msg) {
 		return nil, len(msg), &Error{err: "overflow unpacking opt"}
 	}
@@ -394,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)
-	}
-
-	if off < len(msg) {
-		goto Option
+		return e
 	}
-
-	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)
@@ -537,8 +527,7 @@ func unpackDataNsec(msg []byte, off int) ([]uint16, int, error) {
 		}
 
 		// Walk the bytes in the window and extract the type bits
-		for j := 0; j < length; j++ {
-			b := msg[off+j]
+		for j, b := range msg[off : off+length] {
 			// Check the bits one by one, and set the type
 			if b&0x80 == 0x80 {
 				nsec = append(nsec, uint16(window*256+j*8+0))
@@ -571,13 +560,35 @@ 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
 	}
 	var lastwindow, lastlength uint16
-	for j := 0; j < len(bitmap); j++ {
-		t := bitmap[j]
+	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
@@ -602,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
@@ -621,13 +691,143 @@ func unpackDataDomainNames(msg []byte, off, end int) ([]string, int, error) {
 	return servers, off, nil
 }
 
-func packDataDomainNames(names []string, msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+func packDataDomainNames(names []string, msg []byte, off int, compression compressionMap, compress bool) (int, error) {
+	var err error
+	for _, name := range names {
+		off, err = packDomainName(name, msg, off, compression, compress)
+		if err != nil {
+			return len(msg), err
+		}
+	}
+	return off, nil
+}
+
+func packDataApl(data []APLPrefix, msg []byte, off int) (int, error) {
 	var err error
-	for j := 0; j < len(names); j++ {
-		off, err = PackDomainName(names[j], msg, off, compression, false && compress)
+	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
new file mode 100644
index 00000000..156c5a0e
--- /dev/null
+++ b/vendor/github.com/miekg/dns/msg_truncate.go
@@ -0,0 +1,112 @@
+package dns
+
+// Truncate ensures the reply message will fit into the requested buffer
+// 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, 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 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
+// should be used for UDP requests without an OPT record, and
+// dns.MaxMsgSize for TCP requests without an OPT record.
+func (dns *Msg) Truncate(size int) {
+	if dns.IsTsig() != nil {
+		// To simplify this implementation, we don't perform
+		// truncation on responses with a TSIG record.
+		return
+	}
+
+	// RFC 6891 mandates that the payload size in an OPT record
+	// less than 512 (MinMsgSize) bytes must be treated as equal to 512 bytes.
+	//
+	// For ease of use, we impose that restriction here.
+	if size < MinMsgSize {
+		size = MinMsgSize
+	}
+
+	l := msgLenWithCompressionMap(dns, nil) // uncompressed length
+	if l <= size {
+		// Don't waste effort compressing this message.
+		dns.Compress = false
+		return
+	}
+
+	dns.Compress = true
+
+	edns0 := dns.popEdns0()
+	if edns0 != nil {
+		// Account for the OPT record that gets added at the end,
+		// by subtracting that length from our budget.
+		//
+		// The EDNS(0) OPT record must have the root domain and
+		// it's length is thus unaffected by compression.
+		size -= Len(edns0)
+	}
+
+	compression := make(map[string]struct{})
+
+	l = headerSize
+	for _, r := range dns.Question {
+		l += r.len(l, compression)
+	}
+
+	var numAnswer int
+	if l < size {
+		l, numAnswer = truncateLoop(dns.Answer, size, l, compression)
+	}
+
+	var numNS int
+	if l < size {
+		l, numNS = truncateLoop(dns.Ns, size, l, compression)
+	}
+
+	var numExtra int
+	if l < size {
+		_, numExtra = truncateLoop(dns.Extra, size, l, compression)
+	}
+
+	// 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]
+	dns.Extra = dns.Extra[:numExtra]
+
+	if edns0 != nil {
+		// Add the OPT record back onto the additional section.
+		dns.Extra = append(dns.Extra, edns0)
+	}
+}
+
+func truncateLoop(rrs []RR, size, l int, compression map[string]struct{}) (int, int) {
+	for i, r := range rrs {
+		if r == nil {
+			continue
+		}
+
+		l += r.len(l, compression)
+		if l > size {
+			// Return size, rather than l prior to this record,
+			// to prevent any further records being added.
+			return size, i
+		}
+		if l == size {
+			return l, i + 1
+		}
+	}
+
+	return l, len(rrs)
+}
diff --git a/vendor/github.com/miekg/dns/nsecx.go b/vendor/github.com/miekg/dns/nsecx.go
index 9b908c44..f8826817 100644
--- a/vendor/github.com/miekg/dns/nsecx.go
+++ b/vendor/github.com/miekg/dns/nsecx.go
@@ -2,53 +2,48 @@ package dns
 
 import (
 	"crypto/sha1"
-	"hash"
+	"encoding/hex"
 	"strings"
 )
 
-type saltWireFmt struct {
-	Salt string `dns:"size-hex"`
-}
-
 // HashName hashes a string (label) according to RFC 5155. It returns the hashed string in uppercase.
 func HashName(label string, ha uint8, iter uint16, salt string) string {
-	saltwire := new(saltWireFmt)
-	saltwire.Salt = salt
-	wire := make([]byte, DefaultMsgSize)
-	n, err := packSaltWire(saltwire, wire)
+	if ha != SHA1 {
+		return ""
+	}
+
+	wireSalt := make([]byte, hex.DecodedLen(len(salt)))
+	n, err := packStringHex(salt, wireSalt, 0)
 	if err != nil {
 		return ""
 	}
-	wire = wire[:n]
+	wireSalt = wireSalt[:n]
+
 	name := make([]byte, 255)
 	off, err := PackDomainName(strings.ToLower(label), name, 0, nil, false)
 	if err != nil {
 		return ""
 	}
 	name = name[:off]
-	var s hash.Hash
-	switch ha {
-	case SHA1:
-		s = sha1.New()
-	default:
-		return ""
-	}
 
+	s := sha1.New()
 	// k = 0
 	s.Write(name)
-	s.Write(wire)
+	s.Write(wireSalt)
 	nsec3 := s.Sum(nil)
+
 	// k > 0
 	for k := uint16(0); k < iter; k++ {
 		s.Reset()
 		s.Write(nsec3)
-		s.Write(wire)
+		s.Write(wireSalt)
 		nsec3 = s.Sum(nsec3[:0])
 	}
+
 	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)
@@ -63,8 +58,10 @@ func (rr *NSEC3) Cover(name string) bool {
 	}
 
 	nextHash := rr.NextDomain
-	if ownerHash == nextHash { // empty interval
-		return false
+
+	// if empty interval found, try cover wildcard hashes so nameHash shouldn't match with ownerHash
+	if ownerHash == nextHash && nameHash != ownerHash { // empty interval
+		return true
 	}
 	if ownerHash > nextHash { // end of zone
 		if nameHash > ownerHash { // covered since there is nothing after ownerHash
@@ -96,11 +93,3 @@ func (rr *NSEC3) Match(name string) bool {
 	}
 	return false
 }
-
-func packSaltWire(sw *saltWireFmt, msg []byte) (int, error) {
-	off, err := packStringHex(sw.Salt, msg, 0)
-	if err != nil {
-		return off, err
-	}
-	return off, nil
-}
diff --git a/vendor/github.com/miekg/dns/privaterr.go b/vendor/github.com/miekg/dns/privaterr.go
index 74544a74..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,21 +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()
-	switch rr := anyrr.(type) {
-	case *PrivateRR:
-		return rr
-	}
-	panic(fmt.Sprintf("dns: RR is not a PrivateRR, TypeToRR[%d] generator returned %T", rrtype, anyrr))
+	generator func() PrivateRdata // for copy
 }
 
 // Header return the RR header of r.
@@ -52,86 +35,71 @@ func (r *PrivateRR) Header() *RR_Header { return &r.Hdr }
 func (r *PrivateRR) String() string { return r.Hdr.String() + r.Data.String() }
 
 // Private len and copy parts to satisfy RR interface.
-func (r *PrivateRR) len() int { return r.Hdr.len() + r.Data.Len() }
+func (r *PrivateRR) len(off int, compression map[string]struct{}) int {
+	l := r.Hdr.len(off, compression)
+	l += r.Data.Len()
+	return l
+}
+
 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
 }
-func (r *PrivateRR) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := r.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+
+func (r *PrivateRR) pack(msg []byte, off int, compression compressionMap, compress bool) (int, error) {
 	n, err := r.Data.Pack(msg[off:])
 	if err != nil {
 		return len(msg), err
 	}
 	off += n
-	r.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-// PrivateHandle registers a private resource record type. It requires
-// string and numeric representation of private RR type and generator function as argument.
-func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata) {
-	rtypestr = strings.ToUpper(rtypestr)
-
-	TypeToRR[rtype] = func() RR { return &PrivateRR{RR_Header{}, generator()} }
-	TypeToString[rtype] = rtypestr
-	StringToType[rtypestr] = rtype
+func (r *PrivateRR) unpack(msg []byte, off int) (int, error) {
+	off1, err := r.Data.Unpack(msg[off:])
+	off += off1
+	return off, err
+}
 
-	typeToUnpack[rtype] = func(h RR_Header, msg []byte, off int) (RR, int, error) {
-		if noRdata(h) {
-			return &h, off, nil
+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:
+	for {
+		// TODO(miek): we could also be returning _QUOTE, this might or might not
+		// be an issue (basically parsing TXT becomes hard)
+		switch l, _ = c.Next(); l.value {
+		case zNewline, zEOF:
+			break Fetch
+		case zString:
+			text = append(text, l.token)
 		}
-		var err error
-
-		rr := mkPrivateRR(h.Rrtype)
-		rr.Hdr = h
+	}
 
-		off1, err := rr.Data.Unpack(msg[off:])
-		off += off1
-		if err != nil {
-			return rr, off, err
-		}
-		return rr, off, err
+	err := r.Data.Parse(text)
+	if err != nil {
+		return &ParseError{"", err.Error(), l}
 	}
 
-	setPrivateRR := func(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-		rr := mkPrivateRR(h.Rrtype)
-		rr.Hdr = h
-
-		var l lex
-		text := make([]string, 0, 2) // could be 0..N elements, median is probably 1
-	Fetch:
-		for {
-			// TODO(miek): we could also be returning _QUOTE, this might or might not
-			// be an issue (basically parsing TXT becomes hard)
-			switch l, _ = c.Next(); l.value {
-			case zNewline, zEOF:
-				break Fetch
-			case zString:
-				text = append(text, l.token)
-			}
-		}
+	return nil
+}
 
-		err := rr.Data.Parse(text)
-		if err != nil {
-			return nil, &ParseError{f, err.Error(), l}, ""
-		}
+func (r1 *PrivateRR) isDuplicate(r2 RR) bool { return false }
 
-		return rr, nil, ""
-	}
+// PrivateHandle registers a private resource record type. It requires
+// string and numeric representation of private RR type and generator function as argument.
+func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata) {
+	rtypestr = strings.ToUpper(rtypestr)
 
-	typeToparserFunc[rtype] = parserFunc{setPrivateRR, true}
+	TypeToRR[rtype] = func() RR { return &PrivateRR{RR_Header{}, generator(), generator} }
+	TypeToString[rtype] = rtypestr
+	StringToType[rtypestr] = rtype
 }
 
 // PrivateHandleRemove removes definitions required to support private RR type.
@@ -140,8 +108,6 @@ func PrivateHandleRemove(rtype uint16) {
 	if ok {
 		delete(TypeToRR, rtype)
 		delete(TypeToString, rtype)
-		delete(typeToparserFunc, rtype)
 		delete(StringToType, rtypestr)
-		delete(typeToUnpack, rtype)
 	}
 }
diff --git a/vendor/github.com/miekg/dns/rawmsg.go b/vendor/github.com/miekg/dns/rawmsg.go
deleted file mode 100644
index 6e21fba7..00000000
--- a/vendor/github.com/miekg/dns/rawmsg.go
+++ /dev/null
@@ -1,49 +0,0 @@
-package dns
-
-import "encoding/binary"
-
-// rawSetRdlength sets the rdlength in the header of
-// the RR. The offset 'off' must be positioned at the
-// start of the header of the RR, 'end' must be the
-// end of the RR.
-func rawSetRdlength(msg []byte, off, end int) bool {
-	l := len(msg)
-Loop:
-	for {
-		if off+1 > l {
-			return false
-		}
-		c := int(msg[off])
-		off++
-		switch c & 0xC0 {
-		case 0x00:
-			if c == 0x00 {
-				// End of the domainname
-				break Loop
-			}
-			if off+c > l {
-				return false
-			}
-			off += c
-
-		case 0xC0:
-			// pointer, next byte included, ends domainname
-			off++
-			break Loop
-		}
-	}
-	// The domainname has been seen, we at the start of the fixed part in the header.
-	// Type is 2 bytes, class is 2 bytes, ttl 4 and then 2 bytes for the length.
-	off += 2 + 2 + 4
-	if off+2 > l {
-		return false
-	}
-	//off+1 is the end of the header, 'end' is the end of the rr
-	//so 'end' - 'off+2' is the length of the rdata
-	rdatalen := end - (off + 2)
-	if rdatalen > 0xFFFF {
-		return false
-	}
-	binary.BigEndian.PutUint16(msg[off:], uint16(rdatalen))
-	return true
-}
diff --git a/vendor/github.com/miekg/dns/reverse.go b/vendor/github.com/miekg/dns/reverse.go
index f6e7a47a..28151af8 100644
--- a/vendor/github.com/miekg/dns/reverse.go
+++ b/vendor/github.com/miekg/dns/reverse.go
@@ -12,6 +12,20 @@ var StringToOpcode = reverseInt(OpcodeToString)
 // StringToRcode is a map of rcodes to strings.
 var StringToRcode = reverseInt(RcodeToString)
 
+func init() {
+	// Preserve previous NOTIMP typo, see github.com/miekg/dns/issues/733.
+	StringToRcode["NOTIMPL"] = RcodeNotImplemented
+}
+
+// StringToAlgorithm is the reverse of AlgorithmToString.
+var StringToAlgorithm = reverseInt8(AlgorithmToString)
+
+// StringToHash is a map of names to hash IDs.
+var StringToHash = reverseInt8(HashToString)
+
+// StringToCertType is the reverseof CertTypeToString.
+var StringToCertType = reverseInt16(CertTypeToString)
+
 // Reverse a map
 func reverseInt8(m map[uint8]string) map[string]uint8 {
 	n := make(map[string]uint8, len(m))
diff --git a/vendor/github.com/miekg/dns/sanitize.go b/vendor/github.com/miekg/dns/sanitize.go
index cac15787..a638e862 100644
--- a/vendor/github.com/miekg/dns/sanitize.go
+++ b/vendor/github.com/miekg/dns/sanitize.go
@@ -15,10 +15,11 @@ func Dedup(rrs []RR, m map[string]RR) []RR {
 	for _, r := range rrs {
 		key := normalizedString(r)
 		keys = append(keys, &key)
-		if _, ok := m[key]; ok {
+		if mr, ok := m[key]; ok {
 			// Shortest TTL wins.
-			if m[key].Header().Ttl > r.Header().Ttl {
-				m[key].Header().Ttl = r.Header().Ttl
+			rh, mrh := r.Header(), mr.Header()
+			if mrh.Ttl > rh.Ttl {
+				mrh.Ttl = rh.Ttl
 			}
 			continue
 		}
diff --git a/vendor/github.com/miekg/dns/scan.go b/vendor/github.com/miekg/dns/scan.go
index 61ace121..aa2840ef 100644
--- a/vendor/github.com/miekg/dns/scan.go
+++ b/vendor/github.com/miekg/dns/scan.go
@@ -79,23 +79,12 @@ func (e *ParseError) Error() (s string) {
 }
 
 type lex struct {
-	token   string // text of the token
-	err     bool   // when true, token text has lexer error
-	value   uint8  // value: zString, _BLANK, etc.
-	torc    uint16 // type or class as parsed in the lexer, we only need to look this up in the grammar
-	line    int    // line in the file
-	column  int    // column in the file
-	comment string // any comment text seen
-}
-
-// 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
+	token  string // text of the token
+	err    bool   // when true, token text has lexer error
+	value  uint8  // value: zString, _BLANK, etc.
+	torc   uint16 // type or class as parsed in the lexer, we only need to look this up in the grammar
+	line   int    // line in the file
+	column int    // column in the file
 }
 
 // ttlState describes the state necessary to fill in an omitted RR TTL
@@ -104,15 +93,12 @@ type ttlState struct {
 	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"), "")
@@ -134,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
@@ -204,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:
@@ -244,11 +168,10 @@ type ZoneParser struct {
 	sub    *ZoneParser
 	osFile *os.File
 
-	com string
-
 	includeDepth uint8
 
-	includeAllowed bool
+	includeAllowed     bool
+	generateDisallowed bool
 }
 
 // NewZoneParser returns an RFC 1035 style zonefile parser that reads
@@ -318,12 +241,19 @@ func (zp *ZoneParser) setParseError(err string, l lex) (RR, bool) {
 // Comment returns an optional text comment that occurred alongside
 // the RR.
 func (zp *ZoneParser) Comment() string {
-	return zp.com
+	if zp.parseErr != nil {
+		return ""
+	}
+
+	if zp.sub != nil {
+		return zp.sub.Comment()
+	}
+
+	return zp.c.Comment()
 }
 
 func (zp *ZoneParser) subNext() (RR, bool) {
 	if rr, ok := zp.sub.Next(); ok {
-		zp.com = zp.sub.com
 		return rr, true
 	}
 
@@ -347,8 +277,6 @@ func (zp *ZoneParser) subNext() (RR, bool) {
 // error. After Next returns (nil, false), the Err method will return
 // any error that occurred during parsing.
 func (zp *ZoneParser) Next() (RR, bool) {
-	zp.com = ""
-
 	if zp.parseErr != nil {
 		return nil, false
 	}
@@ -501,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)
@@ -525,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)
@@ -545,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)
 			}
@@ -648,20 +577,44 @@ func (zp *ZoneParser) Next() (RR, bool) {
 
 			st = zExpectRdata
 		case zExpectRdata:
-			r, e, c1 := 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)
 				}
 
-				zp.parseErr = e
-				return nil, false
+				return rr, true
+			} else if l.value == zNewline {
+				return zp.setParseError("unexpected newline", l)
 			}
 
-			zp.com = c1
-			return r, true
+			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)
+				}
+
+				return zp.setParseError(err.err, err.lex)
+			}
+
+			return rr, true
 		}
 	}
 
@@ -670,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
 
@@ -678,9 +643,11 @@ type zlexer struct {
 	line   int
 	column int
 
-	com string
+	comBuf  string
+	comment string
 
-	l lex
+	l       lex
+	cachedL *lex
 
 	brace  int
 	quote  bool
@@ -746,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
 	}
@@ -767,14 +758,15 @@ func (zl *zlexer) Next() (lex, bool) {
 		escape bool
 	)
 
-	if zl.com != "" {
-		comi = copy(com[:], zl.com)
-		zl.com = ""
+	if zl.comBuf != "" {
+		comi = copy(com[:], zl.comBuf)
+		zl.comBuf = ""
 	}
 
+	zl.comment = ""
+
 	for x, ok := zl.readByte(); ok; x, ok = zl.readByte() {
 		l.line, l.column = zl.line, zl.column
-		l.comment = ""
 
 		if stri >= len(str) {
 			l.token = "token length insufficient for parsing"
@@ -898,20 +890,25 @@ func (zl *zlexer) Next() (lex, bool) {
 			}
 
 			zl.commt = true
-			zl.com = ""
+			zl.comBuf = ""
 
 			if comi > 1 {
 				// A newline was previously seen inside a comment that
 				// 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] = ';'
 			comi++
 
 			if stri > 0 {
-				zl.com = string(com[:comi])
+				zl.comBuf = string(com[:comi])
 
 				l.value = zString
 				l.token = string(str[:stri])
@@ -947,11 +944,11 @@ func (zl *zlexer) Next() (lex, bool) {
 
 					l.value = zNewline
 					l.token = "\n"
-					l.comment = string(com[:comi])
+					zl.comment = string(com[:comi])
 					return *l, true
 				}
 
-				zl.com = string(com[:comi])
+				zl.comBuf = string(com[:comi])
 				break
 			}
 
@@ -977,9 +974,9 @@ func (zl *zlexer) Next() (lex, bool) {
 
 				l.value = zNewline
 				l.token = "\n"
-				l.comment = zl.com
 
-				zl.com = ""
+				zl.comment = zl.comBuf
+				zl.comBuf = ""
 				zl.rrtype = false
 				zl.owner = true
 
@@ -1115,7 +1112,7 @@ func (zl *zlexer) Next() (lex, bool) {
 		// Send remainder of com
 		l.value = zNewline
 		l.token = "\n"
-		l.comment = string(com[:comi])
+		zl.comment = string(com[:comi])
 
 		if retL != (lex{}) {
 			zl.nextL = true
@@ -1126,7 +1123,6 @@ func (zl *zlexer) Next() (lex, bool) {
 	}
 
 	if zl.brace != 0 {
-		l.comment = "" // in case there was left over string and comment
 		l.token = "unbalanced brace"
 		l.err = true
 		return *l, true
@@ -1135,6 +1131,14 @@ func (zl *zlexer) Next() (lex, bool) {
 	return lex{value: zEOF}, false
 }
 
+func (zl *zlexer) Comment() string {
+	if zl.l.err {
+		return ""
+	}
+
+	return zl.comment
+}
+
 // Extract the class number from CLASSxx
 func classToInt(token string) (uint16, bool) {
 	offset := 5
@@ -1163,8 +1167,7 @@ func typeToInt(token string) (uint16, bool) {
 
 // stringToTTL parses things like 2w, 2m, etc, and returns the time in seconds.
 func stringToTTL(token string) (uint32, bool) {
-	s := uint32(0)
-	i := uint32(0)
+	var s, i uint32
 	for _, c := range token {
 		switch c {
 		case 's', 'S':
@@ -1207,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
@@ -1224,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
 }
@@ -1252,7 +1270,7 @@ func toAbsoluteName(name, origin string) (absolute string, ok bool) {
 	}
 
 	// check if name is already absolute
-	if name[len(name)-1] == '.' {
+	if IsFqdn(name) {
 		return name, true
 	}
 
@@ -1272,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
@@ -1283,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
@@ -1292,24 +1316,21 @@ func locCheckEast(token string, longitude uint32) (uint32, bool) {
 	return longitude, false
 }
 
-// "Eat" the rest of the "line". Return potential comments
-func slurpRemainder(c *zlexer, f string) (*ParseError, string) {
+// "Eat" the rest of the "line"
+func slurpRemainder(c *zlexer) *ParseError {
 	l, _ := c.Next()
-	com := ""
 	switch l.value {
 	case zBlank:
 		l, _ = c.Next()
-		com = l.comment
 		if l.value != zNewline && l.value != zEOF {
-			return &ParseError{f, "garbage after rdata", l}, ""
+			return &ParseError{"", "garbage after rdata", l}
 		}
 	case zNewline:
-		com = l.comment
 	case zEOF:
 	default:
-		return &ParseError{f, "garbage after rdata", l}, ""
+		return &ParseError{"", "garbage after rdata", l}
 	}
-	return nil, com
+	return nil
 }
 
 // Parse a 64 bit-like ipv6 address: "0014:4fff:ff20:ee64"
diff --git a/vendor/github.com/miekg/dns/scan_rr.go b/vendor/github.com/miekg/dns/scan_rr.go
index 935d22c3..69f10052 100644
--- a/vendor/github.com/miekg/dns/scan_rr.go
+++ b/vendor/github.com/miekg/dns/scan_rr.go
@@ -1,76 +1,42 @@
 package dns
 
 import (
+	"bytes"
 	"encoding/base64"
 	"net"
 	"strconv"
 	"strings"
 )
 
-type parserFunc struct {
-	// Func defines the function that parses the tokens and returns the RR
-	// or an error. The last string contains any comments in the line as
-	// they returned by the lexer as well.
-	Func func(h RR_Header, c *zlexer, origin string, file string) (RR, *ParseError, string)
-	// Signals if the RR ending is of variable length, like TXT or records
-	// that have Hexadecimal or Base64 as their last element in the Rdata. Records
-	// that have a fixed ending or for instance A, AAAA, SOA and etc.
-	Variable bool
-}
-
-// 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, string) {
-	parserfunc, ok := typeToparserFunc[h.Rrtype]
-	if ok {
-		r, e, cm := parserfunc.Func(h, c, o, f)
-		if parserfunc.Variable {
-			return r, e, cm
-		}
-		if e != nil {
-			return nil, e, ""
-		}
-		e, cm = slurpRemainder(c, f)
-		if e != nil {
-			return nil, e, ""
-		}
-		return r, nil, cm
-	}
-	// RFC3957 RR (Unknown RR handling)
-	return setRFC3597(h, c, o, f)
-}
-
 // 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, string) {
-	s := ""
+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, l.comment
+
+	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, string) {
+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
@@ -79,7 +45,7 @@ func endingToTxtSlice(c *zlexer, errstr, f string) ([]string, *ParseError, strin
 	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:
@@ -106,7 +72,7 @@ func endingToTxtSlice(c *zlexer, errstr, f string) ([]string, *ParseError, strin
 		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 {
@@ -115,115 +81,79 @@ func endingToTxtSlice(c *zlexer, errstr, f string) ([]string, *ParseError, strin
 			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, l.comment
-}
 
-func setA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(A)
-	rr.Hdr = h
+	return s, nil
+}
 
+func (rr *A) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, ""
-	}
-
 	rr.A = net.ParseIP(l.token)
-	if rr.A == nil || l.err {
-		return nil, &ParseError{f, "bad A A", l}, ""
+	// IPv4 addresses cannot include ":".
+	// We do this rather than use net.IP's To4() because
+	// To4() treats IPv4-mapped IPv6 addresses as being
+	// IPv4.
+	isIPv4 := !strings.Contains(l.token, ":")
+	if rr.A == nil || !isIPv4 || l.err {
+		return &ParseError{"", "bad A A", l}
 	}
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setAAAA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(AAAA)
-	rr.Hdr = h
-
+func (rr *AAAA) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, ""
-	}
-
 	rr.AAAA = net.ParseIP(l.token)
-	if rr.AAAA == nil || l.err {
-		return nil, &ParseError{f, "bad AAAA AAAA", l}, ""
+	// IPv6 addresses must include ":", and IPv4
+	// addresses cannot include ":".
+	isIPv6 := strings.Contains(l.token, ":")
+	if rr.AAAA == nil || !isIPv6 || l.err {
+		return &ParseError{"", "bad AAAA AAAA", l}
 	}
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setNS(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(NS)
-	rr.Hdr = h
-
+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 rr, nil, ""
-	}
-
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return nil, &ParseError{f, "bad NS Ns", l}, ""
+		return &ParseError{"", "bad NS Ns", l}
 	}
 	rr.Ns = name
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setPTR(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(PTR)
-	rr.Hdr = h
-
+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 rr, nil, ""
-	}
-
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return nil, &ParseError{f, "bad PTR Ptr", l}, ""
+		return &ParseError{"", "bad PTR Ptr", l}
 	}
 	rr.Ptr = name
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setNSAPPTR(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(NSAPPTR)
-	rr.Hdr = h
-
+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 rr, nil, ""
-	}
-
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return nil, &ParseError{f, "bad NSAP-PTR Ptr", l}, ""
+		return &ParseError{"", "bad NSAP-PTR Ptr", l}
 	}
 	rr.Ptr = name
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setRP(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(RP)
-	rr.Hdr = h
-
+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 rr, nil, ""
-	}
-
 	mbox, mboxOk := toAbsoluteName(l.token, o)
 	if l.err || !mboxOk {
-		return nil, &ParseError{f, "bad RP Mbox", l}, ""
+		return &ParseError{"", "bad RP Mbox", l}
 	}
 	rr.Mbox = mbox
 
@@ -233,78 +163,51 @@ func setRP(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 
 	txt, txtOk := toAbsoluteName(l.token, o)
 	if l.err || !txtOk {
-		return nil, &ParseError{f, "bad RP Txt", l}, ""
+		return &ParseError{"", "bad RP Txt", l}
 	}
 	rr.Txt = txt
 
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setMR(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(MR)
-	rr.Hdr = h
-
+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 rr, nil, ""
-	}
-
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return nil, &ParseError{f, "bad MR Mr", l}, ""
+		return &ParseError{"", "bad MR Mr", l}
 	}
 	rr.Mr = name
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setMB(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(MB)
-	rr.Hdr = h
-
+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 rr, nil, ""
-	}
-
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return nil, &ParseError{f, "bad MB Mb", l}, ""
+		return &ParseError{"", "bad MB Mb", l}
 	}
 	rr.Mb = name
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setMG(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(MG)
-	rr.Hdr = h
-
+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 rr, nil, ""
-	}
-
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return nil, &ParseError{f, "bad MG Mg", l}, ""
+		return &ParseError{"", "bad MG Mg", l}
 	}
 	rr.Mg = name
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setHINFO(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(HINFO)
-	rr.Hdr = h
-
-	chunks, e, c1 := 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 nil, e, c1
+		return e
 	}
 
 	if ln := len(chunks); ln == 0 {
-		return rr, nil, ""
+		return nil
 	} else if ln == 1 {
 		// Can we split it?
 		if out := strings.Fields(chunks[0]); len(out) > 1 {
@@ -317,22 +220,14 @@ func setHINFO(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 	rr.Cpu = chunks[0]
 	rr.Os = strings.Join(chunks[1:], " ")
 
-	return rr, nil, ""
+	return nil
 }
 
-func setMINFO(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(MINFO)
-	rr.Hdr = h
-
+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 rr, nil, ""
-	}
-
 	rmail, rmailOk := toAbsoluteName(l.token, o)
 	if l.err || !rmailOk {
-		return nil, &ParseError{f, "bad MINFO Rmail", l}, ""
+		return &ParseError{"", "bad MINFO Rmail", l}
 	}
 	rr.Rmail = rmail
 
@@ -342,61 +237,38 @@ func setMINFO(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 
 	email, emailOk := toAbsoluteName(l.token, o)
 	if l.err || !emailOk {
-		return nil, &ParseError{f, "bad MINFO Email", l}, ""
+		return &ParseError{"", "bad MINFO Email", l}
 	}
 	rr.Email = email
 
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setMF(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(MF)
-	rr.Hdr = h
-
+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 rr, nil, ""
-	}
-
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return nil, &ParseError{f, "bad MF Mf", l}, ""
+		return &ParseError{"", "bad MF Mf", l}
 	}
 	rr.Mf = name
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setMD(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(MD)
-	rr.Hdr = h
-
+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 rr, nil, ""
-	}
-
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return nil, &ParseError{f, "bad MD Md", l}, ""
+		return &ParseError{"", "bad MD Md", l}
 	}
 	rr.Md = name
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setMX(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(MX)
-	rr.Hdr = h
-
+func (rr *MX) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, ""
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return nil, &ParseError{f, "bad MX Pref", l}, ""
+		return &ParseError{"", "bad MX Pref", l}
 	}
 	rr.Preference = uint16(i)
 
@@ -406,25 +278,18 @@ func setMX(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return nil, &ParseError{f, "bad MX Mx", l}, ""
+		return &ParseError{"", "bad MX Mx", l}
 	}
 	rr.Mx = name
 
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setRT(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(RT)
-	rr.Hdr = h
-
+func (rr *RT) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, ""
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil {
-		return nil, &ParseError{f, "bad RT Preference", l}, ""
+		return &ParseError{"", "bad RT Preference", l}
 	}
 	rr.Preference = uint16(i)
 
@@ -434,25 +299,18 @@ func setRT(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return nil, &ParseError{f, "bad RT Host", l}, ""
+		return &ParseError{"", "bad RT Host", l}
 	}
 	rr.Host = name
 
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setAFSDB(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(AFSDB)
-	rr.Hdr = h
-
+func (rr *AFSDB) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, ""
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return nil, &ParseError{f, "bad AFSDB Subtype", l}, ""
+		return &ParseError{"", "bad AFSDB Subtype", l}
 	}
 	rr.Subtype = uint16(i)
 
@@ -462,40 +320,26 @@ func setAFSDB(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return nil, &ParseError{f, "bad AFSDB Hostname", l}, ""
+		return &ParseError{"", "bad AFSDB Hostname", l}
 	}
 	rr.Hostname = name
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setX25(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(X25)
-	rr.Hdr = h
-
+func (rr *X25) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, ""
-	}
-
 	if l.err {
-		return nil, &ParseError{f, "bad X25 PSDNAddress", l}, ""
+		return &ParseError{"", "bad X25 PSDNAddress", l}
 	}
 	rr.PSDNAddress = l.token
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setKX(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(KX)
-	rr.Hdr = h
-
+func (rr *KX) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, ""
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return nil, &ParseError{f, "bad KX Pref", l}, ""
+		return &ParseError{"", "bad KX Pref", l}
 	}
 	rr.Preference = uint16(i)
 
@@ -505,61 +349,37 @@ func setKX(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return nil, &ParseError{f, "bad KX Exchanger", l}, ""
+		return &ParseError{"", "bad KX Exchanger", l}
 	}
 	rr.Exchanger = name
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setCNAME(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(CNAME)
-	rr.Hdr = h
-
+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 rr, nil, ""
-	}
-
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return nil, &ParseError{f, "bad CNAME Target", l}, ""
+		return &ParseError{"", "bad CNAME Target", l}
 	}
 	rr.Target = name
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setDNAME(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(DNAME)
-	rr.Hdr = h
-
+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 rr, nil, ""
-	}
-
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return nil, &ParseError{f, "bad DNAME Target", l}, ""
+		return &ParseError{"", "bad DNAME Target", l}
 	}
 	rr.Target = name
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setSOA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(SOA)
-	rr.Hdr = h
-
+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 rr, nil, ""
-	}
-
 	ns, nsOk := toAbsoluteName(l.token, o)
 	if l.err || !nsOk {
-		return nil, &ParseError{f, "bad SOA Ns", l}, ""
+		return &ParseError{"", "bad SOA Ns", l}
 	}
 	rr.Ns = ns
 
@@ -569,7 +389,7 @@ func setSOA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 
 	mbox, mboxOk := toAbsoluteName(l.token, o)
 	if l.err || !mboxOk {
-		return nil, &ParseError{f, "bad SOA Mbox", l}, ""
+		return &ParseError{"", "bad SOA Mbox", l}
 	}
 	rr.Mbox = mbox
 
@@ -582,16 +402,16 @@ func setSOA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 	for i := 0; i < 5; i++ {
 		l, _ = c.Next()
 		if l.err {
-			return nil, &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 nil, &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 nil, &ParseError{f, "bad SOA zone parameter", l}, ""
+				return &ParseError{"", "bad SOA zone parameter", l}
 
 			}
 		} else {
@@ -614,37 +434,30 @@ func setSOA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 			rr.Minttl = v
 		}
 	}
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setSRV(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(SRV)
-	rr.Hdr = h
-
+func (rr *SRV) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, ""
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return nil, &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 nil, &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 nil, &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)
 
@@ -654,32 +467,25 @@ func setSRV(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return nil, &ParseError{f, "bad SRV Target", l}, ""
+		return &ParseError{"", "bad SRV Target", l}
 	}
 	rr.Target = name
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setNAPTR(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(NAPTR)
-	rr.Hdr = h
-
+func (rr *NAPTR) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, ""
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return nil, &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 nil, &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)
 
@@ -687,57 +493,57 @@ func setNAPTR(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 	c.Next()        // zBlank
 	l, _ = c.Next() // _QUOTE
 	if l.value != zQuote {
-		return nil, &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 nil, &ParseError{f, "bad NAPTR Flags", l}, ""
+			return &ParseError{"", "bad NAPTR Flags", l}
 		}
 	} else if l.value == zQuote {
 		rr.Flags = ""
 	} else {
-		return nil, &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 nil, &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 nil, &ParseError{f, "bad NAPTR Service", l}, ""
+			return &ParseError{"", "bad NAPTR Service", l}
 		}
 	} else if l.value == zQuote {
 		rr.Service = ""
 	} else {
-		return nil, &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 nil, &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 nil, &ParseError{f, "bad NAPTR Regexp", l}, ""
+			return &ParseError{"", "bad NAPTR Regexp", l}
 		}
 	} else if l.value == zQuote {
 		rr.Regexp = ""
 	} else {
-		return nil, &ParseError{f, "bad NAPTR Regexp", l}, ""
+		return &ParseError{"", "bad NAPTR Regexp", l}
 	}
 
 	// After quote no space??
@@ -747,25 +553,17 @@ func setNAPTR(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return nil, &ParseError{f, "bad NAPTR Replacement", l}, ""
+		return &ParseError{"", "bad NAPTR Replacement", l}
 	}
 	rr.Replacement = name
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setTALINK(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(TALINK)
-	rr.Hdr = h
-
+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 rr, nil, ""
-	}
-
 	previousName, previousNameOk := toAbsoluteName(l.token, o)
 	if l.err || !previousNameOk {
-		return nil, &ParseError{f, "bad TALINK PreviousName", l}, ""
+		return &ParseError{"", "bad TALINK PreviousName", l}
 	}
 	rr.PreviousName = previousName
 
@@ -775,30 +573,25 @@ func setTALINK(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 
 	nextName, nextNameOk := toAbsoluteName(l.token, o)
 	if l.err || !nextNameOk {
-		return nil, &ParseError{f, "bad TALINK NextName", l}, ""
+		return &ParseError{"", "bad TALINK NextName", l}
 	}
 	rr.NextName = nextName
 
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setLOC(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(LOC)
-	rr.Hdr = h
+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 rr, nil, ""
-	}
 	i, e := strconv.ParseUint(l.token, 10, 32)
-	if e != nil || l.err {
-		return nil, &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)
 
@@ -808,16 +601,16 @@ func setLOC(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 	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 nil, &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 nil, &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)
 	}
@@ -828,14 +621,14 @@ func setLOC(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 		goto East
 	}
 	// If still alive, flag an error
-	return nil, &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 nil, &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)
 	}
@@ -845,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 nil, &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 nil, &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)
 	}
@@ -864,19 +657,19 @@ East:
 		goto Altitude
 	}
 	// If still alive, flag an error
-	return nil, &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 nil, &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 nil, &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)
 	}
@@ -889,55 +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 nil, &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 nil, &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 nil, &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 nil, &ParseError{f, "bad LOC Size, HorizPre or VertPre", l}, ""
+			return &ParseError{"", "bad LOC Size, HorizPre or VertPre", l}
 		}
 		l, _ = c.Next()
 	}
-	return rr, nil, ""
+	return nil
 }
 
-func setHIP(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(HIP)
-	rr.Hdr = h
-
+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 rr, nil, l.comment
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 8)
 	if e != nil || l.err {
-		return nil, &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 nil, &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
@@ -945,7 +731,7 @@ func setHIP(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 	c.Next()        // zBlank
 	l, _ = c.Next() // zString
 	if len(l.token) == 0 || l.err {
-		return nil, &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)))
@@ -958,33 +744,27 @@ func setHIP(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 		case zString:
 			name, nameOk := toAbsoluteName(l.token, o)
 			if l.err || !nameOk {
-				return nil, &ParseError{f, "bad HIP RendezvousServers", l}, ""
+				return &ParseError{"", "bad HIP RendezvousServers", l}
 			}
 			xs = append(xs, name)
 		case zBlank:
 			// Ok
 		default:
-			return nil, &ParseError{f, "bad HIP RendezvousServers", l}, ""
+			return &ParseError{"", "bad HIP RendezvousServers", l}
 		}
 		l, _ = c.Next()
 	}
+
 	rr.RendezvousServers = xs
-	return rr, nil, l.comment
+	return nil
 }
 
-func setCERT(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(CERT)
-	rr.Hdr = h
-
+func (rr *CERT) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, l.comment
-	}
-
 	if v, ok := StringToCertType[l.token]; ok {
 		rr.Type = v
-	} else if i, e := strconv.ParseUint(l.token, 10, 16); e != nil {
-		return nil, &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)
 	}
@@ -992,60 +772,51 @@ func setCERT(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 	l, _ = c.Next() // zString
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return nil, &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 nil, &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, c1 := endingToString(c, "bad CERT Certificate", f)
+	s, e1 := endingToString(c, "bad CERT Certificate")
 	if e1 != nil {
-		return nil, e1, c1
+		return e1
 	}
 	rr.Certificate = s
-	return rr, nil, c1
+	return nil
 }
 
-func setOPENPGPKEY(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(OPENPGPKEY)
-	rr.Hdr = h
-
-	s, e, c1 := 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 nil, e, c1
+		return e
 	}
 	rr.PublicKey = s
-	return rr, nil, c1
+	return nil
 }
 
-func setCSYNC(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(CSYNC)
-	rr.Hdr = h
-
+func (rr *CSYNC) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, l.comment
-	}
 	j, e := strconv.ParseUint(l.token, 10, 32)
 	if e != nil {
 		// Serial must be a number
-		return nil, &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 nil, &ParseError{f, "bad CSYNC flags", l}, ""
+		return &ParseError{"", "bad CSYNC flags", l}
 	}
 	rr.Flags = uint16(j)
 
@@ -1063,45 +834,32 @@ func setCSYNC(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 			tokenUpper := strings.ToUpper(l.token)
 			if k, ok = StringToType[tokenUpper]; !ok {
 				if k, ok = typeToInt(l.token); !ok {
-					return nil, &ParseError{f, "bad CSYNC TypeBitMap", l}, ""
+					return &ParseError{"", "bad CSYNC TypeBitMap", l}
 				}
 			}
 			rr.TypeBitMap = append(rr.TypeBitMap, k)
 		default:
-			return nil, &ParseError{f, "bad CSYNC TypeBitMap", l}, ""
+			return &ParseError{"", "bad CSYNC TypeBitMap", l}
 		}
 		l, _ = c.Next()
 	}
-	return rr, nil, l.comment
+	return nil
 }
 
-func setSIG(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	r, e, s := setRRSIG(h, c, o, f)
-	if r != nil {
-		return &SIG{*r.(*RRSIG)}, e, s
-	}
-	return nil, e, s
-}
-
-func setRRSIG(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(RRSIG)
-	rr.Hdr = h
+func (rr *SIG) parse(c *zlexer, o string) *ParseError { return rr.RRSIG.parse(c, o) }
 
+func (rr *RRSIG) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, l.comment
-	}
-
 	tokenUpper := strings.ToUpper(l.token)
 	if t, ok := StringToType[tokenUpper]; !ok {
 		if strings.HasPrefix(tokenUpper, "TYPE") {
 			t, ok = typeToInt(l.token)
 			if !ok {
-				return nil, &ParseError{f, "bad RRSIG Typecovered", l}, ""
+				return &ParseError{"", "bad RRSIG Typecovered", l}
 			}
 			rr.TypeCovered = t
 		} else {
-			return nil, &ParseError{f, "bad RRSIG Typecovered", l}, ""
+			return &ParseError{"", "bad RRSIG Typecovered", l}
 		}
 	} else {
 		rr.TypeCovered = t
@@ -1109,25 +867,25 @@ func setRRSIG(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 
 	c.Next() // zBlank
 	l, _ = c.Next()
-	i, err := strconv.ParseUint(l.token, 10, 8)
-	if err != nil || l.err {
-		return nil, &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 nil, &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 nil, &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)
 
@@ -1135,11 +893,10 @@ func setRRSIG(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 	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 nil, &ParseError{f, "bad RRSIG Expiration", l}, ""
+			return &ParseError{"", "bad RRSIG Expiration", l}
 		}
 	} else {
 		rr.Expiration = i
@@ -1148,10 +905,10 @@ func setRRSIG(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 	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 nil, &ParseError{f, "bad RRSIG Inception", l}, ""
+			return &ParseError{"", "bad RRSIG Inception", l}
 		}
 	} else {
 		rr.Inception = i
@@ -1159,9 +916,9 @@ func setRRSIG(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 
 	c.Next() // zBlank
 	l, _ = c.Next()
-	i, err = strconv.ParseUint(l.token, 10, 16)
-	if err != nil || l.err {
-		return nil, &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)
 
@@ -1170,32 +927,24 @@ func setRRSIG(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 	rr.SignerName = l.token
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return nil, &ParseError{f, "bad RRSIG SignerName", l}, ""
+		return &ParseError{"", "bad RRSIG SignerName", l}
 	}
 	rr.SignerName = name
 
-	s, e, c1 := endingToString(c, "bad RRSIG Signature", f)
-	if e != nil {
-		return nil, e, c1
+	s, e4 := endingToString(c, "bad RRSIG Signature")
+	if e4 != nil {
+		return e4
 	}
 	rr.Signature = s
 
-	return rr, nil, c1
+	return nil
 }
 
-func setNSEC(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(NSEC)
-	rr.Hdr = h
-
+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 rr, nil, l.comment
-	}
-
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return nil, &ParseError{f, "bad NSEC NextDomain", l}, ""
+		return &ParseError{"", "bad NSEC NextDomain", l}
 	}
 	rr.NextDomain = name
 
@@ -1213,50 +962,43 @@ func setNSEC(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 			tokenUpper := strings.ToUpper(l.token)
 			if k, ok = StringToType[tokenUpper]; !ok {
 				if k, ok = typeToInt(l.token); !ok {
-					return nil, &ParseError{f, "bad NSEC TypeBitMap", l}, ""
+					return &ParseError{"", "bad NSEC TypeBitMap", l}
 				}
 			}
 			rr.TypeBitMap = append(rr.TypeBitMap, k)
 		default:
-			return nil, &ParseError{f, "bad NSEC TypeBitMap", l}, ""
+			return &ParseError{"", "bad NSEC TypeBitMap", l}
 		}
 		l, _ = c.Next()
 	}
-	return rr, nil, l.comment
+	return nil
 }
 
-func setNSEC3(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(NSEC3)
-	rr.Hdr = h
-
+func (rr *NSEC3) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, l.comment
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 8)
 	if e != nil || l.err {
-		return nil, &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 nil, &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 nil, &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 nil, &ParseError{f, "bad NSEC3 Salt", l}, ""
+		return &ParseError{"", "bad NSEC3 Salt", l}
 	}
 	if l.token != "-" {
 		rr.SaltLength = uint8(len(l.token)) / 2
@@ -1266,7 +1008,7 @@ func setNSEC3(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 	c.Next()
 	l, _ = c.Next()
 	if len(l.token) == 0 || l.err {
-		return nil, &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
@@ -1285,66 +1027,52 @@ func setNSEC3(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 			tokenUpper := strings.ToUpper(l.token)
 			if k, ok = StringToType[tokenUpper]; !ok {
 				if k, ok = typeToInt(l.token); !ok {
-					return nil, &ParseError{f, "bad NSEC3 TypeBitMap", l}, ""
+					return &ParseError{"", "bad NSEC3 TypeBitMap", l}
 				}
 			}
 			rr.TypeBitMap = append(rr.TypeBitMap, k)
 		default:
-			return nil, &ParseError{f, "bad NSEC3 TypeBitMap", l}, ""
+			return &ParseError{"", "bad NSEC3 TypeBitMap", l}
 		}
 		l, _ = c.Next()
 	}
-	return rr, nil, l.comment
+	return nil
 }
 
-func setNSEC3PARAM(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(NSEC3PARAM)
-	rr.Hdr = h
-
+func (rr *NSEC3PARAM) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, ""
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 8)
 	if e != nil || l.err {
-		return nil, &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 nil, &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 nil, &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 rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setEUI48(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(EUI48)
-	rr.Hdr = h
-
+func (rr *EUI48) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, ""
-	}
-
 	if len(l.token) != 17 || l.err {
-		return nil, &ParseError{f, "bad EUI48 Address", l}, ""
+		return &ParseError{"", "bad EUI48 Address", l}
 	}
 	addr := make([]byte, 12)
 	dash := 0
@@ -1353,7 +1081,7 @@ func setEUI48(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 		addr[i+1] = l.token[i+1+dash]
 		dash++
 		if l.token[i+1+dash] != '-' {
-			return nil, &ParseError{f, "bad EUI48 Address", l}, ""
+			return &ParseError{"", "bad EUI48 Address", l}
 		}
 	}
 	addr[10] = l.token[15]
@@ -1361,23 +1089,16 @@ func setEUI48(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 
 	i, e := strconv.ParseUint(string(addr), 16, 48)
 	if e != nil {
-		return nil, &ParseError{f, "bad EUI48 Address", l}, ""
+		return &ParseError{"", "bad EUI48 Address", l}
 	}
 	rr.Address = i
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setEUI64(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(EUI64)
-	rr.Hdr = h
-
+func (rr *EUI64) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, ""
-	}
-
 	if len(l.token) != 23 || l.err {
-		return nil, &ParseError{f, "bad EUI64 Address", l}, ""
+		return &ParseError{"", "bad EUI64 Address", l}
 	}
 	addr := make([]byte, 16)
 	dash := 0
@@ -1386,7 +1107,7 @@ func setEUI64(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 		addr[i+1] = l.token[i+1+dash]
 		dash++
 		if l.token[i+1+dash] != '-' {
-			return nil, &ParseError{f, "bad EUI64 Address", l}, ""
+			return &ParseError{"", "bad EUI64 Address", l}
 		}
 	}
 	addr[14] = l.token[21]
@@ -1394,209 +1115,156 @@ func setEUI64(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 
 	i, e := strconv.ParseUint(string(addr), 16, 64)
 	if e != nil {
-		return nil, &ParseError{f, "bad EUI68 Address", l}, ""
+		return &ParseError{"", "bad EUI68 Address", l}
 	}
-	rr.Address = uint64(i)
-	return rr, nil, ""
+	rr.Address = i
+	return slurpRemainder(c)
 }
 
-func setSSHFP(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(SSHFP)
-	rr.Hdr = h
-
+func (rr *SSHFP) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, ""
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 8)
 	if e != nil || l.err {
-		return nil, &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 nil, &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, c1 := endingToString(c, "bad SSHFP Fingerprint", f)
-	if e1 != nil {
-		return nil, e1, c1
+	s, e2 := endingToString(c, "bad SSHFP Fingerprint")
+	if e2 != nil {
+		return e2
 	}
 	rr.FingerPrint = s
-	return rr, nil, ""
+	return nil
 }
 
-func setDNSKEYs(h RR_Header, c *zlexer, o, f, typ string) (RR, *ParseError, string) {
-	rr := new(DNSKEY)
-	rr.Hdr = h
-
+func (rr *DNSKEY) parseDNSKEY(c *zlexer, o, typ string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, l.comment
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return nil, &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 nil, &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 nil, &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, c1 := endingToString(c, "bad "+typ+" PublicKey", f)
-	if e1 != nil {
-		return nil, e1, c1
+	s, e3 := endingToString(c, "bad "+typ+" PublicKey")
+	if e3 != nil {
+		return e3
 	}
 	rr.PublicKey = s
-	return rr, nil, c1
-}
-
-func setKEY(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	r, e, s := setDNSKEYs(h, c, o, f, "KEY")
-	if r != nil {
-		return &KEY{*r.(*DNSKEY)}, e, s
-	}
-	return nil, e, s
+	return nil
 }
 
-func setDNSKEY(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	r, e, s := setDNSKEYs(h, c, o, f, "DNSKEY")
-	return r, e, s
-}
-
-func setCDNSKEY(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	r, e, s := setDNSKEYs(h, c, o, f, "CDNSKEY")
-	if r != nil {
-		return &CDNSKEY{*r.(*DNSKEY)}, e, s
-	}
-	return nil, e, s
-}
-
-func setRKEY(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(RKEY)
-	rr.Hdr = h
+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 string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, l.comment
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return nil, &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 nil, &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 nil, &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, c1 := endingToString(c, "bad RKEY PublicKey", f)
-	if e1 != nil {
-		return nil, e1, c1
+	s, e3 := endingToString(c, "bad RKEY PublicKey")
+	if e3 != nil {
+		return e3
 	}
 	rr.PublicKey = s
-	return rr, nil, c1
+	return nil
 }
 
-func setEID(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(EID)
-	rr.Hdr = h
-	s, e, c1 := 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 nil, e, c1
+		return e
 	}
 	rr.Endpoint = s
-	return rr, nil, c1
+	return nil
 }
 
-func setNIMLOC(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(NIMLOC)
-	rr.Hdr = h
-	s, e, c1 := 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 nil, e, c1
+		return e
 	}
 	rr.Locator = s
-	return rr, nil, c1
+	return nil
 }
 
-func setGPOS(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(GPOS)
-	rr.Hdr = h
-
+func (rr *GPOS) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, ""
-	}
-
 	_, e := strconv.ParseFloat(l.token, 64)
 	if e != nil || l.err {
-		return nil, &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 nil, &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 nil, &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 rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setDSs(h RR_Header, c *zlexer, o, f, typ string) (RR, *ParseError, string) {
-	rr := new(DS)
-	rr.Hdr = h
-
+func (rr *DS) parseDS(c *zlexer, o, typ string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, l.comment
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return nil, &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 nil, &ParseError{f, "bad " + typ + " Algorithm", l}, ""
+			return &ParseError{"", "bad " + typ + " Algorithm", l}
 		}
 		rr.Algorithm = i
 	} else {
@@ -1604,61 +1272,33 @@ func setDSs(h RR_Header, c *zlexer, o, f, typ string) (RR, *ParseError, string)
 	}
 	c.Next() // zBlank
 	l, _ = c.Next()
-	i, e = strconv.ParseUint(l.token, 10, 8)
-	if e != nil || l.err {
-		return nil, &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, c1 := endingToString(c, "bad "+typ+" Digest", f)
-	if e1 != nil {
-		return nil, e1, c1
+	s, e2 := endingToString(c, "bad "+typ+" Digest")
+	if e2 != nil {
+		return e2
 	}
 	rr.Digest = s
-	return rr, nil, c1
-}
-
-func setDS(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	r, e, s := setDSs(h, c, o, f, "DS")
-	return r, e, s
+	return nil
 }
 
-func setDLV(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	r, e, s := setDSs(h, c, o, f, "DLV")
-	if r != nil {
-		return &DLV{*r.(*DS)}, e, s
-	}
-	return nil, e, s
-}
-
-func setCDS(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	r, e, s := setDSs(h, c, o, f, "CDS")
-	if r != nil {
-		return &CDS{*r.(*DS)}, e, s
-	}
-	return nil, e, s
-}
-
-func setTA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(TA)
-	rr.Hdr = h
-
+func (rr *TA) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, l.comment
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return nil, &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 nil, &ParseError{f, "bad TA Algorithm", l}, ""
+			return &ParseError{"", "bad TA Algorithm", l}
 		}
 		rr.Algorithm = i
 	} else {
@@ -1666,276 +1306,216 @@ func setTA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 	}
 	c.Next() // zBlank
 	l, _ = c.Next()
-	i, e = strconv.ParseUint(l.token, 10, 8)
-	if e != nil || l.err {
-		return nil, &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, c1 := endingToString(c, "bad TA Digest", f)
-	if err != nil {
-		return nil, err, c1
+	s, e2 := endingToString(c, "bad TA Digest")
+	if e2 != nil {
+		return e2
 	}
 	rr.Digest = s
-	return rr, nil, c1
+	return nil
 }
 
-func setTLSA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(TLSA)
-	rr.Hdr = h
-
+func (rr *TLSA) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, l.comment
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 8)
 	if e != nil || l.err {
-		return nil, &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 nil, &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 nil, &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, c1 := endingToString(c, "bad TLSA Certificate", f)
-	if e2 != nil {
-		return nil, e2, c1
+	s, e3 := endingToString(c, "bad TLSA Certificate")
+	if e3 != nil {
+		return e3
 	}
 	rr.Certificate = s
-	return rr, nil, c1
+	return nil
 }
 
-func setSMIMEA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(SMIMEA)
-	rr.Hdr = h
-
+func (rr *SMIMEA) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, l.comment
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 8)
 	if e != nil || l.err {
-		return nil, &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 nil, &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 nil, &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, c1 := endingToString(c, "bad SMIMEA Certificate", f)
-	if e2 != nil {
-		return nil, e2, c1
+	s, e3 := endingToString(c, "bad SMIMEA Certificate")
+	if e3 != nil {
+		return e3
 	}
 	rr.Certificate = s
-	return rr, nil, c1
+	return nil
 }
 
-func setRFC3597(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(RFC3597)
-	rr.Hdr = h
-
+func (rr *RFC3597) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
 	if l.token != "\\#" {
-		return nil, &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 nil, &ParseError{f, "bad RFC3597 Rdata ", l}, ""
+		return &ParseError{"", "bad RFC3597 Rdata ", l}
 	}
 
-	s, e1, c1 := endingToString(c, "bad RFC3597 Rdata", f)
+	s, e1 := endingToString(c, "bad RFC3597 Rdata")
 	if e1 != nil {
-		return nil, e1, c1
+		return e1
 	}
 	if rdlength*2 != len(s) {
-		return nil, &ParseError{f, "bad RFC3597 Rdata", l}, ""
+		return &ParseError{"", "bad RFC3597 Rdata", l}
 	}
 	rr.Rdata = s
-	return rr, nil, c1
+	return nil
 }
 
-func setSPF(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(SPF)
-	rr.Hdr = h
-
-	s, e, c1 := 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 nil, e, ""
+		return e
 	}
 	rr.Txt = s
-	return rr, nil, c1
+	return nil
 }
 
-func setAVC(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(AVC)
-	rr.Hdr = h
-
-	s, e, c1 := 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 nil, e, ""
+		return e
 	}
 	rr.Txt = s
-	return rr, nil, c1
+	return nil
 }
 
-func setTXT(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(TXT)
-	rr.Hdr = h
-
+func (rr *TXT) parse(c *zlexer, o string) *ParseError {
 	// no zBlank reading here, because all this rdata is TXT
-	s, e, c1 := endingToTxtSlice(c, "bad TXT Txt", f)
+	s, e := endingToTxtSlice(c, "bad TXT Txt")
 	if e != nil {
-		return nil, e, ""
+		return e
 	}
 	rr.Txt = s
-	return rr, nil, c1
+	return nil
 }
 
 // identical to setTXT
-func setNINFO(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(NINFO)
-	rr.Hdr = h
-
-	s, e, c1 := 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 nil, e, ""
+		return e
 	}
 	rr.ZSData = s
-	return rr, nil, c1
+	return nil
 }
 
-func setURI(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(URI)
-	rr.Hdr = h
-
+func (rr *URI) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, ""
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return nil, &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 nil, &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, c1 := endingToTxtSlice(c, "bad URI Target", f)
-	if err != nil {
-		return nil, err, ""
+	s, e2 := endingToTxtSlice(c, "bad URI Target")
+	if e2 != nil {
+		return e2
 	}
 	if len(s) != 1 {
-		return nil, &ParseError{f, "bad URI Target", l}, ""
+		return &ParseError{"", "bad URI Target", l}
 	}
 	rr.Target = s[0]
-	return rr, nil, c1
+	return nil
 }
 
-func setDHCID(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
+func (rr *DHCID) parse(c *zlexer, o string) *ParseError {
 	// awesome record to parse!
-	rr := new(DHCID)
-	rr.Hdr = h
-
-	s, e, c1 := endingToString(c, "bad DHCID Digest", f)
+	s, e := endingToString(c, "bad DHCID Digest")
 	if e != nil {
-		return nil, e, c1
+		return e
 	}
 	rr.Digest = s
-	return rr, nil, c1
+	return nil
 }
 
-func setNID(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(NID)
-	rr.Hdr = h
-
+func (rr *NID) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, ""
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return nil, &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 nil, err, ""
+	u, e1 := stringToNodeID(l)
+	if e1 != nil || l.err {
+		return e1
 	}
 	rr.NodeID = u
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setL32(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(L32)
-	rr.Hdr = h
-
+func (rr *L32) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, ""
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return nil, &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 nil, &ParseError{f, "bad L32 Locator", l}, ""
+		return &ParseError{"", "bad L32 Locator", l}
 	}
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setLP(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(LP)
-	rr.Hdr = h
-
+func (rr *LP) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, ""
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return nil, &ParseError{f, "bad LP Preference", l}, ""
+		return &ParseError{"", "bad LP Preference", l}
 	}
 	rr.Preference = uint16(i)
 
@@ -1944,98 +1524,66 @@ func setLP(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 	rr.Fqdn = l.token
 	name, nameOk := toAbsoluteName(l.token, o)
 	if l.err || !nameOk {
-		return nil, &ParseError{f, "bad LP Fqdn", l}, ""
+		return &ParseError{"", "bad LP Fqdn", l}
 	}
 	rr.Fqdn = name
-
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setL64(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(L64)
-	rr.Hdr = h
-
+func (rr *L64) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, ""
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return nil, &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 nil, err, ""
+	u, e1 := stringToNodeID(l)
+	if e1 != nil || l.err {
+		return e1
 	}
 	rr.Locator64 = u
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setUID(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(UID)
-	rr.Hdr = h
-
+func (rr *UID) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, ""
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 32)
 	if e != nil || l.err {
-		return nil, &ParseError{f, "bad UID Uid", l}, ""
+		return &ParseError{"", "bad UID Uid", l}
 	}
 	rr.Uid = uint32(i)
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setGID(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(GID)
-	rr.Hdr = h
-
+func (rr *GID) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, ""
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 32)
 	if e != nil || l.err {
-		return nil, &ParseError{f, "bad GID Gid", l}, ""
+		return &ParseError{"", "bad GID Gid", l}
 	}
 	rr.Gid = uint32(i)
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setUINFO(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(UINFO)
-	rr.Hdr = h
-
-	s, e, c1 := 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 nil, e, c1
+		return e
 	}
 	if ln := len(s); ln == 0 {
-		return rr, nil, c1
+		return nil
 	}
 	rr.Uinfo = s[0] // silently discard anything after the first character-string
-	return rr, nil, c1
+	return nil
 }
 
-func setPX(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(PX)
-	rr.Hdr = h
-
+func (rr *PX) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, ""
-	}
-
 	i, e := strconv.ParseUint(l.token, 10, 16)
 	if e != nil || l.err {
-		return nil, &ParseError{f, "bad PX Preference", l}, ""
+		return &ParseError{"", "bad PX Preference", l}
 	}
 	rr.Preference = uint16(i)
 
@@ -2044,7 +1592,7 @@ func setPX(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 	rr.Map822 = l.token
 	map822, map822Ok := toAbsoluteName(l.token, o)
 	if l.err || !map822Ok {
-		return nil, &ParseError{f, "bad PX Map822", l}, ""
+		return &ParseError{"", "bad PX Map822", l}
 	}
 	rr.Map822 = map822
 
@@ -2053,157 +1601,142 @@ func setPX(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
 	rr.Mapx400 = l.token
 	mapx400, mapx400Ok := toAbsoluteName(l.token, o)
 	if l.err || !mapx400Ok {
-		return nil, &ParseError{f, "bad PX Mapx400", l}, ""
+		return &ParseError{"", "bad PX Mapx400", l}
 	}
 	rr.Mapx400 = mapx400
-
-	return rr, nil, ""
+	return slurpRemainder(c)
 }
 
-func setCAA(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(CAA)
-	rr.Hdr = h
-
+func (rr *CAA) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
-	if len(l.token) == 0 { // dynamic update rr.
-		return rr, nil, l.comment
-	}
-
-	i, err := strconv.ParseUint(l.token, 10, 8)
-	if err != nil || l.err {
-		return nil, &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 nil, &ParseError{f, "bad CAA Tag", l}, ""
+		return &ParseError{"", "bad CAA Tag", l}
 	}
 	rr.Tag = l.token
 
 	c.Next() // zBlank
-	s, e, c1 := endingToTxtSlice(c, "bad CAA Value", f)
-	if e != nil {
-		return nil, e, ""
+	s, e1 := endingToTxtSlice(c, "bad CAA Value")
+	if e1 != nil {
+		return e1
 	}
 	if len(s) != 1 {
-		return nil, &ParseError{f, "bad CAA Value", l}, ""
+		return &ParseError{"", "bad CAA Value", l}
 	}
 	rr.Value = s[0]
-	return rr, nil, c1
+	return nil
 }
 
-func setTKEY(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
-	rr := new(TKEY)
-	rr.Hdr = h
-
+func (rr *TKEY) parse(c *zlexer, o string) *ParseError {
 	l, _ := c.Next()
 
 	// Algorithm
 	if l.value != zString {
-		return nil, &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 nil, &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 nil, &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 nil, &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 nil, &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,
+		})
+	}
 
-	return rr, nil, ""
-}
-
-var typeToparserFunc = map[uint16]parserFunc{
-	TypeAAAA:       {setAAAA, false},
-	TypeAFSDB:      {setAFSDB, false},
-	TypeA:          {setA, false},
-	TypeCAA:        {setCAA, true},
-	TypeCDS:        {setCDS, true},
-	TypeCDNSKEY:    {setCDNSKEY, true},
-	TypeCERT:       {setCERT, true},
-	TypeCNAME:      {setCNAME, false},
-	TypeCSYNC:      {setCSYNC, true},
-	TypeDHCID:      {setDHCID, true},
-	TypeDLV:        {setDLV, true},
-	TypeDNAME:      {setDNAME, false},
-	TypeKEY:        {setKEY, true},
-	TypeDNSKEY:     {setDNSKEY, true},
-	TypeDS:         {setDS, true},
-	TypeEID:        {setEID, true},
-	TypeEUI48:      {setEUI48, false},
-	TypeEUI64:      {setEUI64, false},
-	TypeGID:        {setGID, false},
-	TypeGPOS:       {setGPOS, false},
-	TypeHINFO:      {setHINFO, true},
-	TypeHIP:        {setHIP, true},
-	TypeKX:         {setKX, false},
-	TypeL32:        {setL32, false},
-	TypeL64:        {setL64, false},
-	TypeLOC:        {setLOC, true},
-	TypeLP:         {setLP, false},
-	TypeMB:         {setMB, false},
-	TypeMD:         {setMD, false},
-	TypeMF:         {setMF, false},
-	TypeMG:         {setMG, false},
-	TypeMINFO:      {setMINFO, false},
-	TypeMR:         {setMR, false},
-	TypeMX:         {setMX, false},
-	TypeNAPTR:      {setNAPTR, false},
-	TypeNID:        {setNID, false},
-	TypeNIMLOC:     {setNIMLOC, true},
-	TypeNINFO:      {setNINFO, true},
-	TypeNSAPPTR:    {setNSAPPTR, false},
-	TypeNSEC3PARAM: {setNSEC3PARAM, false},
-	TypeNSEC3:      {setNSEC3, true},
-	TypeNSEC:       {setNSEC, true},
-	TypeNS:         {setNS, false},
-	TypeOPENPGPKEY: {setOPENPGPKEY, true},
-	TypePTR:        {setPTR, false},
-	TypePX:         {setPX, false},
-	TypeSIG:        {setSIG, true},
-	TypeRKEY:       {setRKEY, true},
-	TypeRP:         {setRP, false},
-	TypeRRSIG:      {setRRSIG, true},
-	TypeRT:         {setRT, false},
-	TypeSMIMEA:     {setSMIMEA, true},
-	TypeSOA:        {setSOA, false},
-	TypeSPF:        {setSPF, true},
-	TypeAVC:        {setAVC, true},
-	TypeSRV:        {setSRV, false},
-	TypeSSHFP:      {setSSHFP, true},
-	TypeTALINK:     {setTALINK, false},
-	TypeTA:         {setTA, true},
-	TypeTLSA:       {setTLSA, true},
-	TypeTXT:        {setTXT, true},
-	TypeUID:        {setUID, false},
-	TypeUINFO:      {setUINFO, true},
-	TypeURI:        {setURI, true},
-	TypeX25:        {setX25, false},
-	TypeTKEY:       {setTKEY, true},
+	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 4b4ec33c..30dfd41d 100644
--- a/vendor/github.com/miekg/dns/server.go
+++ b/vendor/github.com/miekg/dns/server.go
@@ -3,7 +3,6 @@
 package dns
 
 import (
-	"bytes"
 	"context"
 	"crypto/tls"
 	"encoding/binary"
@@ -12,26 +11,12 @@ import (
 	"net"
 	"strings"
 	"sync"
-	"sync/atomic"
 	"time"
 )
 
 // Default maximum number of TCP queries before we close the socket.
 const maxTCPQueries = 128
 
-// The maximum number of idle workers.
-//
-// This controls the maximum number of workers that are allowed to stay
-// idle waiting for incoming requests before being torn down.
-//
-// If this limit is reached, the server will just keep spawning new
-// workers (goroutines) for each incoming request. In this case, each
-// worker will only be used for a single request.
-const maxIdleWorkersCount = 10000
-
-// The maximum length of time a worker may idle for before being destroyed.
-const idleWorkerTimeout = 10 * time.Second
-
 // aLongTimeAgo is a non-zero time, far in the past, used for
 // immediate cancelation of network operations.
 var aLongTimeAgo = time.Unix(1, 0)
@@ -81,20 +66,28 @@ type ConnectionStater interface {
 }
 
 type response struct {
-	msg            []byte
+	closed         bool // connection has been closed
 	hijacked       bool // connection has been hijacked by handler
 	tsigTimersOnly bool
 	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
-	wg             *sync.WaitGroup   // for gracefull shutdown
+}
+
+// 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)
@@ -155,22 +148,40 @@ 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
 }
 
-func (dr *defaultReader) ReadTCP(conn net.Conn, timeout time.Duration) ([]byte, error) {
+var _ PacketConnReader = defaultReader{}
+
+func (dr defaultReader) ReadTCP(conn net.Conn, timeout time.Duration) ([]byte, error) {
 	return dr.readTCP(conn, timeout)
 }
 
-func (dr *defaultReader) ReadUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error) {
+func (dr defaultReader) ReadUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error) {
 	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.
@@ -202,9 +213,6 @@ type Server struct {
 	IdleTimeout func() time.Duration
 	// Secret(s) for Tsig map[<zonename>]<base64 secret>. The zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2).
 	TsigSecret map[string]string
-	// Unsafe instructs the server to disregard any sanity checks and directly hand the message to
-	// the handler. It will specifically not check if the query has the QR bit not set.
-	Unsafe bool
 	// If NotifyStartedFunc is set it is called once the server has started listening.
 	NotifyStartedFunc func()
 	// DecorateReader is optional, allows customization of the process that reads raw DNS messages.
@@ -216,11 +224,9 @@ type Server struct {
 	// Whether to set the SO_REUSEPORT socket option, allowing multiple listeners to be bound to a single address.
 	// It is only supported on go1.11+ and when using ListenAndServe.
 	ReusePort bool
-
-	// UDP packet or TCP connection queue
-	queue chan *response
-	// Workers count
-	workersCount int32
+	// AcceptMsgFunc will check the incoming message and will reject it early in the process.
+	// By default DefaultMsgAcceptFunc will be used.
+	MsgAcceptFunc MsgAcceptFunc
 
 	// Shutdown handling
 	lock     sync.RWMutex
@@ -239,51 +245,6 @@ func (srv *Server) isStarted() bool {
 	return started
 }
 
-func (srv *Server) worker(w *response) {
-	srv.serve(w)
-
-	for {
-		count := atomic.LoadInt32(&srv.workersCount)
-		if count > maxIdleWorkersCount {
-			return
-		}
-		if atomic.CompareAndSwapInt32(&srv.workersCount, count, count+1) {
-			break
-		}
-	}
-
-	defer atomic.AddInt32(&srv.workersCount, -1)
-
-	inUse := false
-	timeout := time.NewTimer(idleWorkerTimeout)
-	defer timeout.Stop()
-LOOP:
-	for {
-		select {
-		case w, ok := <-srv.queue:
-			if !ok {
-				break LOOP
-			}
-			inUse = true
-			srv.serve(w)
-		case <-timeout.C:
-			if !inUse {
-				break LOOP
-			}
-			inUse = false
-			timeout.Reset(idleWorkerTimeout)
-		}
-	}
-}
-
-func (srv *Server) spawnWorker(w *response) {
-	select {
-	case srv.queue <- w:
-	default:
-		go srv.worker(w)
-	}
-}
-
 func makeUDPBuffer(size int) func() interface{} {
 	return func() interface{} {
 		return make([]byte, size)
@@ -291,14 +252,18 @@ func makeUDPBuffer(size int) func() interface{} {
 }
 
 func (srv *Server) init() {
-	srv.queue = make(chan *response)
-
 	srv.shutdown = make(chan struct{})
 	srv.conns = make(map[net.Conn]struct{})
 
 	if srv.UDPSize == 0 {
 		srv.UDPSize = MinMsgSize
 	}
+	if srv.MsgAcceptFunc == nil {
+		srv.MsgAcceptFunc = DefaultMsgAcceptFunc
+	}
+	if srv.Handler == nil {
+		srv.Handler = DefaultServeMux
+	}
 
 	srv.udpPool.New = makeUDPBuffer(srv.UDPSize)
 }
@@ -324,7 +289,6 @@ func (srv *Server) ListenAndServe() error {
 	}
 
 	srv.init()
-	defer close(srv.queue)
 
 	switch srv.Net {
 	case "tcp", "tcp4", "tcp6":
@@ -379,26 +343,23 @@ func (srv *Server) ActivateAndServe() error {
 	}
 
 	srv.init()
-	defer close(srv.queue)
 
-	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"}
 }
@@ -459,11 +420,10 @@ var testShutdownNotify *sync.Cond
 
 // getReadTimeout is a helper func to use system timeout if server did not intend to change it.
 func (srv *Server) getReadTimeout() time.Duration {
-	rtimeout := dnsTimeout
 	if srv.ReadTimeout != 0 {
-		rtimeout = srv.ReadTimeout
+		return srv.ReadTimeout
 	}
-	return rtimeout
+	return dnsTimeout
 }
 
 // serveTCP starts a TCP listener for the server.
@@ -496,29 +456,31 @@ func (srv *Server) serveTCP(l net.Listener) error {
 		srv.conns[rw] = struct{}{}
 		srv.lock.Unlock()
 		wg.Add(1)
-		srv.spawnWorker(&response{
-			tsigSecret: srv.TsigSecret,
-			tcp:        rw,
-			wg:         &wg,
-		})
+		go srv.serveTCPConn(&wg, rw)
 	}
 
 	return nil
 }
 
 // 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})
+	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()
@@ -528,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
@@ -545,46 +517,22 @@ func (srv *Server) serveUDP(l *net.UDPConn) error {
 			continue
 		}
 		wg.Add(1)
-		srv.spawnWorker(&response{
-			msg:        m,
-			tsigSecret: srv.TsigSecret,
-			udp:        l,
-			udpSession: s,
-			wg:         &wg,
-		})
+		go srv.serveUDPPacket(&wg, m, l, sUDP, sPC)
 	}
 
 	return nil
 }
 
-func (srv *Server) serve(w *response) {
+// Serve a new TCP connection.
+func (srv *Server) serveTCPConn(wg *sync.WaitGroup, rw net.Conn) {
+	w := &response{tsigSecret: srv.TsigSecret, tcp: rw}
 	if srv.DecorateWriter != nil {
 		w.writer = srv.DecorateWriter(w)
 	} else {
 		w.writer = w
 	}
 
-	if w.udp != nil {
-		// serve UDP
-		srv.serveDNS(w)
-
-		w.wg.Done()
-		return
-	}
-
-	defer func() {
-		if !w.hijacked {
-			w.Close()
-		}
-
-		srv.lock.Lock()
-		delete(srv.conns, w.tcp)
-		srv.lock.Unlock()
-
-		w.wg.Done()
-	}()
-
-	reader := Reader(&defaultReader{srv})
+	reader := Reader(defaultReader{srv})
 	if srv.DecorateReader != nil {
 		reader = srv.DecorateReader(reader)
 	}
@@ -602,14 +550,13 @@ func (srv *Server) serve(w *response) {
 	}
 
 	for q := 0; (q < limit || limit == -1) && srv.isStarted(); q++ {
-		var err error
-		w.msg, err = reader.ReadTCP(w.tcp, timeout)
+		m, err := reader.ReadTCP(w.tcp, timeout)
 		if err != nil {
 			// TODO(tmthrgd): handle error
 			break
 		}
-		srv.serveDNS(w)
-		if w.tcp == nil {
+		srv.serveDNS(m, w)
+		if w.closed {
 			break // Close() was called
 		}
 		if w.hijacked {
@@ -619,25 +566,67 @@ func (srv *Server) serve(w *response) {
 		// idle timeout.
 		timeout = idleTimeout
 	}
+
+	if !w.hijacked {
+		w.Close()
+	}
+
+	srv.lock.Lock()
+	delete(srv.conns, w.tcp)
+	srv.lock.Unlock()
+
+	wg.Done()
 }
 
-func (srv *Server) disposeBuffer(w *response) {
-	if w.udp != nil && cap(w.msg) == srv.UDPSize {
-		srv.udpPool.Put(w.msg[:srv.UDPSize])
+// Serve a new UDP request.
+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 {
+		w.writer = w
 	}
-	w.msg = nil
+
+	srv.serveDNS(m, w)
+	wg.Done()
 }
 
-func (srv *Server) serveDNS(w *response) {
+func (srv *Server) serveDNS(m []byte, w *response) {
+	dh, off, err := unpackMsgHdr(m, 0)
+	if err != nil {
+		// Let client hang, they are sending crap; any reply can be used to amplify.
+		return
+	}
+
 	req := new(Msg)
-	err := req.Unpack(w.msg)
-	if err != nil { // Send a FormatError back
-		x := new(Msg)
-		x.SetRcodeFormatError(req)
-		w.WriteMsg(x)
-	}
-	if err != nil || !srv.Unsafe && req.Response {
-		srv.disposeBuffer(w)
+	req.setHdr(dh)
+
+	switch action := srv.MsgAcceptFunc(dh); action {
+	case MsgAccept:
+		if req.unpack(dh, m, off) == nil {
+			break
+		}
+
+		fallthrough
+	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
 	}
 
@@ -645,7 +634,7 @@ func (srv *Server) serveDNS(w *response) {
 	if w.tsigSecret != nil {
 		if t := req.IsTsig(); t != nil {
 			if secret, ok := w.tsigSecret[t.Hdr.Name]; ok {
-				w.tsigStatus = TsigVerify(w.msg, secret, "", false)
+				w.tsigStatus = TsigVerify(m, secret, "", false)
 			} else {
 				w.tsigStatus = ErrSecret
 			}
@@ -654,14 +643,11 @@ func (srv *Server) serveDNS(w *response) {
 		}
 	}
 
-	srv.disposeBuffer(w)
-
-	handler := srv.Handler
-	if handler == nil {
-		handler = DefaultServeMux
+	if w.udp != nil && cap(m) == srv.UDPSize {
+		srv.udpPool.Put(m[:srv.UDPSize])
 	}
 
-	handler.ServeDNS(w, req) // Writes back to the client
+	srv.Handler.ServeDNS(w, req) // Writes back to the client
 }
 
 func (srv *Server) readTCP(conn net.Conn, timeout time.Duration) ([]byte, error) {
@@ -675,36 +661,16 @@ func (srv *Server) readTCP(conn net.Conn, timeout time.Duration) ([]byte, error)
 	}
 	srv.lock.RUnlock()
 
-	l := make([]byte, 2)
-	n, err := conn.Read(l)
-	if err != nil || n != 2 {
-		if err != nil {
-			return nil, err
-		}
-		return nil, ErrShortRead
-	}
-	length := binary.BigEndian.Uint16(l)
-	if length == 0 {
-		return nil, ErrShortRead
-	}
-	m := make([]byte, int(length))
-	n, err = conn.Read(m[:int(length)])
-	if err != nil || n == 0 {
-		if err != nil {
-			return nil, err
-		}
-		return nil, ErrShortRead
+	var length uint16
+	if err := binary.Read(conn, binary.BigEndian, &length); err != nil {
+		return nil, err
 	}
-	i := n
-	for i < int(length) {
-		j, err := conn.Read(m[i:int(length)])
-		if err != nil {
-			return nil, err
-		}
-		i += j
+
+	m := make([]byte, length)
+	if _, err := io.ReadFull(conn, m); err != nil {
+		return nil, err
 	}
-	n = i
-	m = m[:n]
+
 	return m, nil
 }
 
@@ -726,8 +692,30 @@ 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 {
+		return &Error{err: "WriteMsg called after Close"}
+	}
+
 	var data []byte
 	if w.tsigSecret != nil { // if no secrets, dont check for the tsig (which is a longer check)
 		if t := m.IsTsig(); t != nil {
@@ -749,26 +737,28 @@ func (w *response) WriteMsg(m *Msg) (err error) {
 
 // Write implements the ResponseWriter.Write method.
 func (w *response) Write(m []byte) (int, error) {
+	if w.closed {
+		return 0, &Error{err: "Write called after Close"}
+	}
+
 	switch {
 	case w.udp != nil:
-		n, err := WriteToSessionUDP(w.udp, m, w.udpSession)
-		return n, err
-	case w.tcp != nil:
-		lm := len(m)
-		if lm < 2 {
-			return 0, io.ErrShortBuffer
+		if u, ok := w.udp.(*net.UDPConn); ok {
+			return WriteToSessionUDP(u, m, w.udpSession)
 		}
-		if lm > MaxMsgSize {
+		return w.udp.WriteTo(m, w.pcSession)
+	case w.tcp != nil:
+		if len(m) > MaxMsgSize {
 			return 0, &Error{err: "message too large"}
 		}
-		l := make([]byte, 2, 2+lm)
-		binary.BigEndian.PutUint16(l, uint16(lm))
-		m = append(l, m...)
 
-		n, err := io.Copy(w.tcp, bytes.NewReader(m))
+		l := make([]byte, 2)
+		binary.BigEndian.PutUint16(l, uint16(len(m)))
+
+		n, err := (&net.Buffers{l, m}).WriteTo(w.tcp)
 		return int(n), err
 	default:
-		panic("dns: Write called after Close")
+		panic("dns: internal error: udp and tcp both nil")
 	}
 }
 
@@ -780,7 +770,7 @@ func (w *response) LocalAddr() net.Addr {
 	case w.tcp != nil:
 		return w.tcp.LocalAddr()
 	default:
-		panic("dns: LocalAddr called after Close")
+		panic("dns: internal error: udp and tcp both nil")
 	}
 }
 
@@ -789,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: RemoteAddr called after Close")
+		panic("dns: internal error: udpSession, pcSession and tcp are all nil")
 	}
 }
 
@@ -807,13 +799,20 @@ func (w *response) Hijack() { w.hijacked = true }
 
 // Close implements the ResponseWriter.Close method
 func (w *response) Close() error {
-	// Can't close the udp conn, as that is actually the listener.
-	if w.tcp != nil {
-		e := w.tcp.Close()
-		w.tcp = nil
-		return e
+	if w.closed {
+		return &Error{err: "connection already closed"}
+	}
+	w.closed = true
+
+	switch {
+	case w.udp != nil:
+		// Can't close the udp conn, as that is actually the listener.
+		return nil
+	case w.tcp != nil:
+		return w.tcp.Close()
+	default:
+		panic("dns: internal error: udp and tcp both nil")
 	}
-	return nil
 }
 
 // ConnectionState() implements the ConnectionStater.ConnectionState() interface.
diff --git a/vendor/github.com/miekg/dns/sig0.go b/vendor/github.com/miekg/dns/sig0.go
index 07c2acb1..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"
@@ -21,15 +20,11 @@ func (rr *SIG) Sign(k crypto.Signer, m *Msg) ([]byte, error) {
 	if rr.KeyTag == 0 || len(rr.SignerName) == 0 || rr.Algorithm == 0 {
 		return nil, ErrKey
 	}
-	rr.Header().Rrtype = TypeSIG
-	rr.Header().Class = ClassANY
-	rr.Header().Ttl = 0
-	rr.Header().Name = "."
-	rr.OrigTtl = 0
-	rr.TypeCovered = 0
-	rr.Labels = 0
 
-	buf := make([]byte, m.Len()+rr.len())
+	rr.Hdr = RR_Header{Name: ".", Rrtype: TypeSIG, Class: ClassANY, Ttl: 0}
+	rr.OrigTtl, rr.TypeCovered, rr.Labels = 0, 0, 0
+
+	buf := make([]byte, m.Len()+Len(rr))
 	mbuf, err := m.PackBuffer(buf)
 	if err != nil {
 		return nil, err
@@ -89,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
@@ -107,7 +102,7 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
 	anc := binary.BigEndian.Uint16(buf[6:])
 	auc := binary.BigEndian.Uint16(buf[8:])
 	adc := binary.BigEndian.Uint16(buf[10:])
-	offset := 12
+	offset := headerSize
 	var err error
 	for i := uint16(0); i < qdc && offset < buflen; i++ {
 		_, offset, err = UnpackDomainName(buf, offset)
@@ -167,7 +162,7 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
 	}
 	// If key has come from the DNS name compression might
 	// have mangled the case of the name
-	if strings.ToLower(signername) != strings.ToLower(k.Header().Name) {
+	if !strings.EqualFold(signername, k.Header().Name) {
 		return &Error{err: "signer name doesn't match key name"}
 	}
 	sigend := offset
@@ -182,19 +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 := big.NewInt(0)
-		r.SetBytes(sig[:len(sig)/2])
-		s := big.NewInt(0)
-		s.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 {
@@ -202,10 +184,8 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
 		}
 	case ECDSAP256SHA256, ECDSAP384SHA384:
 		pk := k.publicKeyECDSA()
-		r := big.NewInt(0)
-		r.SetBytes(sig[:len(sig)/2])
-		s := big.NewInt(0)
-		s.SetBytes(sig[len(sig)/2:])
+		r := new(big.Int).SetBytes(sig[:len(sig)/2])
+		s := new(big.Int).SetBytes(sig[len(sig)/2:])
 		if pk != nil {
 			if ecdsa.Verify(pk, hashed, r, s) {
 				return nil
diff --git a/vendor/github.com/miekg/dns/singleinflight.go b/vendor/github.com/miekg/dns/singleinflight.go
index 9573c7d0..febcc300 100644
--- a/vendor/github.com/miekg/dns/singleinflight.go
+++ b/vendor/github.com/miekg/dns/singleinflight.go
@@ -23,6 +23,8 @@ type call struct {
 type singleflight struct {
 	sync.Mutex                  // protects m
 	m          map[string]*call // lazily initialized
+
+	dontDeleteForTesting bool // this is only to be used by TestConcurrentExchanges
 }
 
 // Do executes and returns the results of the given function, making
@@ -49,9 +51,11 @@ func (g *singleflight) Do(key string, fn func() (*Msg, time.Duration, error)) (v
 	c.val, c.rtt, c.err = fn()
 	c.wg.Done()
 
-	g.Lock()
-	delete(g.m, key)
-	g.Unlock()
+	if !g.dontDeleteForTesting {
+		g.Lock()
+		delete(g.m, key)
+		g.Unlock()
+	}
 
 	return c.val, c.rtt, c.err, c.dups > 0
 }
diff --git a/vendor/github.com/miekg/dns/smimea.go b/vendor/github.com/miekg/dns/smimea.go
index 4e7ded4b..89f09f0d 100644
--- a/vendor/github.com/miekg/dns/smimea.go
+++ b/vendor/github.com/miekg/dns/smimea.go
@@ -14,10 +14,7 @@ func (r *SMIMEA) Sign(usage, selector, matchingType int, cert *x509.Certificate)
 	r.MatchingType = uint8(matchingType)
 
 	r.Certificate, err = CertificateToDANE(r.Selector, r.MatchingType, cert)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 // Verify verifies a SMIMEA record against an SSL certificate. If it is OK
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/tlsa.go b/vendor/github.com/miekg/dns/tlsa.go
index 431e2fb5..4e07983b 100644
--- a/vendor/github.com/miekg/dns/tlsa.go
+++ b/vendor/github.com/miekg/dns/tlsa.go
@@ -14,10 +14,7 @@ func (r *TLSA) Sign(usage, selector, matchingType int, cert *x509.Certificate) (
 	r.MatchingType = uint8(matchingType)
 
 	r.Certificate, err = CertificateToDANE(r.Selector, r.MatchingType, cert)
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 // Verify verifies a TLSA record against an SSL certificate. If it is OK
diff --git a/vendor/github.com/miekg/dns/tsig.go b/vendor/github.com/miekg/dns/tsig.go
index 4837b4ab..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,6 +56,10 @@ func (rr *TSIG) String() string {
 	return s
 }
 
+func (rr *TSIG) parse(c *zlexer, origin string) *ParseError {
+	panic("dns: internal error: parse should never be called on TSIG")
+}
+
 // The following values must be put in wireformat, so that the MAC can be calculated.
 // RFC 2845, section 3.4.2. TSIG Variables.
 type tsigWireFmt struct {
@@ -107,39 +113,39 @@ 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, []byte(rawsecret))
+	switch CanonicalName(rr.Algorithm) {
 	case HmacSHA1:
-		h = hmac.New(sha1.New, []byte(rawsecret))
+		h = hmac.New(sha1.New, rawsecret)
+	case HmacSHA224:
+		h = hmac.New(sha256.New224, rawsecret)
 	case HmacSHA256:
-		h = hmac.New(sha256.New, []byte(rawsecret))
+		h = hmac.New(sha256.New, rawsecret)
+	case HmacSHA384:
+		h = hmac.New(sha512.New384, rawsecret)
 	case HmacSHA512:
-		h = hmac.New(sha512.New, []byte(rawsecret))
+		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, t.len())
-	if off, err := PackRR(t, tbuf, 0, nil, false); err == nil {
-		tbuf = tbuf[:off] // reset to actual size used
-	} else {
+	tbuf := make([]byte, Len(t))
+	off, err := PackRR(t, tbuf, 0, nil, false)
+	if err != nil {
 		return nil, "", err
 	}
-	mbuf = append(mbuf, tbuf...)
+	mbuf = append(mbuf, tbuf[:off]...)
 	// Update the ArCount directly in the buffer.
 	binary.BigEndian.PutUint16(mbuf[10:], uint16(len(m.Extra)+1))
 
@@ -150,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
@@ -165,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:
@@ -195,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())
@@ -216,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]
 	}
 
@@ -225,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]
 	}
 
@@ -248,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 115f2c7b..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.
@@ -205,21 +209,23 @@ var CertTypeToString = map[uint16]string{
 	CertOID:     "OID",
 }
 
-// StringToCertType is the reverseof CertTypeToString.
-var StringToCertType = reverseInt16(CertTypeToString)
-
 //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
 	Qclass uint16
 }
 
-func (q *Question) len() int {
-	return len(q.Name) + 1 + 2 + 2
+func (q *Question) len(off int, compression map[string]struct{}) int {
+	l := domainNameLen(q.Name, off, compression, true)
+	l += 2 + 2
+	return l
 }
 
 func (q *Question) String() (s string) {
@@ -230,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
@@ -239,6 +245,25 @@ type ANY struct {
 
 func (rr *ANY) String() string { return rr.Hdr.String() }
 
+func (rr *ANY) parse(c *zlexer, origin string) *ParseError {
+	panic("dns: internal error: parse should never be called on ANY")
+}
+
+// NULL RR. See RFC 1035.
+type NULL struct {
+	Hdr  RR_Header
+	Data string `dns:"any"`
+}
+
+func (rr *NULL) String() string {
+	// There is no presentation format; prefix string with a comment.
+	return ";" + rr.Hdr.String() + rr.Data
+}
+
+func (rr *NULL) parse(c *zlexer, origin string) *ParseError {
+	panic("dns: internal error: parse should never be called on NULL")
+}
+
 // CNAME RR. See RFC 1034.
 type CNAME struct {
 	Hdr    RR_Header
@@ -351,7 +376,7 @@ func (rr *X25) String() string {
 type RT struct {
 	Hdr        RR_Header
 	Preference uint16
-	Host       string `dns:"cdomain-name"`
+	Host       string `dns:"domain-name"` // RFC 3597 prohibits compressing records not defined in RFC 1035.
 }
 
 func (rr *RT) String() string {
@@ -386,7 +411,7 @@ type RP struct {
 }
 
 func (rr *RP) String() string {
-	return rr.Hdr.String() + rr.Mbox + " " + sprintTxt([]string{rr.Txt})
+	return rr.Hdr.String() + sprintName(rr.Mbox) + " " + sprintName(rr.Txt)
 }
 
 // SOA RR. See RFC 1035.
@@ -420,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()
 }
 
@@ -454,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 > '~':
-			writeEscapedByte(&dst, b)
-		default:
-			dst.WriteByte(b)
+		} else {
+			writeTXTStringByte(&dst, b)
 		}
 		i += n
 	}
@@ -492,36 +534,61 @@ 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 == '\\':
 		s.WriteByte('\\')
 		s.WriteByte(b)
 	case b < ' ' || b > '~':
-		writeEscapedByte(s, b)
+		s.WriteString(escapeByte(b))
 	default:
 		s.WriteByte(b)
 	}
 }
 
-func writeEscapedByte(s *strings.Builder, b byte) {
-	var buf [3]byte
-	bufs := strconv.AppendInt(buf[:0], int64(b), 10)
-	s.WriteByte('\\')
-	for i := len(bufs); i < 3; i++ {
-		s.WriteByte('0')
+const (
+	escapedByteSmall = "" +
+		`\000\001\002\003\004\005\006\007\008\009` +
+		`\010\011\012\013\014\015\016\017\018\019` +
+		`\020\021\022\023\024\025\026\027\028\029` +
+		`\030\031`
+	escapedByteLarge = `\127\128\129` +
+		`\130\131\132\133\134\135\136\137\138\139` +
+		`\140\141\142\143\144\145\146\147\148\149` +
+		`\150\151\152\153\154\155\156\157\158\159` +
+		`\160\161\162\163\164\165\166\167\168\169` +
+		`\170\171\172\173\174\175\176\177\178\179` +
+		`\180\181\182\183\184\185\186\187\188\189` +
+		`\190\191\192\193\194\195\196\197\198\199` +
+		`\200\201\202\203\204\205\206\207\208\209` +
+		`\210\211\212\213\214\215\216\217\218\219` +
+		`\220\221\222\223\224\225\226\227\228\229` +
+		`\230\231\232\233\234\235\236\237\238\239` +
+		`\240\241\242\243\244\245\246\247\248\249` +
+		`\250\251\252\253\254\255`
+)
+
+// escapeByte returns the \DDD escaping of b which must
+// satisfy b < ' ' || b > '~'.
+func escapeByte(b byte) string {
+	if b < ' ' {
+		return escapedByteSmall[b*4 : b*4+4]
 	}
-	s.Write(bufs)
+
+	b -= '~' + 1
+	// The cast here is needed as b*4 may overflow byte.
+	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) {
@@ -696,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 {
@@ -803,22 +870,16 @@ type NSEC struct {
 
 func (rr *NSEC) String() string {
 	s := rr.Hdr.String() + sprintName(rr.NextDomain)
-	for i := 0; i < len(rr.TypeBitMap); i++ {
-		s += " " + Type(rr.TypeBitMap[i]).String()
+	for _, t := range rr.TypeBitMap {
+		s += " " + Type(t).String()
 	}
 	return s
 }
 
-func (rr *NSEC) len() int {
-	l := rr.Hdr.len() + 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)
-	}
+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)
+	l += typeBitMapLen(rr.TypeBitMap)
 	return l
 }
 
@@ -968,22 +1029,16 @@ func (rr *NSEC3) String() string {
 		" " + strconv.Itoa(int(rr.Iterations)) +
 		" " + saltToString(rr.Salt) +
 		" " + rr.NextDomain
-	for i := 0; i < len(rr.TypeBitMap); i++ {
-		s += " " + Type(rr.TypeBitMap[i]).String()
+	for _, t := range rr.TypeBitMap {
+		s += " " + Type(t).String()
 	}
 	return s
 }
 
-func (rr *NSEC3) len() int {
-	l := rr.Hdr.len() + 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)
-	}
+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
+	l += typeBitMapLen(rr.TypeBitMap)
 	return l
 }
 
@@ -1022,10 +1077,16 @@ type TKEY struct {
 
 // TKEY has no official presentation format, but this will suffice.
 func (rr *TKEY) String() string {
-	s := "\n;; TKEY PSEUDOSECTION:\n"
-	s += rr.Hdr.String() + " " + rr.Algorithm + " " +
-		strconv.Itoa(int(rr.KeySize)) + " " + rr.Key + " " +
-		strconv.Itoa(int(rr.OtherLen)) + " " + rr.OtherData
+	s := ";" + rr.Hdr.String() +
+		" " + rr.Algorithm +
+		" " + TimeToString(rr.Inception) +
+		" " + TimeToString(rr.Expiration) +
+		" " + strconv.Itoa(int(rr.Mode)) +
+		" " + strconv.Itoa(int(rr.Error)) +
+		" " + strconv.Itoa(int(rr.KeySize)) +
+		" " + rr.Key +
+		" " + strconv.Itoa(int(rr.OtherLen)) +
+		" " + rr.OtherData
 	return s
 }
 
@@ -1061,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)
@@ -1222,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)
 }
@@ -1285,23 +1348,99 @@ type CSYNC struct {
 func (rr *CSYNC) String() string {
 	s := rr.Hdr.String() + strconv.FormatInt(int64(rr.Serial), 10) + " " + strconv.Itoa(int(rr.Flags))
 
-	for i := 0; i < len(rr.TypeBitMap); i++ {
-		s += " " + Type(rr.TypeBitMap[i]).String()
+	for _, t := range rr.TypeBitMap {
+		s += " " + Type(t).String()
 	}
 	return s
 }
 
-func (rr *CSYNC) len() int {
-	l := rr.Hdr.len() + 4 + 2
-	lastwindow := uint32(2 ^ 32 + 1)
-	for _, t := range rr.TypeBitMap {
-		window := t / 256
-		if uint32(window) != lastwindow {
-			l += 1 + 32
+func (rr *CSYNC) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += 4 + 2
+	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
@@ -1360,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/udp_windows.go b/vendor/github.com/miekg/dns/udp_windows.go
index 6778c3c6..e7dd8ca3 100644
--- a/vendor/github.com/miekg/dns/udp_windows.go
+++ b/vendor/github.com/miekg/dns/udp_windows.go
@@ -20,15 +20,13 @@ func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
 	if err != nil {
 		return n, nil, err
 	}
-	session := &SessionUDP{raddr.(*net.UDPAddr)}
-	return n, session, err
+	return n, &SessionUDP{raddr.(*net.UDPAddr)}, err
 }
 
 // WriteToSessionUDP acts just like net.UDPConn.WriteTo(), but uses a *SessionUDP instead of a net.Addr.
 // TODO(fastest963): Once go1.10 is released, use WriteMsgUDP.
 func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
-	n, err := conn.WriteTo(b, session.raddr)
-	return n, err
+	return conn.WriteTo(b, session.raddr)
 }
 
 // TODO(fastest963): Once go1.10 is released and we can use *MsgUDP methods
diff --git a/vendor/github.com/miekg/dns/update.go b/vendor/github.com/miekg/dns/update.go
index e90c5c96..69dd3865 100644
--- a/vendor/github.com/miekg/dns/update.go
+++ b/vendor/github.com/miekg/dns/update.go
@@ -44,7 +44,8 @@ func (u *Msg) RRsetUsed(rr []RR) {
 		u.Answer = make([]RR, 0, len(rr))
 	}
 	for _, r := range rr {
-		u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: r.Header().Rrtype, Class: ClassANY}})
+		h := r.Header()
+		u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: h.Name, Ttl: 0, Rrtype: h.Rrtype, Class: ClassANY}})
 	}
 }
 
@@ -55,7 +56,8 @@ func (u *Msg) RRsetNotUsed(rr []RR) {
 		u.Answer = make([]RR, 0, len(rr))
 	}
 	for _, r := range rr {
-		u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: r.Header().Rrtype, Class: ClassNONE}})
+		h := r.Header()
+		u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: h.Name, Ttl: 0, Rrtype: h.Rrtype, Class: ClassNONE}})
 	}
 }
 
@@ -79,7 +81,8 @@ func (u *Msg) RemoveRRset(rr []RR) {
 		u.Ns = make([]RR, 0, len(rr))
 	}
 	for _, r := range rr {
-		u.Ns = append(u.Ns, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: r.Header().Rrtype, Class: ClassANY}})
+		h := r.Header()
+		u.Ns = append(u.Ns, &ANY{Hdr: RR_Header{Name: h.Name, Ttl: 0, Rrtype: h.Rrtype, Class: ClassANY}})
 	}
 }
 
@@ -99,8 +102,9 @@ func (u *Msg) Remove(rr []RR) {
 		u.Ns = make([]RR, 0, len(rr))
 	}
 	for _, r := range rr {
-		r.Header().Class = ClassNONE
-		r.Header().Ttl = 0
+		h := r.Header()
+		h.Class = ClassNONE
+		h.Ttl = 0
 		u.Ns = append(u.Ns, r)
 	}
 }
diff --git a/vendor/github.com/miekg/dns/version.go b/vendor/github.com/miekg/dns/version.go
index 0b0e9b6d..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, 0, 14}
+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 5d0ff5c8..43970e64 100644
--- a/vendor/github.com/miekg/dns/xfr.go
+++ b/vendor/github.com/miekg/dns/xfr.go
@@ -35,30 +35,36 @@ type Transfer struct {
 //	channel, err := transfer.In(message, master)
 //
 func (t *Transfer) In(q *Msg, a string) (env chan *Envelope, err error) {
+	switch q.Question[0].Qtype {
+	case TypeAXFR, TypeIXFR:
+	default:
+		return nil, &Error{"unsupported question type"}
+	}
+
 	timeout := dnsTimeout
 	if t.DialTimeout != 0 {
 		timeout = t.DialTimeout
 	}
+
 	if t.Conn == nil {
 		t.Conn, err = DialTimeout("tcp", a, timeout)
 		if err != nil {
 			return nil, err
 		}
 	}
+
 	if err := t.WriteMsg(q); err != nil {
 		return nil, err
 	}
+
 	env = make(chan *Envelope)
-	go func() {
-		if q.Question[0].Qtype == TypeAXFR {
-			go t.inAxfr(q, env)
-			return
-		}
-		if q.Question[0].Qtype == TypeIXFR {
-			go t.inIxfr(q, env)
-			return
-		}
-	}()
+	switch q.Question[0].Qtype {
+	case TypeAXFR:
+		go t.inAxfr(q, env)
+	case TypeIXFR:
+		go t.inIxfr(q, env)
+	}
+
 	return env, nil
 }
 
@@ -111,7 +117,7 @@ func (t *Transfer) inAxfr(q *Msg, c chan *Envelope) {
 }
 
 func (t *Transfer) inIxfr(q *Msg, c chan *Envelope) {
-	serial := uint32(0) // The first serial seen is the current server serial
+	var serial uint32 // The first serial seen is the current server serial
 	axfr := true
 	n := 0
 	qser := q.Ns[0].(*SOA).Serial
@@ -176,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)
@@ -192,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
 }
 
@@ -237,24 +249,18 @@ func (t *Transfer) WriteMsg(m *Msg) (err error) {
 	if err != nil {
 		return err
 	}
-	if _, err = t.Write(out); err != nil {
-		return err
-	}
-	return nil
+	_, err = t.Write(out)
+	return err
 }
 
 func isSOAFirst(in *Msg) bool {
-	if len(in.Answer) > 0 {
-		return in.Answer[0].Header().Rrtype == TypeSOA
-	}
-	return false
+	return len(in.Answer) > 0 &&
+		in.Answer[0].Header().Rrtype == TypeSOA
 }
 
 func isSOALast(in *Msg) bool {
-	if len(in.Answer) > 0 {
-		return in.Answer[len(in.Answer)-1].Header().Rrtype == TypeSOA
-	}
-	return false
+	return len(in.Answer) > 0 &&
+		in.Answer[len(in.Answer)-1].Header().Rrtype == TypeSOA
 }
 
 const errXFR = "bad xfr rcode: %d"
diff --git a/vendor/github.com/miekg/dns/zcompress.go b/vendor/github.com/miekg/dns/zcompress.go
deleted file mode 100644
index 6391a350..00000000
--- a/vendor/github.com/miekg/dns/zcompress.go
+++ /dev/null
@@ -1,152 +0,0 @@
-// Code generated by "go run compress_generate.go"; DO NOT EDIT.
-
-package dns
-
-func compressionLenHelperType(c map[string]int, r RR, initLen int) int {
-	currentLen := initLen
-	switch x := r.(type) {
-	case *AFSDB:
-		currentLen -= len(x.Hostname) + 1
-		currentLen += compressionLenHelper(c, x.Hostname, currentLen)
-	case *CNAME:
-		currentLen -= len(x.Target) + 1
-		currentLen += compressionLenHelper(c, x.Target, currentLen)
-	case *DNAME:
-		currentLen -= len(x.Target) + 1
-		currentLen += compressionLenHelper(c, x.Target, currentLen)
-	case *HIP:
-		for i := range x.RendezvousServers {
-			currentLen -= len(x.RendezvousServers[i]) + 1
-		}
-		for i := range x.RendezvousServers {
-			currentLen += compressionLenHelper(c, x.RendezvousServers[i], currentLen)
-		}
-	case *KX:
-		currentLen -= len(x.Exchanger) + 1
-		currentLen += compressionLenHelper(c, x.Exchanger, currentLen)
-	case *LP:
-		currentLen -= len(x.Fqdn) + 1
-		currentLen += compressionLenHelper(c, x.Fqdn, currentLen)
-	case *MB:
-		currentLen -= len(x.Mb) + 1
-		currentLen += compressionLenHelper(c, x.Mb, currentLen)
-	case *MD:
-		currentLen -= len(x.Md) + 1
-		currentLen += compressionLenHelper(c, x.Md, currentLen)
-	case *MF:
-		currentLen -= len(x.Mf) + 1
-		currentLen += compressionLenHelper(c, x.Mf, currentLen)
-	case *MG:
-		currentLen -= len(x.Mg) + 1
-		currentLen += compressionLenHelper(c, x.Mg, currentLen)
-	case *MINFO:
-		currentLen -= len(x.Rmail) + 1
-		currentLen += compressionLenHelper(c, x.Rmail, currentLen)
-		currentLen -= len(x.Email) + 1
-		currentLen += compressionLenHelper(c, x.Email, currentLen)
-	case *MR:
-		currentLen -= len(x.Mr) + 1
-		currentLen += compressionLenHelper(c, x.Mr, currentLen)
-	case *MX:
-		currentLen -= len(x.Mx) + 1
-		currentLen += compressionLenHelper(c, x.Mx, currentLen)
-	case *NAPTR:
-		currentLen -= len(x.Replacement) + 1
-		currentLen += compressionLenHelper(c, x.Replacement, currentLen)
-	case *NS:
-		currentLen -= len(x.Ns) + 1
-		currentLen += compressionLenHelper(c, x.Ns, currentLen)
-	case *NSAPPTR:
-		currentLen -= len(x.Ptr) + 1
-		currentLen += compressionLenHelper(c, x.Ptr, currentLen)
-	case *NSEC:
-		currentLen -= len(x.NextDomain) + 1
-		currentLen += compressionLenHelper(c, x.NextDomain, currentLen)
-	case *PTR:
-		currentLen -= len(x.Ptr) + 1
-		currentLen += compressionLenHelper(c, x.Ptr, currentLen)
-	case *PX:
-		currentLen -= len(x.Map822) + 1
-		currentLen += compressionLenHelper(c, x.Map822, currentLen)
-		currentLen -= len(x.Mapx400) + 1
-		currentLen += compressionLenHelper(c, x.Mapx400, currentLen)
-	case *RP:
-		currentLen -= len(x.Mbox) + 1
-		currentLen += compressionLenHelper(c, x.Mbox, currentLen)
-		currentLen -= len(x.Txt) + 1
-		currentLen += compressionLenHelper(c, x.Txt, currentLen)
-	case *RRSIG:
-		currentLen -= len(x.SignerName) + 1
-		currentLen += compressionLenHelper(c, x.SignerName, currentLen)
-	case *RT:
-		currentLen -= len(x.Host) + 1
-		currentLen += compressionLenHelper(c, x.Host, currentLen)
-	case *SIG:
-		currentLen -= len(x.SignerName) + 1
-		currentLen += compressionLenHelper(c, x.SignerName, currentLen)
-	case *SOA:
-		currentLen -= len(x.Ns) + 1
-		currentLen += compressionLenHelper(c, x.Ns, currentLen)
-		currentLen -= len(x.Mbox) + 1
-		currentLen += compressionLenHelper(c, x.Mbox, currentLen)
-	case *SRV:
-		currentLen -= len(x.Target) + 1
-		currentLen += compressionLenHelper(c, x.Target, currentLen)
-	case *TALINK:
-		currentLen -= len(x.PreviousName) + 1
-		currentLen += compressionLenHelper(c, x.PreviousName, currentLen)
-		currentLen -= len(x.NextName) + 1
-		currentLen += compressionLenHelper(c, x.NextName, currentLen)
-	case *TKEY:
-		currentLen -= len(x.Algorithm) + 1
-		currentLen += compressionLenHelper(c, x.Algorithm, currentLen)
-	case *TSIG:
-		currentLen -= len(x.Algorithm) + 1
-		currentLen += compressionLenHelper(c, x.Algorithm, currentLen)
-	}
-	return currentLen - initLen
-}
-
-func compressionLenSearchType(c map[string]int, r RR) (int, bool, int) {
-	switch x := r.(type) {
-	case *CNAME:
-		k1, ok1, sz1 := compressionLenSearch(c, x.Target)
-		return k1, ok1, sz1
-	case *MB:
-		k1, ok1, sz1 := compressionLenSearch(c, x.Mb)
-		return k1, ok1, sz1
-	case *MD:
-		k1, ok1, sz1 := compressionLenSearch(c, x.Md)
-		return k1, ok1, sz1
-	case *MF:
-		k1, ok1, sz1 := compressionLenSearch(c, x.Mf)
-		return k1, ok1, sz1
-	case *MG:
-		k1, ok1, sz1 := compressionLenSearch(c, x.Mg)
-		return k1, ok1, sz1
-	case *MINFO:
-		k1, ok1, sz1 := compressionLenSearch(c, x.Rmail)
-		k2, ok2, sz2 := compressionLenSearch(c, x.Email)
-		return k1 + k2, ok1 && ok2, sz1 + sz2
-	case *MR:
-		k1, ok1, sz1 := compressionLenSearch(c, x.Mr)
-		return k1, ok1, sz1
-	case *MX:
-		k1, ok1, sz1 := compressionLenSearch(c, x.Mx)
-		return k1, ok1, sz1
-	case *NS:
-		k1, ok1, sz1 := compressionLenSearch(c, x.Ns)
-		return k1, ok1, sz1
-	case *PTR:
-		k1, ok1, sz1 := compressionLenSearch(c, x.Ptr)
-		return k1, ok1, sz1
-	case *RT:
-		k1, ok1, sz1 := compressionLenSearch(c, x.Host)
-		return k1, ok1, sz1
-	case *SOA:
-		k1, ok1, sz1 := compressionLenSearch(c, x.Ns)
-		k2, ok2, sz2 := compressionLenSearch(c, x.Mbox)
-		return k1 + k2, ok1 && ok2, sz1 + sz2
-	}
-	return 0, false, 0
-}
diff --git a/vendor/github.com/miekg/dns/zduplicate.go b/vendor/github.com/miekg/dns/zduplicate.go
index ba9863b2..0d3b34bd 100644
--- a/vendor/github.com/miekg/dns/zduplicate.go
+++ b/vendor/github.com/miekg/dns/zduplicate.go
@@ -2,174 +2,79 @@
 
 package dns
 
-// isDuplicateRdata calls the rdata specific functions
-func isDuplicateRdata(r1, r2 RR) bool {
-	switch r1.Header().Rrtype {
-	case TypeA:
-		return isDuplicateA(r1.(*A), r2.(*A))
-	case TypeAAAA:
-		return isDuplicateAAAA(r1.(*AAAA), r2.(*AAAA))
-	case TypeAFSDB:
-		return isDuplicateAFSDB(r1.(*AFSDB), r2.(*AFSDB))
-	case TypeAVC:
-		return isDuplicateAVC(r1.(*AVC), r2.(*AVC))
-	case TypeCAA:
-		return isDuplicateCAA(r1.(*CAA), r2.(*CAA))
-	case TypeCERT:
-		return isDuplicateCERT(r1.(*CERT), r2.(*CERT))
-	case TypeCNAME:
-		return isDuplicateCNAME(r1.(*CNAME), r2.(*CNAME))
-	case TypeCSYNC:
-		return isDuplicateCSYNC(r1.(*CSYNC), r2.(*CSYNC))
-	case TypeDHCID:
-		return isDuplicateDHCID(r1.(*DHCID), r2.(*DHCID))
-	case TypeDNAME:
-		return isDuplicateDNAME(r1.(*DNAME), r2.(*DNAME))
-	case TypeDNSKEY:
-		return isDuplicateDNSKEY(r1.(*DNSKEY), r2.(*DNSKEY))
-	case TypeDS:
-		return isDuplicateDS(r1.(*DS), r2.(*DS))
-	case TypeEID:
-		return isDuplicateEID(r1.(*EID), r2.(*EID))
-	case TypeEUI48:
-		return isDuplicateEUI48(r1.(*EUI48), r2.(*EUI48))
-	case TypeEUI64:
-		return isDuplicateEUI64(r1.(*EUI64), r2.(*EUI64))
-	case TypeGID:
-		return isDuplicateGID(r1.(*GID), r2.(*GID))
-	case TypeGPOS:
-		return isDuplicateGPOS(r1.(*GPOS), r2.(*GPOS))
-	case TypeHINFO:
-		return isDuplicateHINFO(r1.(*HINFO), r2.(*HINFO))
-	case TypeHIP:
-		return isDuplicateHIP(r1.(*HIP), r2.(*HIP))
-	case TypeKX:
-		return isDuplicateKX(r1.(*KX), r2.(*KX))
-	case TypeL32:
-		return isDuplicateL32(r1.(*L32), r2.(*L32))
-	case TypeL64:
-		return isDuplicateL64(r1.(*L64), r2.(*L64))
-	case TypeLOC:
-		return isDuplicateLOC(r1.(*LOC), r2.(*LOC))
-	case TypeLP:
-		return isDuplicateLP(r1.(*LP), r2.(*LP))
-	case TypeMB:
-		return isDuplicateMB(r1.(*MB), r2.(*MB))
-	case TypeMD:
-		return isDuplicateMD(r1.(*MD), r2.(*MD))
-	case TypeMF:
-		return isDuplicateMF(r1.(*MF), r2.(*MF))
-	case TypeMG:
-		return isDuplicateMG(r1.(*MG), r2.(*MG))
-	case TypeMINFO:
-		return isDuplicateMINFO(r1.(*MINFO), r2.(*MINFO))
-	case TypeMR:
-		return isDuplicateMR(r1.(*MR), r2.(*MR))
-	case TypeMX:
-		return isDuplicateMX(r1.(*MX), r2.(*MX))
-	case TypeNAPTR:
-		return isDuplicateNAPTR(r1.(*NAPTR), r2.(*NAPTR))
-	case TypeNID:
-		return isDuplicateNID(r1.(*NID), r2.(*NID))
-	case TypeNIMLOC:
-		return isDuplicateNIMLOC(r1.(*NIMLOC), r2.(*NIMLOC))
-	case TypeNINFO:
-		return isDuplicateNINFO(r1.(*NINFO), r2.(*NINFO))
-	case TypeNS:
-		return isDuplicateNS(r1.(*NS), r2.(*NS))
-	case TypeNSAPPTR:
-		return isDuplicateNSAPPTR(r1.(*NSAPPTR), r2.(*NSAPPTR))
-	case TypeNSEC:
-		return isDuplicateNSEC(r1.(*NSEC), r2.(*NSEC))
-	case TypeNSEC3:
-		return isDuplicateNSEC3(r1.(*NSEC3), r2.(*NSEC3))
-	case TypeNSEC3PARAM:
-		return isDuplicateNSEC3PARAM(r1.(*NSEC3PARAM), r2.(*NSEC3PARAM))
-	case TypeOPENPGPKEY:
-		return isDuplicateOPENPGPKEY(r1.(*OPENPGPKEY), r2.(*OPENPGPKEY))
-	case TypePTR:
-		return isDuplicatePTR(r1.(*PTR), r2.(*PTR))
-	case TypePX:
-		return isDuplicatePX(r1.(*PX), r2.(*PX))
-	case TypeRKEY:
-		return isDuplicateRKEY(r1.(*RKEY), r2.(*RKEY))
-	case TypeRP:
-		return isDuplicateRP(r1.(*RP), r2.(*RP))
-	case TypeRRSIG:
-		return isDuplicateRRSIG(r1.(*RRSIG), r2.(*RRSIG))
-	case TypeRT:
-		return isDuplicateRT(r1.(*RT), r2.(*RT))
-	case TypeSMIMEA:
-		return isDuplicateSMIMEA(r1.(*SMIMEA), r2.(*SMIMEA))
-	case TypeSOA:
-		return isDuplicateSOA(r1.(*SOA), r2.(*SOA))
-	case TypeSPF:
-		return isDuplicateSPF(r1.(*SPF), r2.(*SPF))
-	case TypeSRV:
-		return isDuplicateSRV(r1.(*SRV), r2.(*SRV))
-	case TypeSSHFP:
-		return isDuplicateSSHFP(r1.(*SSHFP), r2.(*SSHFP))
-	case TypeTA:
-		return isDuplicateTA(r1.(*TA), r2.(*TA))
-	case TypeTALINK:
-		return isDuplicateTALINK(r1.(*TALINK), r2.(*TALINK))
-	case TypeTKEY:
-		return isDuplicateTKEY(r1.(*TKEY), r2.(*TKEY))
-	case TypeTLSA:
-		return isDuplicateTLSA(r1.(*TLSA), r2.(*TLSA))
-	case TypeTSIG:
-		return isDuplicateTSIG(r1.(*TSIG), r2.(*TSIG))
-	case TypeTXT:
-		return isDuplicateTXT(r1.(*TXT), r2.(*TXT))
-	case TypeUID:
-		return isDuplicateUID(r1.(*UID), r2.(*UID))
-	case TypeUINFO:
-		return isDuplicateUINFO(r1.(*UINFO), r2.(*UINFO))
-	case TypeURI:
-		return isDuplicateURI(r1.(*URI), r2.(*URI))
-	case TypeX25:
-		return isDuplicateX25(r1.(*X25), r2.(*X25))
-	}
-	return false
-}
-
 // isDuplicate() functions
 
-func isDuplicateA(r1, r2 *A) bool {
-	if len(r1.A) != len(r2.A) {
+func (r1 *A) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*A)
+	if !ok {
 		return false
 	}
-	for i := 0; i < len(r1.A); i++ {
-		if r1.A[i] != r2.A[i] {
-			return false
-		}
+	_ = r2
+	if !r1.A.Equal(r2.A) {
+		return false
 	}
 	return true
 }
 
-func isDuplicateAAAA(r1, r2 *AAAA) bool {
-	if len(r1.AAAA) != len(r2.AAAA) {
+func (r1 *AAAA) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*AAAA)
+	if !ok {
 		return false
 	}
-	for i := 0; i < len(r1.AAAA); i++ {
-		if r1.AAAA[i] != r2.AAAA[i] {
-			return false
-		}
+	_ = r2
+	if !r1.AAAA.Equal(r2.AAAA) {
+		return false
 	}
 	return true
 }
 
-func isDuplicateAFSDB(r1, r2 *AFSDB) bool {
+func (r1 *AFSDB) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*AFSDB)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.Subtype != r2.Subtype {
 		return false
 	}
-	if !isDulicateName(r1.Hostname, r2.Hostname) {
+	if !isDuplicateName(r1.Hostname, r2.Hostname) {
+		return false
+	}
+	return true
+}
+
+func (r1 *ANY) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*ANY)
+	if !ok {
+		return false
+	}
+	_ = r2
+	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 isDuplicateAVC(r1, r2 *AVC) bool {
+func (r1 *AVC) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*AVC)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if len(r1.Txt) != len(r2.Txt) {
 		return false
 	}
@@ -181,7 +86,12 @@ func isDuplicateAVC(r1, r2 *AVC) bool {
 	return true
 }
 
-func isDuplicateCAA(r1, r2 *CAA) bool {
+func (r1 *CAA) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*CAA)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.Flag != r2.Flag {
 		return false
 	}
@@ -194,7 +104,54 @@ func isDuplicateCAA(r1, r2 *CAA) bool {
 	return true
 }
 
-func isDuplicateCERT(r1, r2 *CERT) bool {
+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 {
+		return false
+	}
+	_ = r2
 	if r1.Type != r2.Type {
 		return false
 	}
@@ -210,14 +167,24 @@ func isDuplicateCERT(r1, r2 *CERT) bool {
 	return true
 }
 
-func isDuplicateCNAME(r1, r2 *CNAME) bool {
-	if !isDulicateName(r1.Target, r2.Target) {
+func (r1 *CNAME) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*CNAME)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.Target, r2.Target) {
 		return false
 	}
 	return true
 }
 
-func isDuplicateCSYNC(r1, r2 *CSYNC) bool {
+func (r1 *CSYNC) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*CSYNC)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.Serial != r2.Serial {
 		return false
 	}
@@ -235,21 +202,57 @@ func isDuplicateCSYNC(r1, r2 *CSYNC) bool {
 	return true
 }
 
-func isDuplicateDHCID(r1, r2 *DHCID) bool {
+func (r1 *DHCID) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*DHCID)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Digest != r2.Digest {
+		return false
+	}
+	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 isDuplicateDNAME(r1, r2 *DNAME) bool {
-	if !isDulicateName(r1.Target, r2.Target) {
+func (r1 *DNAME) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*DNAME)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.Target, r2.Target) {
 		return false
 	}
 	return true
 }
 
-func isDuplicateDNSKEY(r1, r2 *DNSKEY) bool {
+func (r1 *DNSKEY) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*DNSKEY)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.Flags != r2.Flags {
 		return false
 	}
@@ -265,7 +268,12 @@ func isDuplicateDNSKEY(r1, r2 *DNSKEY) bool {
 	return true
 }
 
-func isDuplicateDS(r1, r2 *DS) bool {
+func (r1 *DS) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*DS)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.KeyTag != r2.KeyTag {
 		return false
 	}
@@ -281,35 +289,60 @@ func isDuplicateDS(r1, r2 *DS) bool {
 	return true
 }
 
-func isDuplicateEID(r1, r2 *EID) bool {
+func (r1 *EID) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*EID)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.Endpoint != r2.Endpoint {
 		return false
 	}
 	return true
 }
 
-func isDuplicateEUI48(r1, r2 *EUI48) bool {
+func (r1 *EUI48) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*EUI48)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.Address != r2.Address {
 		return false
 	}
 	return true
 }
 
-func isDuplicateEUI64(r1, r2 *EUI64) bool {
+func (r1 *EUI64) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*EUI64)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.Address != r2.Address {
 		return false
 	}
 	return true
 }
 
-func isDuplicateGID(r1, r2 *GID) bool {
+func (r1 *GID) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*GID)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.Gid != r2.Gid {
 		return false
 	}
 	return true
 }
 
-func isDuplicateGPOS(r1, r2 *GPOS) bool {
+func (r1 *GPOS) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*GPOS)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.Longitude != r2.Longitude {
 		return false
 	}
@@ -322,7 +355,12 @@ func isDuplicateGPOS(r1, r2 *GPOS) bool {
 	return true
 }
 
-func isDuplicateHINFO(r1, r2 *HINFO) bool {
+func (r1 *HINFO) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*HINFO)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.Cpu != r2.Cpu {
 		return false
 	}
@@ -332,7 +370,12 @@ func isDuplicateHINFO(r1, r2 *HINFO) bool {
 	return true
 }
 
-func isDuplicateHIP(r1, r2 *HIP) bool {
+func (r1 *HIP) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*HIP)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.HitLength != r2.HitLength {
 		return false
 	}
@@ -352,39 +395,91 @@ func isDuplicateHIP(r1, r2 *HIP) bool {
 		return false
 	}
 	for i := 0; i < len(r1.RendezvousServers); i++ {
-		if !isDulicateName(r1.RendezvousServers[i], r2.RendezvousServers[i]) {
+		if !isDuplicateName(r1.RendezvousServers[i], r2.RendezvousServers[i]) {
 			return false
 		}
 	}
 	return true
 }
 
-func isDuplicateKX(r1, r2 *KX) bool {
-	if r1.Preference != r2.Preference {
+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 !isDulicateName(r1.Exchanger, r2.Exchanger) {
+	if r1.Protocol != r2.Protocol {
+		return false
+	}
+	if r1.Algorithm != r2.Algorithm {
+		return false
+	}
+	if r1.PublicKey != r2.PublicKey {
 		return false
 	}
 	return true
 }
 
-func isDuplicateL32(r1, r2 *L32) bool {
+func (r1 *KX) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*KX)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.Preference != r2.Preference {
 		return false
 	}
-	if len(r1.Locator32) != len(r2.Locator32) {
+	if !isDuplicateName(r1.Exchanger, r2.Exchanger) {
 		return false
 	}
-	for i := 0; i < len(r1.Locator32); i++ {
-		if r1.Locator32[i] != r2.Locator32[i] {
-			return false
-		}
+	return true
+}
+
+func (r1 *L32) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*L32)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Preference != r2.Preference {
+		return false
+	}
+	if !r1.Locator32.Equal(r2.Locator32) {
+		return false
 	}
 	return true
 }
 
-func isDuplicateL64(r1, r2 *L64) bool {
+func (r1 *L64) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*L64)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.Preference != r2.Preference {
 		return false
 	}
@@ -394,7 +489,12 @@ func isDuplicateL64(r1, r2 *L64) bool {
 	return true
 }
 
-func isDuplicateLOC(r1, r2 *LOC) bool {
+func (r1 *LOC) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*LOC)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.Version != r2.Version {
 		return false
 	}
@@ -419,72 +519,117 @@ func isDuplicateLOC(r1, r2 *LOC) bool {
 	return true
 }
 
-func isDuplicateLP(r1, r2 *LP) bool {
+func (r1 *LP) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*LP)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.Preference != r2.Preference {
 		return false
 	}
-	if !isDulicateName(r1.Fqdn, r2.Fqdn) {
+	if !isDuplicateName(r1.Fqdn, r2.Fqdn) {
 		return false
 	}
 	return true
 }
 
-func isDuplicateMB(r1, r2 *MB) bool {
-	if !isDulicateName(r1.Mb, r2.Mb) {
+func (r1 *MB) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*MB)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.Mb, r2.Mb) {
 		return false
 	}
 	return true
 }
 
-func isDuplicateMD(r1, r2 *MD) bool {
-	if !isDulicateName(r1.Md, r2.Md) {
+func (r1 *MD) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*MD)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.Md, r2.Md) {
 		return false
 	}
 	return true
 }
 
-func isDuplicateMF(r1, r2 *MF) bool {
-	if !isDulicateName(r1.Mf, r2.Mf) {
+func (r1 *MF) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*MF)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.Mf, r2.Mf) {
 		return false
 	}
 	return true
 }
 
-func isDuplicateMG(r1, r2 *MG) bool {
-	if !isDulicateName(r1.Mg, r2.Mg) {
+func (r1 *MG) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*MG)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.Mg, r2.Mg) {
 		return false
 	}
 	return true
 }
 
-func isDuplicateMINFO(r1, r2 *MINFO) bool {
-	if !isDulicateName(r1.Rmail, r2.Rmail) {
+func (r1 *MINFO) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*MINFO)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.Rmail, r2.Rmail) {
 		return false
 	}
-	if !isDulicateName(r1.Email, r2.Email) {
+	if !isDuplicateName(r1.Email, r2.Email) {
 		return false
 	}
 	return true
 }
 
-func isDuplicateMR(r1, r2 *MR) bool {
-	if !isDulicateName(r1.Mr, r2.Mr) {
+func (r1 *MR) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*MR)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.Mr, r2.Mr) {
 		return false
 	}
 	return true
 }
 
-func isDuplicateMX(r1, r2 *MX) bool {
+func (r1 *MX) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*MX)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.Preference != r2.Preference {
 		return false
 	}
-	if !isDulicateName(r1.Mx, r2.Mx) {
+	if !isDuplicateName(r1.Mx, r2.Mx) {
 		return false
 	}
 	return true
 }
 
-func isDuplicateNAPTR(r1, r2 *NAPTR) bool {
+func (r1 *NAPTR) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*NAPTR)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.Order != r2.Order {
 		return false
 	}
@@ -500,13 +645,18 @@ func isDuplicateNAPTR(r1, r2 *NAPTR) bool {
 	if r1.Regexp != r2.Regexp {
 		return false
 	}
-	if !isDulicateName(r1.Replacement, r2.Replacement) {
+	if !isDuplicateName(r1.Replacement, r2.Replacement) {
 		return false
 	}
 	return true
 }
 
-func isDuplicateNID(r1, r2 *NID) bool {
+func (r1 *NID) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*NID)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.Preference != r2.Preference {
 		return false
 	}
@@ -516,14 +666,24 @@ func isDuplicateNID(r1, r2 *NID) bool {
 	return true
 }
 
-func isDuplicateNIMLOC(r1, r2 *NIMLOC) bool {
+func (r1 *NIMLOC) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*NIMLOC)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.Locator != r2.Locator {
 		return false
 	}
 	return true
 }
 
-func isDuplicateNINFO(r1, r2 *NINFO) bool {
+func (r1 *NINFO) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*NINFO)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if len(r1.ZSData) != len(r2.ZSData) {
 		return false
 	}
@@ -535,22 +695,37 @@ func isDuplicateNINFO(r1, r2 *NINFO) bool {
 	return true
 }
 
-func isDuplicateNS(r1, r2 *NS) bool {
-	if !isDulicateName(r1.Ns, r2.Ns) {
+func (r1 *NS) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*NS)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.Ns, r2.Ns) {
 		return false
 	}
 	return true
 }
 
-func isDuplicateNSAPPTR(r1, r2 *NSAPPTR) bool {
-	if !isDulicateName(r1.Ptr, r2.Ptr) {
+func (r1 *NSAPPTR) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*NSAPPTR)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.Ptr, r2.Ptr) {
 		return false
 	}
 	return true
 }
 
-func isDuplicateNSEC(r1, r2 *NSEC) bool {
-	if !isDulicateName(r1.NextDomain, r2.NextDomain) {
+func (r1 *NSEC) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*NSEC)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.NextDomain, r2.NextDomain) {
 		return false
 	}
 	if len(r1.TypeBitMap) != len(r2.TypeBitMap) {
@@ -564,7 +739,12 @@ func isDuplicateNSEC(r1, r2 *NSEC) bool {
 	return true
 }
 
-func isDuplicateNSEC3(r1, r2 *NSEC3) bool {
+func (r1 *NSEC3) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*NSEC3)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.Hash != r2.Hash {
 		return false
 	}
@@ -597,7 +777,12 @@ func isDuplicateNSEC3(r1, r2 *NSEC3) bool {
 	return true
 }
 
-func isDuplicateNSEC3PARAM(r1, r2 *NSEC3PARAM) bool {
+func (r1 *NSEC3PARAM) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*NSEC3PARAM)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.Hash != r2.Hash {
 		return false
 	}
@@ -616,34 +801,78 @@ func isDuplicateNSEC3PARAM(r1, r2 *NSEC3PARAM) bool {
 	return true
 }
 
-func isDuplicateOPENPGPKEY(r1, r2 *OPENPGPKEY) bool {
+func (r1 *NULL) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*NULL)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Data != r2.Data {
+		return false
+	}
+	return true
+}
+
+func (r1 *OPENPGPKEY) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*OPENPGPKEY)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.PublicKey != r2.PublicKey {
 		return false
 	}
 	return true
 }
 
-func isDuplicatePTR(r1, r2 *PTR) bool {
-	if !isDulicateName(r1.Ptr, r2.Ptr) {
+func (r1 *PTR) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*PTR)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.Ptr, r2.Ptr) {
 		return false
 	}
 	return true
 }
 
-func isDuplicatePX(r1, r2 *PX) bool {
+func (r1 *PX) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*PX)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.Preference != r2.Preference {
 		return false
 	}
-	if !isDulicateName(r1.Map822, r2.Map822) {
+	if !isDuplicateName(r1.Map822, r2.Map822) {
+		return false
+	}
+	if !isDuplicateName(r1.Mapx400, r2.Mapx400) {
 		return false
 	}
-	if !isDulicateName(r1.Mapx400, r2.Mapx400) {
+	return true
+}
+
+func (r1 *RFC3597) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*RFC3597)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if r1.Rdata != r2.Rdata {
 		return false
 	}
 	return true
 }
 
-func isDuplicateRKEY(r1, r2 *RKEY) bool {
+func (r1 *RKEY) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*RKEY)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.Flags != r2.Flags {
 		return false
 	}
@@ -659,17 +888,27 @@ func isDuplicateRKEY(r1, r2 *RKEY) bool {
 	return true
 }
 
-func isDuplicateRP(r1, r2 *RP) bool {
-	if !isDulicateName(r1.Mbox, r2.Mbox) {
+func (r1 *RP) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*RP)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.Mbox, r2.Mbox) {
 		return false
 	}
-	if !isDulicateName(r1.Txt, r2.Txt) {
+	if !isDuplicateName(r1.Txt, r2.Txt) {
 		return false
 	}
 	return true
 }
 
-func isDuplicateRRSIG(r1, r2 *RRSIG) bool {
+func (r1 *RRSIG) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*RRSIG)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.TypeCovered != r2.TypeCovered {
 		return false
 	}
@@ -691,7 +930,7 @@ func isDuplicateRRSIG(r1, r2 *RRSIG) bool {
 	if r1.KeyTag != r2.KeyTag {
 		return false
 	}
-	if !isDulicateName(r1.SignerName, r2.SignerName) {
+	if !isDuplicateName(r1.SignerName, r2.SignerName) {
 		return false
 	}
 	if r1.Signature != r2.Signature {
@@ -700,17 +939,63 @@ func isDuplicateRRSIG(r1, r2 *RRSIG) bool {
 	return true
 }
 
-func isDuplicateRT(r1, r2 *RT) bool {
+func (r1 *RT) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*RT)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.Preference != r2.Preference {
 		return false
 	}
-	if !isDulicateName(r1.Host, r2.Host) {
+	if !isDuplicateName(r1.Host, r2.Host) {
 		return false
 	}
 	return true
 }
 
-func isDuplicateSMIMEA(r1, r2 *SMIMEA) bool {
+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 {
+		return false
+	}
+	_ = r2
 	if r1.Usage != r2.Usage {
 		return false
 	}
@@ -726,11 +1011,16 @@ func isDuplicateSMIMEA(r1, r2 *SMIMEA) bool {
 	return true
 }
 
-func isDuplicateSOA(r1, r2 *SOA) bool {
-	if !isDulicateName(r1.Ns, r2.Ns) {
+func (r1 *SOA) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*SOA)
+	if !ok {
 		return false
 	}
-	if !isDulicateName(r1.Mbox, r2.Mbox) {
+	_ = r2
+	if !isDuplicateName(r1.Ns, r2.Ns) {
+		return false
+	}
+	if !isDuplicateName(r1.Mbox, r2.Mbox) {
 		return false
 	}
 	if r1.Serial != r2.Serial {
@@ -751,7 +1041,12 @@ func isDuplicateSOA(r1, r2 *SOA) bool {
 	return true
 }
 
-func isDuplicateSPF(r1, r2 *SPF) bool {
+func (r1 *SPF) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*SPF)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if len(r1.Txt) != len(r2.Txt) {
 		return false
 	}
@@ -763,7 +1058,12 @@ func isDuplicateSPF(r1, r2 *SPF) bool {
 	return true
 }
 
-func isDuplicateSRV(r1, r2 *SRV) bool {
+func (r1 *SRV) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*SRV)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.Priority != r2.Priority {
 		return false
 	}
@@ -773,13 +1073,18 @@ func isDuplicateSRV(r1, r2 *SRV) bool {
 	if r1.Port != r2.Port {
 		return false
 	}
-	if !isDulicateName(r1.Target, r2.Target) {
+	if !isDuplicateName(r1.Target, r2.Target) {
 		return false
 	}
 	return true
 }
 
-func isDuplicateSSHFP(r1, r2 *SSHFP) bool {
+func (r1 *SSHFP) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*SSHFP)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.Algorithm != r2.Algorithm {
 		return false
 	}
@@ -792,7 +1097,33 @@ func isDuplicateSSHFP(r1, r2 *SSHFP) bool {
 	return true
 }
 
-func isDuplicateTA(r1, r2 *TA) bool {
+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 {
+		return false
+	}
+	_ = r2
 	if r1.KeyTag != r2.KeyTag {
 		return false
 	}
@@ -808,18 +1139,28 @@ func isDuplicateTA(r1, r2 *TA) bool {
 	return true
 }
 
-func isDuplicateTALINK(r1, r2 *TALINK) bool {
-	if !isDulicateName(r1.PreviousName, r2.PreviousName) {
+func (r1 *TALINK) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*TALINK)
+	if !ok {
 		return false
 	}
-	if !isDulicateName(r1.NextName, r2.NextName) {
+	_ = r2
+	if !isDuplicateName(r1.PreviousName, r2.PreviousName) {
+		return false
+	}
+	if !isDuplicateName(r1.NextName, r2.NextName) {
 		return false
 	}
 	return true
 }
 
-func isDuplicateTKEY(r1, r2 *TKEY) bool {
-	if !isDulicateName(r1.Algorithm, r2.Algorithm) {
+func (r1 *TKEY) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*TKEY)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.Algorithm, r2.Algorithm) {
 		return false
 	}
 	if r1.Inception != r2.Inception {
@@ -849,7 +1190,12 @@ func isDuplicateTKEY(r1, r2 *TKEY) bool {
 	return true
 }
 
-func isDuplicateTLSA(r1, r2 *TLSA) bool {
+func (r1 *TLSA) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*TLSA)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.Usage != r2.Usage {
 		return false
 	}
@@ -865,8 +1211,13 @@ func isDuplicateTLSA(r1, r2 *TLSA) bool {
 	return true
 }
 
-func isDuplicateTSIG(r1, r2 *TSIG) bool {
-	if !isDulicateName(r1.Algorithm, r2.Algorithm) {
+func (r1 *TSIG) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*TSIG)
+	if !ok {
+		return false
+	}
+	_ = r2
+	if !isDuplicateName(r1.Algorithm, r2.Algorithm) {
 		return false
 	}
 	if r1.TimeSigned != r2.TimeSigned {
@@ -896,7 +1247,12 @@ func isDuplicateTSIG(r1, r2 *TSIG) bool {
 	return true
 }
 
-func isDuplicateTXT(r1, r2 *TXT) bool {
+func (r1 *TXT) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*TXT)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if len(r1.Txt) != len(r2.Txt) {
 		return false
 	}
@@ -908,21 +1264,36 @@ func isDuplicateTXT(r1, r2 *TXT) bool {
 	return true
 }
 
-func isDuplicateUID(r1, r2 *UID) bool {
+func (r1 *UID) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*UID)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.Uid != r2.Uid {
 		return false
 	}
 	return true
 }
 
-func isDuplicateUINFO(r1, r2 *UINFO) bool {
+func (r1 *UINFO) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*UINFO)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.Uinfo != r2.Uinfo {
 		return false
 	}
 	return true
 }
 
-func isDuplicateURI(r1, r2 *URI) bool {
+func (r1 *URI) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*URI)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.Priority != r2.Priority {
 		return false
 	}
@@ -935,7 +1306,12 @@ func isDuplicateURI(r1, r2 *URI) bool {
 	return true
 }
 
-func isDuplicateX25(r1, r2 *X25) bool {
+func (r1 *X25) isDuplicate(_r2 RR) bool {
+	r2, ok := _r2.(*X25)
+	if !ok {
+		return false
+	}
+	_ = r2
 	if r1.PSDNAddress != r2.PSDNAddress {
 		return false
 	}
diff --git a/vendor/github.com/miekg/dns/zmsg.go b/vendor/github.com/miekg/dns/zmsg.go
index 1a68f74d..d24a10fa 100644
--- a/vendor/github.com/miekg/dns/zmsg.go
+++ b/vendor/github.com/miekg/dns/zmsg.go
@@ -4,82 +4,55 @@ package dns
 
 // pack*() functions
 
-func (rr *A) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *A) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packDataA(rr.A, msg, off)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *AAAA) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *AAAA) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packDataAAAA(rr.AAAA, msg, off)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *AFSDB) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *AFSDB) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint16(rr.Subtype, msg, off)
 	if err != nil {
 		return off, err
 	}
-	off, err = PackDomainName(rr.Hostname, msg, off, compression, false)
+	off, err = packDomainName(rr.Hostname, msg, off, compression, false)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *ANY) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
-	rr.Header().Rdlength = uint16(off - headerEnd)
+func (rr *ANY) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	return off, nil
 }
 
-func (rr *AVC) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
+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
 	}
-	headerEnd := off
+	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 {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *CAA) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *CAA) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint8(rr.Flag, msg, off)
 	if err != nil {
 		return off, err
@@ -92,16 +65,10 @@ func (rr *CAA) pack(msg []byte, off int, compression map[string]int, compress bo
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *CDNSKEY) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *CDNSKEY) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint16(rr.Flags, msg, off)
 	if err != nil {
 		return off, err
@@ -118,16 +85,10 @@ func (rr *CDNSKEY) pack(msg []byte, off int, compression map[string]int, compres
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *CDS) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *CDS) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint16(rr.KeyTag, msg, off)
 	if err != nil {
 		return off, err
@@ -144,16 +105,10 @@ func (rr *CDS) pack(msg []byte, off int, compression map[string]int, compress bo
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *CERT) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *CERT) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint16(rr.Type, msg, off)
 	if err != nil {
 		return off, err
@@ -170,30 +125,18 @@ func (rr *CERT) pack(msg []byte, off int, compression map[string]int, compress b
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *CNAME) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
-	off, err = PackDomainName(rr.Target, msg, off, compression, compress)
+func (rr *CNAME) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
+	off, err = packDomainName(rr.Target, msg, off, compression, compress)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *CSYNC) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *CSYNC) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint32(rr.Serial, msg, off)
 	if err != nil {
 		return off, err
@@ -206,30 +149,18 @@ func (rr *CSYNC) pack(msg []byte, off int, compression map[string]int, compress
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *DHCID) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *DHCID) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packStringBase64(rr.Digest, msg, off)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *DLV) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *DLV) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint16(rr.KeyTag, msg, off)
 	if err != nil {
 		return off, err
@@ -246,30 +177,18 @@ func (rr *DLV) pack(msg []byte, off int, compression map[string]int, compress bo
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *DNAME) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
-	off, err = PackDomainName(rr.Target, msg, off, compression, false)
+func (rr *DNAME) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
+	off, err = packDomainName(rr.Target, msg, off, compression, false)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *DNSKEY) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *DNSKEY) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint16(rr.Flags, msg, off)
 	if err != nil {
 		return off, err
@@ -286,16 +205,10 @@ func (rr *DNSKEY) pack(msg []byte, off int, compression map[string]int, compress
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *DS) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *DS) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint16(rr.KeyTag, msg, off)
 	if err != nil {
 		return off, err
@@ -312,72 +225,42 @@ func (rr *DS) pack(msg []byte, off int, compression map[string]int, compress boo
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *EID) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *EID) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packStringHex(rr.Endpoint, msg, off)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *EUI48) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *EUI48) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint48(rr.Address, msg, off)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *EUI64) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *EUI64) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint64(rr.Address, msg, off)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *GID) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *GID) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint32(rr.Gid, msg, off)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *GPOS) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *GPOS) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packString(rr.Longitude, msg, off)
 	if err != nil {
 		return off, err
@@ -390,16 +273,10 @@ func (rr *GPOS) pack(msg []byte, off int, compression map[string]int, compress b
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *HINFO) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *HINFO) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packString(rr.Cpu, msg, off)
 	if err != nil {
 		return off, err
@@ -408,16 +285,10 @@ func (rr *HINFO) pack(msg []byte, off int, compression map[string]int, compress
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *HIP) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *HIP) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint8(rr.HitLength, msg, off)
 	if err != nil {
 		return off, err
@@ -438,20 +309,30 @@ func (rr *HIP) pack(msg []byte, off int, compression map[string]int, compress bo
 	if err != nil {
 		return off, err
 	}
-	off, err = packDataDomainNames(rr.RendezvousServers, msg, off, compression, compress)
+	off, err = packDataDomainNames(rr.RendezvousServers, msg, off, compression, false)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *KEY) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
+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
 	}
-	headerEnd := off
+	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 {
 		return off, err
@@ -468,34 +349,22 @@ func (rr *KEY) pack(msg []byte, off int, compression map[string]int, compress bo
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *KX) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *KX) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint16(rr.Preference, msg, off)
 	if err != nil {
 		return off, err
 	}
-	off, err = PackDomainName(rr.Exchanger, msg, off, compression, false)
+	off, err = packDomainName(rr.Exchanger, msg, off, compression, false)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *L32) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *L32) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint16(rr.Preference, msg, off)
 	if err != nil {
 		return off, err
@@ -504,16 +373,10 @@ func (rr *L32) pack(msg []byte, off int, compression map[string]int, compress bo
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *L64) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *L64) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint16(rr.Preference, msg, off)
 	if err != nil {
 		return off, err
@@ -522,16 +385,10 @@ func (rr *L64) pack(msg []byte, off int, compression map[string]int, compress bo
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *LOC) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *LOC) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint8(rr.Version, msg, off)
 	if err != nil {
 		return off, err
@@ -560,140 +417,86 @@ func (rr *LOC) pack(msg []byte, off int, compression map[string]int, compress bo
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *LP) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *LP) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint16(rr.Preference, msg, off)
 	if err != nil {
 		return off, err
 	}
-	off, err = PackDomainName(rr.Fqdn, msg, off, compression, false)
+	off, err = packDomainName(rr.Fqdn, msg, off, compression, false)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *MB) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
-	off, err = PackDomainName(rr.Mb, msg, off, compression, compress)
+func (rr *MB) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
+	off, err = packDomainName(rr.Mb, msg, off, compression, compress)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *MD) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
-	off, err = PackDomainName(rr.Md, msg, off, compression, compress)
+func (rr *MD) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
+	off, err = packDomainName(rr.Md, msg, off, compression, compress)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *MF) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
+func (rr *MF) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
+	off, err = packDomainName(rr.Mf, msg, off, compression, compress)
 	if err != nil {
 		return off, err
 	}
-	headerEnd := off
-	off, err = PackDomainName(rr.Mf, msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *MG) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
-	off, err = PackDomainName(rr.Mg, msg, off, compression, compress)
+func (rr *MG) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
+	off, err = packDomainName(rr.Mg, msg, off, compression, compress)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *MINFO) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
-	off, err = PackDomainName(rr.Rmail, msg, off, compression, compress)
+func (rr *MINFO) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
+	off, err = packDomainName(rr.Rmail, msg, off, compression, compress)
 	if err != nil {
 		return off, err
 	}
-	off, err = PackDomainName(rr.Email, msg, off, compression, compress)
+	off, err = packDomainName(rr.Email, msg, off, compression, compress)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *MR) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
-	off, err = PackDomainName(rr.Mr, msg, off, compression, compress)
+func (rr *MR) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
+	off, err = packDomainName(rr.Mr, msg, off, compression, compress)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *MX) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *MX) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint16(rr.Preference, msg, off)
 	if err != nil {
 		return off, err
 	}
-	off, err = PackDomainName(rr.Mx, msg, off, compression, compress)
+	off, err = packDomainName(rr.Mx, msg, off, compression, compress)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *NAPTR) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *NAPTR) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint16(rr.Order, msg, off)
 	if err != nil {
 		return off, err
@@ -714,20 +517,14 @@ func (rr *NAPTR) pack(msg []byte, off int, compression map[string]int, compress
 	if err != nil {
 		return off, err
 	}
-	off, err = PackDomainName(rr.Replacement, msg, off, compression, false)
+	off, err = packDomainName(rr.Replacement, msg, off, compression, false)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *NID) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *NID) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint16(rr.Preference, msg, off)
 	if err != nil {
 		return off, err
@@ -736,73 +533,43 @@ func (rr *NID) pack(msg []byte, off int, compression map[string]int, compress bo
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *NIMLOC) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *NIMLOC) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packStringHex(rr.Locator, msg, off)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *NINFO) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *NINFO) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packStringTxt(rr.ZSData, msg, off)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *NS) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
-	off, err = PackDomainName(rr.Ns, msg, off, compression, compress)
+func (rr *NS) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
+	off, err = packDomainName(rr.Ns, msg, off, compression, compress)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *NSAPPTR) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
-	off, err = PackDomainName(rr.Ptr, msg, off, compression, false)
+func (rr *NSAPPTR) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
+	off, err = packDomainName(rr.Ptr, msg, off, compression, false)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *NSEC) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
-	off, err = PackDomainName(rr.NextDomain, msg, off, compression, false)
+func (rr *NSEC) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
+	off, err = packDomainName(rr.NextDomain, msg, off, compression, false)
 	if err != nil {
 		return off, err
 	}
@@ -810,16 +577,10 @@ func (rr *NSEC) pack(msg []byte, off int, compression map[string]int, compress b
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *NSEC3) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *NSEC3) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint8(rr.Hash, msg, off)
 	if err != nil {
 		return off, err
@@ -855,16 +616,10 @@ func (rr *NSEC3) pack(msg []byte, off int, compression map[string]int, compress
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *NSEC3PARAM) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *NSEC3PARAM) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint8(rr.Hash, msg, off)
 	if err != nil {
 		return off, err
@@ -888,94 +643,66 @@ func (rr *NSEC3PARAM) pack(msg []byte, off int, compression map[string]int, comp
 			return off, err
 		}
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *OPENPGPKEY) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
+func (rr *NULL) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
+	off, err = packStringAny(rr.Data, msg, off)
 	if err != nil {
 		return off, err
 	}
-	headerEnd := off
+	return off, nil
+}
+
+func (rr *OPENPGPKEY) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packStringBase64(rr.PublicKey, msg, off)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *OPT) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *OPT) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packDataOpt(rr.Option, msg, off)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *PTR) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
+func (rr *PTR) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
+	off, err = packDomainName(rr.Ptr, msg, off, compression, compress)
 	if err != nil {
 		return off, err
 	}
-	headerEnd := off
-	off, err = PackDomainName(rr.Ptr, msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *PX) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *PX) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint16(rr.Preference, msg, off)
 	if err != nil {
 		return off, err
 	}
-	off, err = PackDomainName(rr.Map822, msg, off, compression, false)
+	off, err = packDomainName(rr.Map822, msg, off, compression, false)
 	if err != nil {
 		return off, err
 	}
-	off, err = PackDomainName(rr.Mapx400, msg, off, compression, false)
+	off, err = packDomainName(rr.Mapx400, msg, off, compression, false)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *RFC3597) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *RFC3597) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packStringHex(rr.Rdata, msg, off)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *RKEY) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *RKEY) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint16(rr.Flags, msg, off)
 	if err != nil {
 		return off, err
@@ -992,34 +719,22 @@ func (rr *RKEY) pack(msg []byte, off int, compression map[string]int, compress b
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *RP) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
+func (rr *RP) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
+	off, err = packDomainName(rr.Mbox, msg, off, compression, false)
 	if err != nil {
 		return off, err
 	}
-	headerEnd := off
-	off, err = PackDomainName(rr.Mbox, msg, off, compression, false)
+	off, err = packDomainName(rr.Txt, msg, off, compression, false)
 	if err != nil {
 		return off, err
 	}
-	off, err = PackDomainName(rr.Txt, msg, off, compression, false)
-	if err != nil {
-		return off, err
-	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *RRSIG) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *RRSIG) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint16(rr.TypeCovered, msg, off)
 	if err != nil {
 		return off, err
@@ -1048,7 +763,7 @@ func (rr *RRSIG) pack(msg []byte, off int, compression map[string]int, compress
 	if err != nil {
 		return off, err
 	}
-	off, err = PackDomainName(rr.SignerName, msg, off, compression, false)
+	off, err = packDomainName(rr.SignerName, msg, off, compression, false)
 	if err != nil {
 		return off, err
 	}
@@ -1056,34 +771,22 @@ func (rr *RRSIG) pack(msg []byte, off int, compression map[string]int, compress
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *RT) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *RT) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint16(rr.Preference, msg, off)
 	if err != nil {
 		return off, err
 	}
-	off, err = PackDomainName(rr.Host, msg, off, compression, compress)
+	off, err = packDomainName(rr.Host, msg, off, compression, false)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *SIG) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *SIG) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint16(rr.TypeCovered, msg, off)
 	if err != nil {
 		return off, err
@@ -1112,7 +815,7 @@ func (rr *SIG) pack(msg []byte, off int, compression map[string]int, compress bo
 	if err != nil {
 		return off, err
 	}
-	off, err = PackDomainName(rr.SignerName, msg, off, compression, false)
+	off, err = packDomainName(rr.SignerName, msg, off, compression, false)
 	if err != nil {
 		return off, err
 	}
@@ -1120,16 +823,10 @@ func (rr *SIG) pack(msg []byte, off int, compression map[string]int, compress bo
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *SMIMEA) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *SMIMEA) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint8(rr.Usage, msg, off)
 	if err != nil {
 		return off, err
@@ -1146,21 +843,15 @@ func (rr *SMIMEA) pack(msg []byte, off int, compression map[string]int, compress
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *SOA) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
-	off, err = PackDomainName(rr.Ns, msg, off, compression, compress)
+func (rr *SOA) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
+	off, err = packDomainName(rr.Ns, msg, off, compression, compress)
 	if err != nil {
 		return off, err
 	}
-	off, err = PackDomainName(rr.Mbox, msg, off, compression, compress)
+	off, err = packDomainName(rr.Mbox, msg, off, compression, compress)
 	if err != nil {
 		return off, err
 	}
@@ -1184,30 +875,18 @@ func (rr *SOA) pack(msg []byte, off int, compression map[string]int, compress bo
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *SPF) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *SPF) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packStringTxt(rr.Txt, msg, off)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *SRV) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *SRV) 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
@@ -1220,20 +899,14 @@ func (rr *SRV) pack(msg []byte, off int, compression map[string]int, compress bo
 	if err != nil {
 		return off, err
 	}
-	off, err = PackDomainName(rr.Target, msg, off, compression, false)
+	off, err = packDomainName(rr.Target, msg, off, compression, false)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *SSHFP) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *SSHFP) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint8(rr.Algorithm, msg, off)
 	if err != nil {
 		return off, err
@@ -1246,16 +919,26 @@ func (rr *SSHFP) pack(msg []byte, off int, compression map[string]int, compress
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *TA) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
+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
 	}
-	headerEnd := off
+	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 {
 		return off, err
@@ -1272,35 +955,23 @@ func (rr *TA) pack(msg []byte, off int, compression map[string]int, compress boo
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *TALINK) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
-	off, err = PackDomainName(rr.PreviousName, msg, off, compression, false)
+func (rr *TALINK) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
+	off, err = packDomainName(rr.PreviousName, msg, off, compression, false)
 	if err != nil {
 		return off, err
 	}
-	off, err = PackDomainName(rr.NextName, msg, off, compression, false)
+	off, err = packDomainName(rr.NextName, msg, off, compression, false)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *TKEY) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
-	off, err = PackDomainName(rr.Algorithm, msg, off, compression, false)
+func (rr *TKEY) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
+	off, err = packDomainName(rr.Algorithm, msg, off, compression, false)
 	if err != nil {
 		return off, err
 	}
@@ -1336,16 +1007,10 @@ func (rr *TKEY) pack(msg []byte, off int, compression map[string]int, compress b
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *TLSA) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *TLSA) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint8(rr.Usage, msg, off)
 	if err != nil {
 		return off, err
@@ -1362,17 +1027,11 @@ func (rr *TLSA) pack(msg []byte, off int, compression map[string]int, compress b
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *TSIG) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
-	off, err = PackDomainName(rr.Algorithm, msg, off, compression, false)
+func (rr *TSIG) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
+	off, err = packDomainName(rr.Algorithm, msg, off, compression, false)
 	if err != nil {
 		return off, err
 	}
@@ -1408,58 +1067,34 @@ func (rr *TSIG) pack(msg []byte, off int, compression map[string]int, compress b
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *TXT) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *TXT) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packStringTxt(rr.Txt, msg, off)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *UID) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *UID) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packUint32(rr.Uid, msg, off)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *UINFO) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *UINFO) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packString(rr.Uinfo, msg, off)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *URI) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *URI) 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
@@ -1472,2144 +1107,1717 @@ func (rr *URI) pack(msg []byte, off int, compression map[string]int, compress bo
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
-func (rr *X25) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
-	off, err := rr.Hdr.pack(msg, off, compression, compress)
-	if err != nil {
-		return off, err
-	}
-	headerEnd := off
+func (rr *X25) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
 	off, err = packString(rr.PSDNAddress, msg, off)
 	if err != nil {
 		return off, err
 	}
-	rr.Header().Rdlength = uint16(off - headerEnd)
 	return off, nil
 }
 
 // unpack*() functions
 
-func unpackA(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(A)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *A) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.A, off, err = unpackDataA(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackAAAA(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(AAAA)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *AAAA) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.AAAA, off, err = unpackDataAAAA(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackAFSDB(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(AFSDB)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *AFSDB) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Subtype, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Hostname, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackANY(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(ANY)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *ANY) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
-	return rr, off, err
+	return off, nil
 }
 
-func unpackAVC(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(AVC)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, 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
 	}
-	var err error
+	return off, nil
+}
+
+func (rr *AVC) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Txt, off, err = unpackStringTxt(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackCAA(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(CAA)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *CAA) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Flag, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Tag, off, err = unpackString(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Value, off, err = unpackStringOctet(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackCDNSKEY(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(CDNSKEY)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *CDNSKEY) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Flags, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Protocol, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Algorithm, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.PublicKey, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackCDS(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(CDS)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *CDS) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.KeyTag, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Algorithm, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.DigestType, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Digest, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackCERT(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(CERT)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *CERT) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Type, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.KeyTag, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Algorithm, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Certificate, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackCNAME(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(CNAME)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *CNAME) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Target, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackCSYNC(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(CSYNC)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *CSYNC) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Serial, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Flags, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.TypeBitMap, off, err = unpackDataNsec(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackDHCID(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(DHCID)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *DHCID) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Digest, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackDLV(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(DLV)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *DLV) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.KeyTag, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Algorithm, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.DigestType, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Digest, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackDNAME(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(DNAME)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *DNAME) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Target, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackDNSKEY(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(DNSKEY)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *DNSKEY) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Flags, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Protocol, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Algorithm, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.PublicKey, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackDS(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(DS)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *DS) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.KeyTag, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Algorithm, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.DigestType, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Digest, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackEID(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(EID)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *EID) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Endpoint, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackEUI48(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(EUI48)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *EUI48) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Address, off, err = unpackUint48(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackEUI64(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(EUI64)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *EUI64) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Address, off, err = unpackUint64(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackGID(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(GID)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *GID) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Gid, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackGPOS(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(GPOS)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *GPOS) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Longitude, off, err = unpackString(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Latitude, off, err = unpackString(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Altitude, off, err = unpackString(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackHINFO(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(HINFO)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *HINFO) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Cpu, off, err = unpackString(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Os, off, err = unpackString(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackHIP(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(HIP)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *HIP) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.HitLength, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.PublicKeyAlgorithm, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.PublicKeyLength, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Hit, off, err = unpackStringHex(msg, off, off+int(rr.HitLength))
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	rr.PublicKey, off, err = unpackStringBase64(msg, off, off+int(rr.PublicKeyLength))
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	rr.RendezvousServers, off, err = unpackDataDomainNames(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackKEY(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(KEY)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, 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
 	}
-	var err error
+	return off, nil
+}
+
+func (rr *KEY) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Flags, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Protocol, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Algorithm, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.PublicKey, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackKX(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(KX)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *KX) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Preference, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Exchanger, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackL32(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(L32)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *L32) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Preference, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Locator32, off, err = unpackDataA(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackL64(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(L64)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *L64) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Preference, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Locator64, off, err = unpackUint64(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackLOC(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(LOC)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *LOC) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Version, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Size, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.HorizPre, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.VertPre, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Latitude, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Longitude, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Altitude, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackLP(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(LP)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *LP) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Preference, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Fqdn, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackMB(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(MB)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *MB) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Mb, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackMD(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(MD)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *MD) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Md, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackMF(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(MF)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *MF) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Mf, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackMG(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(MG)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *MG) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Mg, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackMINFO(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(MINFO)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *MINFO) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Rmail, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Email, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackMR(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(MR)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *MR) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Mr, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackMX(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(MX)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *MX) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Preference, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Mx, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackNAPTR(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(NAPTR)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *NAPTR) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Order, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Preference, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Flags, off, err = unpackString(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Service, off, err = unpackString(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Regexp, off, err = unpackString(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Replacement, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackNID(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(NID)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *NID) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Preference, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.NodeID, off, err = unpackUint64(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackNIMLOC(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(NIMLOC)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *NIMLOC) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Locator, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackNINFO(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(NINFO)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *NINFO) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.ZSData, off, err = unpackStringTxt(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackNS(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(NS)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *NS) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Ns, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackNSAPPTR(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(NSAPPTR)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *NSAPPTR) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Ptr, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackNSEC(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(NSEC)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *NSEC) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.NextDomain, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.TypeBitMap, off, err = unpackDataNsec(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackNSEC3(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(NSEC3)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *NSEC3) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Hash, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Flags, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Iterations, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.SaltLength, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Salt, off, err = unpackStringHex(msg, off, off+int(rr.SaltLength))
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	rr.HashLength, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.NextDomain, off, err = unpackStringBase32(msg, off, off+int(rr.HashLength))
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	rr.TypeBitMap, off, err = unpackDataNsec(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackNSEC3PARAM(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(NSEC3PARAM)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *NSEC3PARAM) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Hash, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Flags, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Iterations, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.SaltLength, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Salt, off, err = unpackStringHex(msg, off, off+int(rr.SaltLength))
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackOPENPGPKEY(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(OPENPGPKEY)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
+func (rr *NULL) unpack(msg []byte, off int) (off1 int, err error) {
+	rdStart := off
+	_ = rdStart
+
+	rr.Data, off, err = unpackStringAny(msg, off, rdStart+int(rr.Hdr.Rdlength))
+	if err != nil {
+		return off, err
 	}
-	var err error
+	return off, nil
+}
+
+func (rr *OPENPGPKEY) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.PublicKey, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackOPT(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(OPT)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *OPT) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Option, off, err = unpackDataOpt(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackPTR(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(PTR)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *PTR) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Ptr, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackPX(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(PX)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *PX) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Preference, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Map822, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Mapx400, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackRFC3597(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(RFC3597)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *RFC3597) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Rdata, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackRKEY(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(RKEY)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *RKEY) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Flags, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Protocol, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Algorithm, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.PublicKey, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackRP(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(RP)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *RP) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Mbox, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Txt, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackRRSIG(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(RRSIG)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *RRSIG) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.TypeCovered, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Algorithm, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Labels, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.OrigTtl, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Expiration, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Inception, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.KeyTag, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.SignerName, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Signature, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackRT(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(RT)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *RT) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Preference, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Host, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackSIG(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(SIG)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *SIG) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.TypeCovered, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Algorithm, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Labels, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.OrigTtl, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Expiration, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Inception, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.KeyTag, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.SignerName, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Signature, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackSMIMEA(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(SMIMEA)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *SMIMEA) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Usage, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Selector, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.MatchingType, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Certificate, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackSOA(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(SOA)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *SOA) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Ns, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Mbox, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Serial, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Refresh, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Retry, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Expire, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Minttl, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackSPF(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(SPF)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *SPF) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Txt, off, err = unpackStringTxt(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackSRV(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(SRV)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *SRV) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Priority, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Weight, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Port, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Target, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackSSHFP(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(SSHFP)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *SSHFP) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Algorithm, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Type, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.FingerPrint, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackTA(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(TA)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, 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
 	}
-	var err error
+	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
 
 	rr.KeyTag, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Algorithm, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.DigestType, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Digest, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackTALINK(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(TALINK)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *TALINK) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.PreviousName, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.NextName, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackTKEY(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(TKEY)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *TKEY) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Algorithm, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Inception, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Expiration, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Mode, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Error, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.KeySize, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Key, off, err = unpackStringHex(msg, off, off+int(rr.KeySize))
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	rr.OtherLen, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.OtherData, off, err = unpackStringHex(msg, off, off+int(rr.OtherLen))
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackTLSA(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(TLSA)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *TLSA) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Usage, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Selector, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.MatchingType, off, err = unpackUint8(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Certificate, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackTSIG(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(TSIG)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *TSIG) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Algorithm, off, err = UnpackDomainName(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.TimeSigned, off, err = unpackUint48(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Fudge, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.MACSize, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.MAC, off, err = unpackStringHex(msg, off, off+int(rr.MACSize))
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	rr.OrigId, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Error, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.OtherLen, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.OtherData, off, err = unpackStringHex(msg, off, off+int(rr.OtherLen))
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackTXT(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(TXT)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *TXT) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Txt, off, err = unpackStringTxt(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackUID(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(UID)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *UID) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Uid, off, err = unpackUint32(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackUINFO(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(UINFO)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *UINFO) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Uinfo, off, err = unpackString(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackURI(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(URI)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *URI) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.Priority, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Weight, off, err = unpackUint16(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
 	if off == len(msg) {
-		return rr, off, nil
+		return off, nil
 	}
 	rr.Target, off, err = unpackStringOctet(msg, off)
 	if err != nil {
-		return rr, off, err
+		return off, err
 	}
-	return rr, off, err
+	return off, nil
 }
 
-func unpackX25(h RR_Header, msg []byte, off int) (RR, int, error) {
-	rr := new(X25)
-	rr.Hdr = h
-	if noRdata(h) {
-		return rr, off, nil
-	}
-	var err error
+func (rr *X25) unpack(msg []byte, off int) (off1 int, err error) {
 	rdStart := off
 	_ = rdStart
 
 	rr.PSDNAddress, off, err = unpackString(msg, off)
 	if err != nil {
-		return rr, off, err
-	}
-	return rr, off, err
-}
-
-var typeToUnpack = map[uint16]func(RR_Header, []byte, int) (RR, int, error){
-	TypeA:          unpackA,
-	TypeAAAA:       unpackAAAA,
-	TypeAFSDB:      unpackAFSDB,
-	TypeANY:        unpackANY,
-	TypeAVC:        unpackAVC,
-	TypeCAA:        unpackCAA,
-	TypeCDNSKEY:    unpackCDNSKEY,
-	TypeCDS:        unpackCDS,
-	TypeCERT:       unpackCERT,
-	TypeCNAME:      unpackCNAME,
-	TypeCSYNC:      unpackCSYNC,
-	TypeDHCID:      unpackDHCID,
-	TypeDLV:        unpackDLV,
-	TypeDNAME:      unpackDNAME,
-	TypeDNSKEY:     unpackDNSKEY,
-	TypeDS:         unpackDS,
-	TypeEID:        unpackEID,
-	TypeEUI48:      unpackEUI48,
-	TypeEUI64:      unpackEUI64,
-	TypeGID:        unpackGID,
-	TypeGPOS:       unpackGPOS,
-	TypeHINFO:      unpackHINFO,
-	TypeHIP:        unpackHIP,
-	TypeKEY:        unpackKEY,
-	TypeKX:         unpackKX,
-	TypeL32:        unpackL32,
-	TypeL64:        unpackL64,
-	TypeLOC:        unpackLOC,
-	TypeLP:         unpackLP,
-	TypeMB:         unpackMB,
-	TypeMD:         unpackMD,
-	TypeMF:         unpackMF,
-	TypeMG:         unpackMG,
-	TypeMINFO:      unpackMINFO,
-	TypeMR:         unpackMR,
-	TypeMX:         unpackMX,
-	TypeNAPTR:      unpackNAPTR,
-	TypeNID:        unpackNID,
-	TypeNIMLOC:     unpackNIMLOC,
-	TypeNINFO:      unpackNINFO,
-	TypeNS:         unpackNS,
-	TypeNSAPPTR:    unpackNSAPPTR,
-	TypeNSEC:       unpackNSEC,
-	TypeNSEC3:      unpackNSEC3,
-	TypeNSEC3PARAM: unpackNSEC3PARAM,
-	TypeOPENPGPKEY: unpackOPENPGPKEY,
-	TypeOPT:        unpackOPT,
-	TypePTR:        unpackPTR,
-	TypePX:         unpackPX,
-	TypeRKEY:       unpackRKEY,
-	TypeRP:         unpackRP,
-	TypeRRSIG:      unpackRRSIG,
-	TypeRT:         unpackRT,
-	TypeSIG:        unpackSIG,
-	TypeSMIMEA:     unpackSMIMEA,
-	TypeSOA:        unpackSOA,
-	TypeSPF:        unpackSPF,
-	TypeSRV:        unpackSRV,
-	TypeSSHFP:      unpackSSHFP,
-	TypeTA:         unpackTA,
-	TypeTALINK:     unpackTALINK,
-	TypeTKEY:       unpackTKEY,
-	TypeTLSA:       unpackTLSA,
-	TypeTSIG:       unpackTSIG,
-	TypeTXT:        unpackTXT,
-	TypeUID:        unpackUID,
-	TypeUINFO:      unpackUINFO,
-	TypeURI:        unpackURI,
-	TypeX25:        unpackX25,
+		return off, err
+	}
+	return off, nil
 }
diff --git a/vendor/github.com/miekg/dns/ztypes.go b/vendor/github.com/miekg/dns/ztypes.go
index 965753b1..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) },
@@ -54,6 +56,7 @@ var TypeToRR = map[uint16]func() RR{
 	TypeNSEC:       func() RR { return new(NSEC) },
 	TypeNSEC3:      func() RR { return new(NSEC3) },
 	TypeNSEC3PARAM: func() RR { return new(NSEC3PARAM) },
+	TypeNULL:       func() RR { return new(NULL) },
 	TypeOPENPGPKEY: func() RR { return new(OPENPGPKEY) },
 	TypeOPT:        func() RR { return new(OPT) },
 	TypePTR:        func() RR { return new(PTR) },
@@ -68,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) },
@@ -86,6 +90,7 @@ var TypeToString = map[uint16]string{
 	TypeAAAA:       "AAAA",
 	TypeAFSDB:      "AFSDB",
 	TypeANY:        "ANY",
+	TypeAPL:        "APL",
 	TypeATMA:       "ATMA",
 	TypeAVC:        "AVC",
 	TypeAXFR:       "AXFR",
@@ -107,6 +112,7 @@ var TypeToString = map[uint16]string{
 	TypeGPOS:       "GPOS",
 	TypeHINFO:      "HINFO",
 	TypeHIP:        "HIP",
+	TypeHTTPS:      "HTTPS",
 	TypeISDN:       "ISDN",
 	TypeIXFR:       "IXFR",
 	TypeKEY:        "KEY",
@@ -150,6 +156,7 @@ var TypeToString = map[uint16]string{
 	TypeSPF:        "SPF",
 	TypeSRV:        "SRV",
 	TypeSSHFP:      "SSHFP",
+	TypeSVCB:       "SVCB",
 	TypeTA:         "TA",
 	TypeTALINK:     "TALINK",
 	TypeTKEY:       "TKEY",
@@ -168,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 }
@@ -187,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 }
@@ -209,6 +218,7 @@ func (rr *NSAPPTR) Header() *RR_Header    { return &rr.Hdr }
 func (rr *NSEC) Header() *RR_Header       { return &rr.Hdr }
 func (rr *NSEC3) Header() *RR_Header      { return &rr.Hdr }
 func (rr *NSEC3PARAM) Header() *RR_Header { return &rr.Hdr }
+func (rr *NULL) Header() *RR_Header       { return &rr.Hdr }
 func (rr *OPENPGPKEY) Header() *RR_Header { return &rr.Hdr }
 func (rr *OPT) Header() *RR_Header        { return &rr.Hdr }
 func (rr *PTR) Header() *RR_Header        { return &rr.Hdr }
@@ -224,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 }
@@ -236,144 +247,157 @@ func (rr *URI) Header() *RR_Header        { return &rr.Hdr }
 func (rr *X25) Header() *RR_Header        { return &rr.Hdr }
 
 // len() functions
-func (rr *A) len() int {
-	l := rr.Hdr.len()
-	l += net.IPv4len // A
+func (rr *A) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	if len(rr.A) != 0 {
+		l += net.IPv4len
+	}
 	return l
 }
-func (rr *AAAA) len() int {
-	l := rr.Hdr.len()
-	l += net.IPv6len // AAAA
+func (rr *AAAA) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	if len(rr.AAAA) != 0 {
+		l += net.IPv6len
+	}
 	return l
 }
-func (rr *AFSDB) len() int {
-	l := rr.Hdr.len()
+func (rr *AFSDB) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // Subtype
-	l += len(rr.Hostname) + 1
+	l += domainNameLen(rr.Hostname, off+l, compression, false)
 	return l
 }
-func (rr *ANY) len() int {
-	l := rr.Hdr.len()
+func (rr *ANY) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	return l
 }
-func (rr *AVC) len() int {
-	l := rr.Hdr.len()
+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 {
 		l += len(x) + 1
 	}
 	return l
 }
-func (rr *CAA) len() int {
-	l := rr.Hdr.len()
+func (rr *CAA) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l++ // Flag
 	l += len(rr.Tag) + 1
 	l += len(rr.Value)
 	return l
 }
-func (rr *CERT) len() int {
-	l := rr.Hdr.len()
+func (rr *CERT) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // Type
 	l += 2 // KeyTag
 	l++    // Algorithm
 	l += base64.StdEncoding.DecodedLen(len(rr.Certificate))
 	return l
 }
-func (rr *CNAME) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Target) + 1
+func (rr *CNAME) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.Target, off+l, compression, true)
 	return l
 }
-func (rr *DHCID) len() int {
-	l := rr.Hdr.len()
+func (rr *DHCID) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += base64.StdEncoding.DecodedLen(len(rr.Digest))
 	return l
 }
-func (rr *DNAME) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Target) + 1
+func (rr *DNAME) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.Target, off+l, compression, false)
 	return l
 }
-func (rr *DNSKEY) len() int {
-	l := rr.Hdr.len()
+func (rr *DNSKEY) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // Flags
 	l++    // Protocol
 	l++    // Algorithm
 	l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
 	return l
 }
-func (rr *DS) len() int {
-	l := rr.Hdr.len()
+func (rr *DS) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // KeyTag
 	l++    // Algorithm
 	l++    // DigestType
-	l += len(rr.Digest)/2 + 1
+	l += len(rr.Digest) / 2
 	return l
 }
-func (rr *EID) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Endpoint)/2 + 1
+func (rr *EID) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += len(rr.Endpoint) / 2
 	return l
 }
-func (rr *EUI48) len() int {
-	l := rr.Hdr.len()
+func (rr *EUI48) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 6 // Address
 	return l
 }
-func (rr *EUI64) len() int {
-	l := rr.Hdr.len()
+func (rr *EUI64) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 8 // Address
 	return l
 }
-func (rr *GID) len() int {
-	l := rr.Hdr.len()
+func (rr *GID) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 4 // Gid
 	return l
 }
-func (rr *GPOS) len() int {
-	l := rr.Hdr.len()
+func (rr *GPOS) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += len(rr.Longitude) + 1
 	l += len(rr.Latitude) + 1
 	l += len(rr.Altitude) + 1
 	return l
 }
-func (rr *HINFO) len() int {
-	l := rr.Hdr.len()
+func (rr *HINFO) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += len(rr.Cpu) + 1
 	l += len(rr.Os) + 1
 	return l
 }
-func (rr *HIP) len() int {
-	l := rr.Hdr.len()
+func (rr *HIP) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l++    // HitLength
 	l++    // PublicKeyAlgorithm
 	l += 2 // PublicKeyLength
 	l += len(rr.Hit) / 2
 	l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
 	for _, x := range rr.RendezvousServers {
-		l += len(x) + 1
+		l += domainNameLen(x, off+l, compression, false)
 	}
 	return l
 }
-func (rr *KX) len() int {
-	l := rr.Hdr.len()
+func (rr *KX) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // Preference
-	l += len(rr.Exchanger) + 1
+	l += domainNameLen(rr.Exchanger, off+l, compression, false)
 	return l
 }
-func (rr *L32) len() int {
-	l := rr.Hdr.len()
-	l += 2           // Preference
-	l += net.IPv4len // Locator32
+func (rr *L32) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += 2 // Preference
+	if len(rr.Locator32) != 0 {
+		l += net.IPv4len
+	}
 	return l
 }
-func (rr *L64) len() int {
-	l := rr.Hdr.len()
+func (rr *L64) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // Preference
 	l += 8 // Locator64
 	return l
 }
-func (rr *LOC) len() int {
-	l := rr.Hdr.len()
+func (rr *LOC) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l++    // Version
 	l++    // Size
 	l++    // HorizPre
@@ -383,89 +407,89 @@ func (rr *LOC) len() int {
 	l += 4 // Altitude
 	return l
 }
-func (rr *LP) len() int {
-	l := rr.Hdr.len()
+func (rr *LP) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // Preference
-	l += len(rr.Fqdn) + 1
+	l += domainNameLen(rr.Fqdn, off+l, compression, false)
 	return l
 }
-func (rr *MB) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Mb) + 1
+func (rr *MB) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.Mb, off+l, compression, true)
 	return l
 }
-func (rr *MD) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Md) + 1
+func (rr *MD) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.Md, off+l, compression, true)
 	return l
 }
-func (rr *MF) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Mf) + 1
+func (rr *MF) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.Mf, off+l, compression, true)
 	return l
 }
-func (rr *MG) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Mg) + 1
+func (rr *MG) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.Mg, off+l, compression, true)
 	return l
 }
-func (rr *MINFO) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Rmail) + 1
-	l += len(rr.Email) + 1
+func (rr *MINFO) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.Rmail, off+l, compression, true)
+	l += domainNameLen(rr.Email, off+l, compression, true)
 	return l
 }
-func (rr *MR) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Mr) + 1
+func (rr *MR) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.Mr, off+l, compression, true)
 	return l
 }
-func (rr *MX) len() int {
-	l := rr.Hdr.len()
+func (rr *MX) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // Preference
-	l += len(rr.Mx) + 1
+	l += domainNameLen(rr.Mx, off+l, compression, true)
 	return l
 }
-func (rr *NAPTR) len() int {
-	l := rr.Hdr.len()
+func (rr *NAPTR) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // Order
 	l += 2 // Preference
 	l += len(rr.Flags) + 1
 	l += len(rr.Service) + 1
 	l += len(rr.Regexp) + 1
-	l += len(rr.Replacement) + 1
+	l += domainNameLen(rr.Replacement, off+l, compression, false)
 	return l
 }
-func (rr *NID) len() int {
-	l := rr.Hdr.len()
+func (rr *NID) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // Preference
 	l += 8 // NodeID
 	return l
 }
-func (rr *NIMLOC) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Locator)/2 + 1
+func (rr *NIMLOC) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += len(rr.Locator) / 2
 	return l
 }
-func (rr *NINFO) len() int {
-	l := rr.Hdr.len()
+func (rr *NINFO) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	for _, x := range rr.ZSData {
 		l += len(x) + 1
 	}
 	return l
 }
-func (rr *NS) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Ns) + 1
+func (rr *NS) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.Ns, off+l, compression, true)
 	return l
 }
-func (rr *NSAPPTR) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Ptr) + 1
+func (rr *NSAPPTR) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.Ptr, off+l, compression, false)
 	return l
 }
-func (rr *NSEC3PARAM) len() int {
-	l := rr.Hdr.len()
+func (rr *NSEC3PARAM) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l++    // Hash
 	l++    // Flags
 	l += 2 // Iterations
@@ -473,44 +497,49 @@ func (rr *NSEC3PARAM) len() int {
 	l += len(rr.Salt) / 2
 	return l
 }
-func (rr *OPENPGPKEY) len() int {
-	l := rr.Hdr.len()
+func (rr *NULL) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += len(rr.Data)
+	return l
+}
+func (rr *OPENPGPKEY) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
 	return l
 }
-func (rr *PTR) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Ptr) + 1
+func (rr *PTR) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.Ptr, off+l, compression, true)
 	return l
 }
-func (rr *PX) len() int {
-	l := rr.Hdr.len()
+func (rr *PX) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // Preference
-	l += len(rr.Map822) + 1
-	l += len(rr.Mapx400) + 1
+	l += domainNameLen(rr.Map822, off+l, compression, false)
+	l += domainNameLen(rr.Mapx400, off+l, compression, false)
 	return l
 }
-func (rr *RFC3597) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Rdata)/2 + 1
+func (rr *RFC3597) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += len(rr.Rdata) / 2
 	return l
 }
-func (rr *RKEY) len() int {
-	l := rr.Hdr.len()
+func (rr *RKEY) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // Flags
 	l++    // Protocol
 	l++    // Algorithm
 	l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
 	return l
 }
-func (rr *RP) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Mbox) + 1
-	l += len(rr.Txt) + 1
+func (rr *RP) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.Mbox, off+l, compression, false)
+	l += domainNameLen(rr.Txt, off+l, compression, false)
 	return l
 }
-func (rr *RRSIG) len() int {
-	l := rr.Hdr.len()
+func (rr *RRSIG) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // TypeCovered
 	l++    // Algorithm
 	l++    // Labels
@@ -518,28 +547,28 @@ func (rr *RRSIG) len() int {
 	l += 4 // Expiration
 	l += 4 // Inception
 	l += 2 // KeyTag
-	l += len(rr.SignerName) + 1
+	l += domainNameLen(rr.SignerName, off+l, compression, false)
 	l += base64.StdEncoding.DecodedLen(len(rr.Signature))
 	return l
 }
-func (rr *RT) len() int {
-	l := rr.Hdr.len()
+func (rr *RT) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // Preference
-	l += len(rr.Host) + 1
+	l += domainNameLen(rr.Host, off+l, compression, false)
 	return l
 }
-func (rr *SMIMEA) len() int {
-	l := rr.Hdr.len()
+func (rr *SMIMEA) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l++ // Usage
 	l++ // Selector
 	l++ // MatchingType
-	l += len(rr.Certificate)/2 + 1
+	l += len(rr.Certificate) / 2
 	return l
 }
-func (rr *SOA) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Ns) + 1
-	l += len(rr.Mbox) + 1
+func (rr *SOA) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.Ns, off+l, compression, true)
+	l += domainNameLen(rr.Mbox, off+l, compression, true)
 	l += 4 // Serial
 	l += 4 // Refresh
 	l += 4 // Retry
@@ -547,45 +576,54 @@ func (rr *SOA) len() int {
 	l += 4 // Minttl
 	return l
 }
-func (rr *SPF) len() int {
-	l := rr.Hdr.len()
+func (rr *SPF) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	for _, x := range rr.Txt {
 		l += len(x) + 1
 	}
 	return l
 }
-func (rr *SRV) len() int {
-	l := rr.Hdr.len()
+func (rr *SRV) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // Priority
 	l += 2 // Weight
 	l += 2 // Port
-	l += len(rr.Target) + 1
+	l += domainNameLen(rr.Target, off+l, compression, false)
 	return l
 }
-func (rr *SSHFP) len() int {
-	l := rr.Hdr.len()
+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() int {
-	l := rr.Hdr.len()
+func (rr *TA) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // KeyTag
 	l++    // Algorithm
 	l++    // DigestType
-	l += len(rr.Digest)/2 + 1
+	l += len(rr.Digest) / 2
 	return l
 }
-func (rr *TALINK) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.PreviousName) + 1
-	l += len(rr.NextName) + 1
+func (rr *TALINK) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.PreviousName, off+l, compression, false)
+	l += domainNameLen(rr.NextName, off+l, compression, false)
 	return l
 }
-func (rr *TKEY) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Algorithm) + 1
+func (rr *TKEY) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.Algorithm, off+l, compression, false)
 	l += 4 // Inception
 	l += 4 // Expiration
 	l += 2 // Mode
@@ -596,17 +634,17 @@ func (rr *TKEY) len() int {
 	l += len(rr.OtherData) / 2
 	return l
 }
-func (rr *TLSA) len() int {
-	l := rr.Hdr.len()
+func (rr *TLSA) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l++ // Usage
 	l++ // Selector
 	l++ // MatchingType
-	l += len(rr.Certificate)/2 + 1
+	l += len(rr.Certificate) / 2
 	return l
 }
-func (rr *TSIG) len() int {
-	l := rr.Hdr.len()
-	l += len(rr.Algorithm) + 1
+func (rr *TSIG) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
+	l += domainNameLen(rr.Algorithm, off+l, compression, false)
 	l += 6 // TimeSigned
 	l += 2 // Fudge
 	l += 2 // MACSize
@@ -617,32 +655,32 @@ func (rr *TSIG) len() int {
 	l += len(rr.OtherData) / 2
 	return l
 }
-func (rr *TXT) len() int {
-	l := rr.Hdr.len()
+func (rr *TXT) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	for _, x := range rr.Txt {
 		l += len(x) + 1
 	}
 	return l
 }
-func (rr *UID) len() int {
-	l := rr.Hdr.len()
+func (rr *UID) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 4 // Uid
 	return l
 }
-func (rr *UINFO) len() int {
-	l := rr.Hdr.len()
+func (rr *UINFO) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += len(rr.Uinfo) + 1
 	return l
 }
-func (rr *URI) len() int {
-	l := rr.Hdr.len()
+func (rr *URI) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += 2 // Priority
 	l += 2 // Weight
 	l += len(rr.Target)
 	return l
 }
-func (rr *X25) len() int {
-	l := rr.Hdr.len()
+func (rr *X25) len(off int, compression map[string]struct{}) int {
+	l := rr.Hdr.len(off, compression)
 	l += len(rr.PSDNAddress) + 1
 	return l
 }
@@ -660,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)
@@ -668,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}
 }
@@ -682,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}
 }
@@ -714,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}
 }
@@ -783,12 +843,17 @@ func (rr *NSEC3) copy() RR {
 func (rr *NSEC3PARAM) copy() RR {
 	return &NSEC3PARAM{rr.Hdr, rr.Hash, rr.Flags, rr.Iterations, rr.SaltLength, rr.Salt}
 }
+func (rr *NULL) copy() RR {
+	return &NULL{rr.Hdr, rr.Data}
+}
 func (rr *OPENPGPKEY) copy() RR {
 	return &OPENPGPKEY{rr.Hdr, rr.PublicKey}
 }
 func (rr *OPT) copy() RR {
 	Option := make([]EDNS0, len(rr.Option))
-	copy(Option, rr.Option)
+	for i, e := range rr.Option {
+		Option[i] = e.copy()
+	}
 	return &OPT{rr.Hdr, Option}
 }
 func (rr *PTR) copy() RR {
@@ -812,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}
 }
@@ -829,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 6fc3b8b4..aaf07db2 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -31,7 +31,7 @@ github.com/golang/protobuf/ptypes/timestamp
 github.com/gorilla/handlers
 # github.com/matttproud/golang_protobuf_extensions v1.0.1
 github.com/matttproud/golang_protobuf_extensions/pbutil
-# github.com/miekg/dns v1.0.14
+# github.com/miekg/dns v1.1.35
 ## explicit
 github.com/miekg/dns
 # github.com/openzipkin/zipkin-go v0.2.5
-- 
GitLab