mirror of
https://github.com/prometheus/prometheus.git
synced 2024-12-24 05:04:05 -08:00
Add miekg/dns 1.1.4
Signed-off-by: Erik Hollensbe <github@hollensbe.org>
This commit is contained in:
parent
9b8bbe3246
commit
9154e9aca8
2
go.mod
2
go.mod
|
@ -66,7 +66,7 @@ require (
|
||||||
github.com/lib/pq v1.0.0 // indirect
|
github.com/lib/pq v1.0.0 // indirect
|
||||||
github.com/lightstep/lightstep-tracer-go v0.15.6 // indirect
|
github.com/lightstep/lightstep-tracer-go v0.15.6 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.3 // indirect
|
github.com/mattn/go-runewidth v0.0.3 // indirect
|
||||||
github.com/miekg/dns v1.0.4
|
github.com/miekg/dns v1.1.4
|
||||||
github.com/mitchellh/go-homedir v0.0.0-20180523094522-3864e76763d9 // indirect
|
github.com/mitchellh/go-homedir v0.0.0-20180523094522-3864e76763d9 // indirect
|
||||||
github.com/mitchellh/go-testing-interface v1.0.0 // indirect
|
github.com/mitchellh/go-testing-interface v1.0.0 // indirect
|
||||||
github.com/mitchellh/reflectwalk v1.0.0 // indirect
|
github.com/mitchellh/reflectwalk v1.0.0 // indirect
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -174,8 +174,8 @@ github.com/mattn/go-runewidth v0.0.3 h1:a+kO+98RDGEfo6asOGMmpodZq4FNtnGP54yps8Bz
|
||||||
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
github.com/miekg/dns v1.0.4 h1:Ec3LTJwwzqT1++63P12fhtdEbQhtPE7TBdD6rlhqrMM=
|
github.com/miekg/dns v1.1.4 h1:rCMZsU2ScVSYcAsOXgmC6+AKOK+6pmQTOcw03nfwYV0=
|
||||||
github.com/miekg/dns v1.0.4/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
github.com/miekg/dns v1.1.4/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||||
github.com/mitchellh/go-homedir v0.0.0-20180523094522-3864e76763d9 h1:Y94YB7jrsihrbGSqRNMwRWJ2/dCxr0hdC2oPRohkx0A=
|
github.com/mitchellh/go-homedir v0.0.0-20180523094522-3864e76763d9 h1:Y94YB7jrsihrbGSqRNMwRWJ2/dCxr0hdC2oPRohkx0A=
|
||||||
github.com/mitchellh/go-homedir v0.0.0-20180523094522-3864e76763d9/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v0.0.0-20180523094522-3864e76763d9/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
|
github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
|
||||||
|
|
12
vendor/github.com/miekg/dns/.travis.yml
generated
vendored
12
vendor/github.com/miekg/dns/.travis.yml
generated
vendored
|
@ -1,12 +1,10 @@
|
||||||
language: go
|
language: go
|
||||||
sudo: false
|
sudo: false
|
||||||
go:
|
|
||||||
- 1.9.x
|
|
||||||
- tip
|
|
||||||
|
|
||||||
env:
|
go:
|
||||||
- TESTS="-race -v -bench=. -coverprofile=coverage.txt -covermode=atomic"
|
- 1.10.x
|
||||||
- TESTS="-race -v ./..."
|
- 1.11.x
|
||||||
|
- tip
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
# don't use the miekg/dns when testing forks
|
# don't use the miekg/dns when testing forks
|
||||||
|
@ -14,7 +12,7 @@ before_install:
|
||||||
- ln -s $TRAVIS_BUILD_DIR $GOPATH/src/github.com/miekg/ || true
|
- ln -s $TRAVIS_BUILD_DIR $GOPATH/src/github.com/miekg/ || true
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- go test $TESTS
|
- go test -race -v -bench=. -coverprofile=coverage.txt -covermode=atomic ./...
|
||||||
|
|
||||||
after_success:
|
after_success:
|
||||||
- bash <(curl -s https://codecov.io/bash)
|
- bash <(curl -s https://codecov.io/bash)
|
||||||
|
|
46
vendor/github.com/miekg/dns/Gopkg.lock
generated
vendored
46
vendor/github.com/miekg/dns/Gopkg.lock
generated
vendored
|
@ -3,19 +3,55 @@
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:6914c49eed986dfb8dffb33516fa129c49929d4d873f41e073c83c11c372b870"
|
||||||
name = "golang.org/x/crypto"
|
name = "golang.org/x/crypto"
|
||||||
packages = ["ed25519","ed25519/internal/edwards25519"]
|
packages = [
|
||||||
revision = "b080dc9a8c480b08e698fb1219160d598526310f"
|
"ed25519",
|
||||||
|
"ed25519/internal/edwards25519",
|
||||||
|
]
|
||||||
|
pruneopts = ""
|
||||||
|
revision = "e3636079e1a4c1f337f212cc5cd2aca108f6c900"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:08e41d63f8dac84d83797368b56cf0b339e42d0224e5e56668963c28aec95685"
|
||||||
name = "golang.org/x/net"
|
name = "golang.org/x/net"
|
||||||
packages = ["bpf","internal/iana","internal/socket","ipv4","ipv6"]
|
packages = [
|
||||||
revision = "894f8ed5849b15b810ae41e9590a0d05395bba27"
|
"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]
|
[solve-meta]
|
||||||
analyzer-name = "dep"
|
analyzer-name = "dep"
|
||||||
analyzer-version = 1
|
analyzer-version = 1
|
||||||
inputs-digest = "c4abc38abaeeeeb9be92455c9c02cae32841122b8982aaa067ef25bb8e86ff9d"
|
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-name = "gps-cdcl"
|
||||||
solver-version = 1
|
solver-version = 1
|
||||||
|
|
12
vendor/github.com/miekg/dns/Gopkg.toml
generated
vendored
12
vendor/github.com/miekg/dns/Gopkg.toml
generated
vendored
|
@ -24,3 +24,15 @@
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "golang.org/x/crypto"
|
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"
|
||||||
|
|
61
vendor/github.com/miekg/dns/README.md
generated
vendored
61
vendor/github.com/miekg/dns/README.md
generated
vendored
|
@ -7,10 +7,10 @@
|
||||||
|
|
||||||
> Less is more.
|
> Less is more.
|
||||||
|
|
||||||
Complete and usable DNS library. All widely used Resource Records are supported, including the
|
Complete and usable DNS library. All Resource Records are supported, including the DNSSEC types.
|
||||||
DNSSEC types. It follows a lean and mean philosophy. If there is stuff you should know as a DNS
|
It follows a lean and mean philosophy. If there is stuff you should know as a DNS programmer there
|
||||||
programmer there isn't a convenience function for it. Server side and client side programming is
|
isn't a convenience function for it. Server side and client side programming is supported, i.e. you
|
||||||
supported, i.e. you can build servers and resolvers with it.
|
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,
|
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.
|
avoiding breaking changes wherever reasonable. We support the last two versions of Go.
|
||||||
|
@ -42,10 +42,9 @@ A not-so-up-to-date-list-that-may-be-actually-current:
|
||||||
* https://github.com/tianon/rawdns
|
* https://github.com/tianon/rawdns
|
||||||
* https://mesosphere.github.io/mesos-dns/
|
* https://mesosphere.github.io/mesos-dns/
|
||||||
* https://pulse.turbobytes.com/
|
* https://pulse.turbobytes.com/
|
||||||
* https://play.google.com/store/apps/details?id=com.turbobytes.dig
|
|
||||||
* https://github.com/fcambus/statzone
|
* https://github.com/fcambus/statzone
|
||||||
* https://github.com/benschw/dns-clb-go
|
* https://github.com/benschw/dns-clb-go
|
||||||
* https://github.com/corny/dnscheck for http://public-dns.info/
|
* https://github.com/corny/dnscheck for <http://public-dns.info/>
|
||||||
* https://namesmith.io
|
* https://namesmith.io
|
||||||
* https://github.com/miekg/unbound
|
* https://github.com/miekg/unbound
|
||||||
* https://github.com/miekg/exdns
|
* https://github.com/miekg/exdns
|
||||||
|
@ -56,7 +55,7 @@ A not-so-up-to-date-list-that-may-be-actually-current:
|
||||||
* https://github.com/bamarni/dockness
|
* https://github.com/bamarni/dockness
|
||||||
* https://github.com/fffaraz/microdns
|
* https://github.com/fffaraz/microdns
|
||||||
* http://kelda.io
|
* http://kelda.io
|
||||||
* https://github.com/ipdcode/hades (JD.COM)
|
* https://github.com/ipdcode/hades <https://jd.com>
|
||||||
* https://github.com/StackExchange/dnscontrol/
|
* https://github.com/StackExchange/dnscontrol/
|
||||||
* https://www.dnsperf.com/
|
* https://www.dnsperf.com/
|
||||||
* https://dnssectest.net/
|
* https://dnssectest.net/
|
||||||
|
@ -64,29 +63,32 @@ A not-so-up-to-date-list-that-may-be-actually-current:
|
||||||
* https://github.com/oif/apex
|
* https://github.com/oif/apex
|
||||||
* https://github.com/jedisct1/dnscrypt-proxy
|
* https://github.com/jedisct1/dnscrypt-proxy
|
||||||
* https://github.com/jedisct1/rpdns
|
* 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
|
||||||
|
|
||||||
Send pull request if you want to be listed here.
|
Send pull request if you want to be listed here.
|
||||||
|
|
||||||
# Features
|
# Features
|
||||||
|
|
||||||
* UDP/TCP queries, IPv4 and IPv6;
|
* UDP/TCP queries, IPv4 and IPv6
|
||||||
* RFC 1035 zone file parsing ($INCLUDE, $ORIGIN, $TTL and $GENERATE (for all record types) are supported;
|
* RFC 1035 zone file parsing ($INCLUDE, $ORIGIN, $TTL and $GENERATE (for all record types) are supported
|
||||||
* Fast:
|
* Fast
|
||||||
* Reply speed around ~ 80K qps (faster hardware results in more qps);
|
* Server side programming (mimicking the net/http package)
|
||||||
* Parsing RRs ~ 100K RR/s, that's 5M records in about 50 seconds;
|
* Client side programming
|
||||||
* Server side programming (mimicking the net/http package);
|
* DNSSEC: signing, validating and key generation for DSA, RSA, ECDSA and Ed25519
|
||||||
* Client side programming;
|
* EDNS0, NSID, Cookies
|
||||||
* DNSSEC: signing, validating and key generation for DSA, RSA, ECDSA and Ed25519;
|
* AXFR/IXFR
|
||||||
* EDNS0, NSID, Cookies;
|
* TSIG, SIG(0)
|
||||||
* AXFR/IXFR;
|
* DNS over TLS (DoT): encrypted connection between client and server over TCP
|
||||||
* TSIG, SIG(0);
|
* DNS name compression
|
||||||
* DNS over TLS: optional encrypted connection between client and server;
|
|
||||||
* DNS name compression;
|
|
||||||
* Depends only on the standard library.
|
|
||||||
|
|
||||||
Have fun!
|
Have fun!
|
||||||
|
|
||||||
Miek Gieben - 2010-2012 - <miek@miek.nl>
|
Miek Gieben - 2010-2012 - <miek@miek.nl>
|
||||||
|
DNS Authors 2012-
|
||||||
|
|
||||||
# Building
|
# Building
|
||||||
|
|
||||||
|
@ -98,8 +100,8 @@ work:
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
A short "how to use the API" is at the beginning of doc.go (this also will show
|
A short "how to use the API" is at the beginning of doc.go (this also will show when you call `godoc
|
||||||
when you call `godoc github.com/miekg/dns`).
|
github.com/miekg/dns`).
|
||||||
|
|
||||||
Example programs can be found in the `github.com/miekg/exdns` repository.
|
Example programs can be found in the `github.com/miekg/exdns` repository.
|
||||||
|
|
||||||
|
@ -157,12 +159,13 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
|
||||||
* 7553 - URI record
|
* 7553 - URI record
|
||||||
* 7858 - DNS over TLS: Initiation and Performance Considerations
|
* 7858 - DNS over TLS: Initiation and Performance Considerations
|
||||||
* 7871 - EDNS0 Client Subnet
|
* 7871 - EDNS0 Client Subnet
|
||||||
* 7873 - Domain Name System (DNS) Cookies (draft-ietf-dnsop-cookies)
|
* 7873 - Domain Name System (DNS) Cookies
|
||||||
* 8080 - EdDSA for DNSSEC
|
* 8080 - EdDSA for DNSSEC
|
||||||
|
* 8499 - DNS Terminology
|
||||||
|
|
||||||
## Loosely based upon
|
## Loosely Based Upon
|
||||||
|
|
||||||
* `ldns`
|
* ldns - <https://nlnetlabs.nl/projects/ldns/about/>
|
||||||
* `NSD`
|
* NSD - <https://nlnetlabs.nl/projects/nsd/about/>
|
||||||
* `Net::DNS`
|
* Net::DNS - <http://www.net-dns.org/>
|
||||||
* `GRONG`
|
* GRONG - <https://github.com/bortzmeyer/grong>
|
||||||
|
|
56
vendor/github.com/miekg/dns/acceptfunc.go
generated
vendored
Normal file
56
vendor/github.com/miekg/dns/acceptfunc.go
generated
vendored
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
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.
|
||||||
|
)
|
||||||
|
|
||||||
|
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 MsgReject
|
||||||
|
}
|
||||||
|
|
||||||
|
if isZero := dh.Bits&_Z != 0; isZero {
|
||||||
|
return MsgReject
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
86
vendor/github.com/miekg/dns/client.go
generated
vendored
86
vendor/github.com/miekg/dns/client.go
generated
vendored
|
@ -13,16 +13,16 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const dnsTimeout time.Duration = 2 * time.Second
|
const (
|
||||||
const tcpIdleTimeout time.Duration = 8 * time.Second
|
dnsTimeout time.Duration = 2 * time.Second
|
||||||
|
tcpIdleTimeout time.Duration = 8 * time.Second
|
||||||
|
)
|
||||||
|
|
||||||
// A Conn represents a connection to a DNS server.
|
// A Conn represents a connection to a DNS server.
|
||||||
type Conn struct {
|
type Conn struct {
|
||||||
net.Conn // a net.Conn holding the connection
|
net.Conn // a net.Conn holding the connection
|
||||||
UDPSize uint16 // minimum receive buffer for UDP messages
|
UDPSize uint16 // minimum receive buffer for UDP messages
|
||||||
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
|
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
|
||||||
rtt time.Duration
|
|
||||||
t time.Time
|
|
||||||
tsigRequestMAC string
|
tsigRequestMAC string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,33 +83,22 @@ func (c *Client) Dial(address string) (conn *Conn, err error) {
|
||||||
// create a new dialer with the appropriate timeout
|
// create a new dialer with the appropriate timeout
|
||||||
var d net.Dialer
|
var d net.Dialer
|
||||||
if c.Dialer == nil {
|
if c.Dialer == nil {
|
||||||
d = net.Dialer{}
|
d = net.Dialer{Timeout: c.getTimeoutForRequest(c.dialTimeout())}
|
||||||
} else {
|
} else {
|
||||||
d = net.Dialer(*c.Dialer)
|
d = *c.Dialer
|
||||||
}
|
}
|
||||||
d.Timeout = c.getTimeoutForRequest(c.writeTimeout())
|
|
||||||
|
|
||||||
network := "udp"
|
network := c.Net
|
||||||
useTLS := false
|
if network == "" {
|
||||||
|
network = "udp"
|
||||||
switch c.Net {
|
|
||||||
case "tcp-tls":
|
|
||||||
network = "tcp"
|
|
||||||
useTLS = true
|
|
||||||
case "tcp4-tls":
|
|
||||||
network = "tcp4"
|
|
||||||
useTLS = true
|
|
||||||
case "tcp6-tls":
|
|
||||||
network = "tcp6"
|
|
||||||
useTLS = true
|
|
||||||
default:
|
|
||||||
if c.Net != "" {
|
|
||||||
network = c.Net
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useTLS := strings.HasPrefix(network, "tcp") && strings.HasSuffix(network, "-tls")
|
||||||
|
|
||||||
conn = new(Conn)
|
conn = new(Conn)
|
||||||
if useTLS {
|
if useTLS {
|
||||||
|
network = strings.TrimSuffix(network, "-tls")
|
||||||
|
|
||||||
conn.Conn, err = tls.DialWithDialer(&d, network, address, c.TLSConfig)
|
conn.Conn, err = tls.DialWithDialer(&d, network, address, c.TLSConfig)
|
||||||
} else {
|
} else {
|
||||||
conn.Conn, err = d.Dial(network, address)
|
conn.Conn, err = d.Dial(network, address)
|
||||||
|
@ -117,6 +106,7 @@ func (c *Client) Dial(address string) (conn *Conn, err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,8 +167,9 @@ func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro
|
||||||
}
|
}
|
||||||
|
|
||||||
co.TsigSecret = c.TsigSecret
|
co.TsigSecret = c.TsigSecret
|
||||||
|
t := time.Now()
|
||||||
// write with the appropriate write timeout
|
// write with the appropriate write timeout
|
||||||
co.SetWriteDeadline(time.Now().Add(c.getTimeoutForRequest(c.writeTimeout())))
|
co.SetWriteDeadline(t.Add(c.getTimeoutForRequest(c.writeTimeout())))
|
||||||
if err = co.WriteMsg(m); err != nil {
|
if err = co.WriteMsg(m); err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
@ -188,7 +179,8 @@ func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro
|
||||||
if err == nil && r.Id != m.Id {
|
if err == nil && r.Id != m.Id {
|
||||||
err = ErrId
|
err = ErrId
|
||||||
}
|
}
|
||||||
return r, co.rtt, err
|
rtt = time.Since(t)
|
||||||
|
return r, rtt, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadMsg reads a message from the connection co.
|
// ReadMsg reads a message from the connection co.
|
||||||
|
@ -240,7 +232,6 @@ func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) {
|
||||||
}
|
}
|
||||||
p = make([]byte, l)
|
p = make([]byte, l)
|
||||||
n, err = tcpRead(r, p)
|
n, err = tcpRead(r, p)
|
||||||
co.rtt = time.Since(co.t)
|
|
||||||
default:
|
default:
|
||||||
if co.UDPSize > MinMsgSize {
|
if co.UDPSize > MinMsgSize {
|
||||||
p = make([]byte, co.UDPSize)
|
p = make([]byte, co.UDPSize)
|
||||||
|
@ -248,7 +239,6 @@ func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) {
|
||||||
p = make([]byte, MinMsgSize)
|
p = make([]byte, MinMsgSize)
|
||||||
}
|
}
|
||||||
n, err = co.Read(p)
|
n, err = co.Read(p)
|
||||||
co.rtt = time.Since(co.t)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -330,16 +320,12 @@ func (co *Conn) Read(p []byte) (n int, err error) {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
if l > len(p) {
|
if l > len(p) {
|
||||||
return int(l), io.ErrShortBuffer
|
return l, io.ErrShortBuffer
|
||||||
}
|
}
|
||||||
return tcpRead(r, p[:l])
|
return tcpRead(r, p[:l])
|
||||||
}
|
}
|
||||||
// UDP connection
|
// UDP connection
|
||||||
n, err = co.Conn.Read(p)
|
return co.Conn.Read(p)
|
||||||
if err != nil {
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
return n, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteMsg sends a message through the connection co.
|
// WriteMsg sends a message through the connection co.
|
||||||
|
@ -361,11 +347,8 @@ func (co *Conn) WriteMsg(m *Msg) (err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
co.t = time.Now()
|
_, err = co.Write(out)
|
||||||
if _, err = co.Write(out); err != nil {
|
return err
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write implements the net.Conn Write method.
|
// Write implements the net.Conn Write method.
|
||||||
|
@ -387,8 +370,7 @@ func (co *Conn) Write(p []byte) (n int, err error) {
|
||||||
n, err := io.Copy(w, bytes.NewReader(p))
|
n, err := io.Copy(w, bytes.NewReader(p))
|
||||||
return int(n), err
|
return int(n), err
|
||||||
}
|
}
|
||||||
n, err = co.Conn.Write(p)
|
return co.Conn.Write(p)
|
||||||
return n, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the appropriate timeout for a specific request
|
// Return the appropriate timeout for a specific request
|
||||||
|
@ -455,11 +437,7 @@ func ExchangeConn(c net.Conn, m *Msg) (r *Msg, err error) {
|
||||||
// DialTimeout acts like Dial but takes a timeout.
|
// DialTimeout acts like Dial but takes a timeout.
|
||||||
func DialTimeout(network, address string, timeout time.Duration) (conn *Conn, err error) {
|
func DialTimeout(network, address string, timeout time.Duration) (conn *Conn, err error) {
|
||||||
client := Client{Net: network, Dialer: &net.Dialer{Timeout: timeout}}
|
client := Client{Net: network, Dialer: &net.Dialer{Timeout: timeout}}
|
||||||
conn, err = client.Dial(address)
|
return client.Dial(address)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return conn, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialWithTLS connects to the address on the named network with TLS.
|
// DialWithTLS connects to the address on the named network with TLS.
|
||||||
|
@ -468,12 +446,7 @@ func DialWithTLS(network, address string, tlsConfig *tls.Config) (conn *Conn, er
|
||||||
network += "-tls"
|
network += "-tls"
|
||||||
}
|
}
|
||||||
client := Client{Net: network, TLSConfig: tlsConfig}
|
client := Client{Net: network, TLSConfig: tlsConfig}
|
||||||
conn, err = client.Dial(address)
|
return client.Dial(address)
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return conn, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialTimeoutWithTLS acts like DialWithTLS but takes a timeout.
|
// DialTimeoutWithTLS acts like DialWithTLS but takes a timeout.
|
||||||
|
@ -482,11 +455,7 @@ func DialTimeoutWithTLS(network, address string, tlsConfig *tls.Config, timeout
|
||||||
network += "-tls"
|
network += "-tls"
|
||||||
}
|
}
|
||||||
client := Client{Net: network, Dialer: &net.Dialer{Timeout: timeout}, TLSConfig: tlsConfig}
|
client := Client{Net: network, Dialer: &net.Dialer{Timeout: timeout}, TLSConfig: tlsConfig}
|
||||||
conn, err = client.Dial(address)
|
return client.Dial(address)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return conn, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExchangeContext acts like Exchange, but honors the deadline on the provided
|
// ExchangeContext acts like Exchange, but honors the deadline on the provided
|
||||||
|
@ -497,10 +466,11 @@ func (c *Client) ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg,
|
||||||
if deadline, ok := ctx.Deadline(); !ok {
|
if deadline, ok := ctx.Deadline(); !ok {
|
||||||
timeout = 0
|
timeout = 0
|
||||||
} else {
|
} else {
|
||||||
timeout = deadline.Sub(time.Now())
|
timeout = time.Until(deadline)
|
||||||
}
|
}
|
||||||
// not passing the context to the underlying calls, as the API does not support
|
// 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.
|
// context. For timeouts you should set up Client.Dialer and call Client.Exchange.
|
||||||
|
// TODO(tmthrgd,miekg): this is a race condition.
|
||||||
c.Dialer = &net.Dialer{Timeout: timeout}
|
c.Dialer = &net.Dialer{Timeout: timeout}
|
||||||
return c.Exchange(m, a)
|
return c.Exchange(m, a)
|
||||||
}
|
}
|
||||||
|
|
2
vendor/github.com/miekg/dns/clientconfig.go
generated
vendored
2
vendor/github.com/miekg/dns/clientconfig.go
generated
vendored
|
@ -91,7 +91,7 @@ func ClientConfigFromReader(resolvconf io.Reader) (*ClientConfig, error) {
|
||||||
n = 1
|
n = 1
|
||||||
}
|
}
|
||||||
c.Timeout = n
|
c.Timeout = n
|
||||||
case len(s) >= 8 && s[:9] == "attempts:":
|
case len(s) >= 9 && s[:9] == "attempts:":
|
||||||
n, _ := strconv.Atoi(s[9:])
|
n, _ := strconv.Atoi(s[9:])
|
||||||
if n < 1 {
|
if n < 1 {
|
||||||
n = 1
|
n = 1
|
||||||
|
|
188
vendor/github.com/miekg/dns/compress_generate.go
generated
vendored
188
vendor/github.com/miekg/dns/compress_generate.go
generated
vendored
|
@ -1,188 +0,0 @@
|
||||||
//+build ignore
|
|
||||||
|
|
||||||
// compression_generate.go is meant to run with go generate. It will use
|
|
||||||
// go/{importer,types} to track down all the RR struct types. Then for each type
|
|
||||||
// it will look to see if there are (compressible) names, if so it will add that
|
|
||||||
// type to compressionLenHelperType and comressionLenSearchType which "fake" the
|
|
||||||
// compression so that Len() is fast.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"go/format"
|
|
||||||
"go/importer"
|
|
||||||
"go/types"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
var packageHdr = `
|
|
||||||
// Code generated by "go run compress_generate.go"; DO NOT EDIT.
|
|
||||||
|
|
||||||
package dns
|
|
||||||
|
|
||||||
`
|
|
||||||
|
|
||||||
// getTypeStruct will take a type and the package scope, and return the
|
|
||||||
// (innermost) struct if the type is considered a RR type (currently defined as
|
|
||||||
// those structs beginning with a RR_Header, could be redefined as implementing
|
|
||||||
// the RR interface). The bool return value indicates if embedded structs were
|
|
||||||
// resolved.
|
|
||||||
func getTypeStruct(t types.Type, scope *types.Scope) (*types.Struct, bool) {
|
|
||||||
st, ok := t.Underlying().(*types.Struct)
|
|
||||||
if !ok {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
if st.Field(0).Type() == scope.Lookup("RR_Header").Type() {
|
|
||||||
return st, false
|
|
||||||
}
|
|
||||||
if st.Field(0).Anonymous() {
|
|
||||||
st, _ := getTypeStruct(st.Field(0).Type(), scope)
|
|
||||||
return st, true
|
|
||||||
}
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// Import and type-check the package
|
|
||||||
pkg, err := importer.Default().Import("github.com/miekg/dns")
|
|
||||||
fatalIfErr(err)
|
|
||||||
scope := pkg.Scope()
|
|
||||||
|
|
||||||
var domainTypes []string // Types that have a domain name in them (either compressible or not).
|
|
||||||
var cdomainTypes []string // Types that have a compressible domain name in them (subset of domainType)
|
|
||||||
Names:
|
|
||||||
for _, name := range scope.Names() {
|
|
||||||
o := scope.Lookup(name)
|
|
||||||
if o == nil || !o.Exported() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
st, _ := getTypeStruct(o.Type(), scope)
|
|
||||||
if st == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if name == "PrivateRR" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if scope.Lookup("Type"+o.Name()) == nil && o.Name() != "RFC3597" {
|
|
||||||
log.Fatalf("Constant Type%s does not exist.", o.Name())
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 1; i < st.NumFields(); i++ {
|
|
||||||
if _, ok := st.Field(i).Type().(*types.Slice); ok {
|
|
||||||
if st.Tag(i) == `dns:"domain-name"` {
|
|
||||||
domainTypes = append(domainTypes, o.Name())
|
|
||||||
continue Names
|
|
||||||
}
|
|
||||||
if st.Tag(i) == `dns:"cdomain-name"` {
|
|
||||||
cdomainTypes = append(cdomainTypes, o.Name())
|
|
||||||
domainTypes = append(domainTypes, o.Name())
|
|
||||||
continue Names
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case st.Tag(i) == `dns:"domain-name"`:
|
|
||||||
domainTypes = append(domainTypes, o.Name())
|
|
||||||
continue Names
|
|
||||||
case st.Tag(i) == `dns:"cdomain-name"`:
|
|
||||||
cdomainTypes = append(cdomainTypes, o.Name())
|
|
||||||
domainTypes = append(domainTypes, o.Name())
|
|
||||||
continue Names
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
b := &bytes.Buffer{}
|
|
||||||
b.WriteString(packageHdr)
|
|
||||||
|
|
||||||
// compressionLenHelperType - all types that have domain-name/cdomain-name can be used for compressing names
|
|
||||||
|
|
||||||
fmt.Fprint(b, "func compressionLenHelperType(c map[string]int, r RR) {\n")
|
|
||||||
fmt.Fprint(b, "switch x := r.(type) {\n")
|
|
||||||
for _, name := range domainTypes {
|
|
||||||
o := scope.Lookup(name)
|
|
||||||
st, _ := getTypeStruct(o.Type(), scope)
|
|
||||||
|
|
||||||
fmt.Fprintf(b, "case *%s:\n", name)
|
|
||||||
for i := 1; i < st.NumFields(); i++ {
|
|
||||||
out := func(s string) { fmt.Fprintf(b, "compressionLenHelper(c, x.%s)\n", st.Field(i).Name()) }
|
|
||||||
|
|
||||||
if _, ok := st.Field(i).Type().(*types.Slice); ok {
|
|
||||||
switch st.Tag(i) {
|
|
||||||
case `dns:"domain-name"`:
|
|
||||||
fallthrough
|
|
||||||
case `dns:"cdomain-name"`:
|
|
||||||
// For HIP we need to slice over the elements in this slice.
|
|
||||||
fmt.Fprintf(b, `for i := range x.%s {
|
|
||||||
compressionLenHelper(c, x.%s[i])
|
|
||||||
}
|
|
||||||
`, st.Field(i).Name(), st.Field(i).Name())
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case st.Tag(i) == `dns:"cdomain-name"`:
|
|
||||||
fallthrough
|
|
||||||
case st.Tag(i) == `dns:"domain-name"`:
|
|
||||||
out(st.Field(i).Name())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fmt.Fprintln(b, "}\n}\n\n")
|
|
||||||
|
|
||||||
// compressionLenSearchType - search cdomain-tags types for compressible names.
|
|
||||||
|
|
||||||
fmt.Fprint(b, "func compressionLenSearchType(c map[string]int, r RR) (int, bool) {\n")
|
|
||||||
fmt.Fprint(b, "switch x := r.(type) {\n")
|
|
||||||
for _, name := range cdomainTypes {
|
|
||||||
o := scope.Lookup(name)
|
|
||||||
st, _ := getTypeStruct(o.Type(), scope)
|
|
||||||
|
|
||||||
fmt.Fprintf(b, "case *%s:\n", name)
|
|
||||||
j := 1
|
|
||||||
for i := 1; i < st.NumFields(); i++ {
|
|
||||||
out := func(s string, j int) {
|
|
||||||
fmt.Fprintf(b, "k%d, ok%d := compressionLenSearch(c, x.%s)\n", j, j, st.Field(i).Name())
|
|
||||||
}
|
|
||||||
|
|
||||||
// There are no slice types with names that can be compressed.
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case st.Tag(i) == `dns:"cdomain-name"`:
|
|
||||||
out(st.Field(i).Name(), j)
|
|
||||||
j++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
k := "k1"
|
|
||||||
ok := "ok1"
|
|
||||||
for i := 2; i < j; i++ {
|
|
||||||
k += fmt.Sprintf(" + k%d", i)
|
|
||||||
ok += fmt.Sprintf(" && ok%d", i)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(b, "return %s, %s\n", k, ok)
|
|
||||||
}
|
|
||||||
fmt.Fprintln(b, "}\nreturn 0, false\n}\n\n")
|
|
||||||
|
|
||||||
// gofmt
|
|
||||||
res, err := format.Source(b.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
b.WriteTo(os.Stderr)
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err := os.Create("zcompress.go")
|
|
||||||
fatalIfErr(err)
|
|
||||||
defer f.Close()
|
|
||||||
f.Write(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
func fatalIfErr(err error) {
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
100
vendor/github.com/miekg/dns/defaults.go
generated
vendored
100
vendor/github.com/miekg/dns/defaults.go
generated
vendored
|
@ -4,6 +4,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
const hexDigit = "0123456789abcdef"
|
const hexDigit = "0123456789abcdef"
|
||||||
|
@ -163,11 +164,72 @@ func (dns *Msg) IsEdns0() *OPT {
|
||||||
// the number of labels. When false is returned the number of labels is not
|
// 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
|
// 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
|
// 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
|
// label fits in 63 characters and that the entire name will fit into the 255
|
||||||
// string s. I.e. a domain name longer than 255 characters is considered valid.
|
// octet wire format limit.
|
||||||
func IsDomainName(s string) (labels int, ok bool) {
|
func IsDomainName(s string) (labels int, ok bool) {
|
||||||
_, labels, err := packDomainName(s, nil, 0, nil, false)
|
// XXX: The logic in this function was copied from packDomainName and
|
||||||
return labels, err == nil
|
// 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
|
// IsSubDomain checks if child is indeed a child of the parent. If child and parent
|
||||||
|
@ -181,7 +243,7 @@ func IsSubDomain(parent, child string) bool {
|
||||||
// The checking is performed on the binary payload.
|
// The checking is performed on the binary payload.
|
||||||
func IsMsg(buf []byte) error {
|
func IsMsg(buf []byte) error {
|
||||||
// Header
|
// Header
|
||||||
if len(buf) < 12 {
|
if len(buf) < headerSize {
|
||||||
return errors.New("dns: bad message header")
|
return errors.New("dns: bad message header")
|
||||||
}
|
}
|
||||||
// Header: Opcode
|
// Header: Opcode
|
||||||
|
@ -191,11 +253,18 @@ func IsMsg(buf []byte) error {
|
||||||
|
|
||||||
// IsFqdn checks if a domain name is fully qualified.
|
// IsFqdn checks if a domain name is fully qualified.
|
||||||
func IsFqdn(s string) bool {
|
func IsFqdn(s string) bool {
|
||||||
l := len(s)
|
s2 := strings.TrimSuffix(s, ".")
|
||||||
if l == 0 {
|
if s == s2 {
|
||||||
return false
|
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.
|
// IsRRset checks if a set of RRs is a valid RRset as defined by RFC 2181.
|
||||||
|
@ -244,12 +313,19 @@ func ReverseAddr(addr string) (arpa string, err error) {
|
||||||
if ip == nil {
|
if ip == nil {
|
||||||
return "", &Error{err: "unrecognized address: " + addr}
|
return "", &Error{err: "unrecognized address: " + addr}
|
||||||
}
|
}
|
||||||
if ip.To4() != nil {
|
if v4 := ip.To4(); v4 != nil {
|
||||||
return strconv.Itoa(int(ip[15])) + "." + strconv.Itoa(int(ip[14])) + "." + strconv.Itoa(int(ip[13])) + "." +
|
buf := make([]byte, 0, net.IPv4len*4+len("in-addr.arpa."))
|
||||||
strconv.Itoa(int(ip[12])) + ".in-addr.arpa.", nil
|
// 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
|
// 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
|
// Add it, in reverse, to the buffer
|
||||||
for i := len(ip) - 1; i >= 0; i-- {
|
for i := len(ip) - 1; i >= 0; i-- {
|
||||||
v := ip[i]
|
v := ip[i]
|
||||||
|
|
71
vendor/github.com/miekg/dns/dns.go
generated
vendored
71
vendor/github.com/miekg/dns/dns.go
generated
vendored
|
@ -34,10 +34,30 @@ type RR interface {
|
||||||
|
|
||||||
// copy returns a copy of the RR
|
// copy returns a copy of the RR
|
||||||
copy() RR
|
copy() RR
|
||||||
// len returns the length (in octets) of the uncompressed RR in wire format.
|
|
||||||
len() int
|
// len returns the length (in octets) of the compressed or uncompressed RR in wire format.
|
||||||
// pack packs an RR into wire format.
|
//
|
||||||
pack([]byte, int, map[string]int, bool) (int, error)
|
// 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, file string) *ParseError
|
||||||
|
|
||||||
|
// isDuplicate returns whether the two RRs are duplicates.
|
||||||
|
isDuplicate(r2 RR) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// RR_Header is the header all DNS resource records share.
|
// RR_Header is the header all DNS resource records share.
|
||||||
|
@ -55,16 +75,6 @@ func (h *RR_Header) Header() *RR_Header { return h }
|
||||||
// Just to implement the RR interface.
|
// Just to implement the RR interface.
|
||||||
func (h *RR_Header) copy() RR { return nil }
|
func (h *RR_Header) copy() RR { return nil }
|
||||||
|
|
||||||
func (h *RR_Header) copyHeader() *RR_Header {
|
|
||||||
r := new(RR_Header)
|
|
||||||
r.Name = h.Name
|
|
||||||
r.Rrtype = h.Rrtype
|
|
||||||
r.Class = h.Class
|
|
||||||
r.Ttl = h.Ttl
|
|
||||||
r.Rdlength = h.Rdlength
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *RR_Header) String() string {
|
func (h *RR_Header) String() string {
|
||||||
var s string
|
var s string
|
||||||
|
|
||||||
|
@ -80,28 +90,45 @@ func (h *RR_Header) String() string {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *RR_Header) len() int {
|
func (h *RR_Header) len(off int, compression map[string]struct{}) int {
|
||||||
l := len(h.Name) + 1
|
l := domainNameLen(h.Name, off, compression, true)
|
||||||
l += 10 // rrtype(2) + class(2) + ttl(4) + rdlength(2)
|
l += 10 // rrtype(2) + class(2) + ttl(4) + rdlength(2)
|
||||||
return l
|
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, file 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.
|
// ToRFC3597 converts a known RR to the unknown RR representation from RFC 3597.
|
||||||
func (rr *RFC3597) ToRFC3597(r RR) error {
|
func (rr *RFC3597) ToRFC3597(r RR) error {
|
||||||
buf := make([]byte, r.len()*2)
|
buf := make([]byte, Len(r)*2)
|
||||||
off, err := PackRR(r, buf, 0, nil, false)
|
headerEnd, off, err := packRR(r, buf, 0, compressionMap{}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
buf = buf[:off]
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*rr = *rfc3597.(*RFC3597)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
88
vendor/github.com/miekg/dns/dnssec.go
generated
vendored
88
vendor/github.com/miekg/dns/dnssec.go
generated
vendored
|
@ -67,12 +67,10 @@ var AlgorithmToString = map[uint8]string{
|
||||||
PRIVATEOID: "PRIVATEOID",
|
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.
|
// AlgorithmToHash is a map of algorithm crypto hash IDs to crypto.Hash's.
|
||||||
var AlgorithmToHash = map[uint8]crypto.Hash{
|
var AlgorithmToHash = map[uint8]crypto.Hash{
|
||||||
RSAMD5: crypto.MD5, // Deprecated in RFC 6725
|
RSAMD5: crypto.MD5, // Deprecated in RFC 6725
|
||||||
|
DSA: crypto.SHA1,
|
||||||
RSASHA1: crypto.SHA1,
|
RSASHA1: crypto.SHA1,
|
||||||
RSASHA1NSEC3SHA1: crypto.SHA1,
|
RSASHA1NSEC3SHA1: crypto.SHA1,
|
||||||
RSASHA256: crypto.SHA256,
|
RSASHA256: crypto.SHA256,
|
||||||
|
@ -101,9 +99,6 @@ var HashToString = map[uint8]string{
|
||||||
SHA512: "SHA512",
|
SHA512: "SHA512",
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringToHash is a map of names to hash IDs.
|
|
||||||
var StringToHash = reverseInt8(HashToString)
|
|
||||||
|
|
||||||
// DNSKEY flag values.
|
// DNSKEY flag values.
|
||||||
const (
|
const (
|
||||||
SEP = 1
|
SEP = 1
|
||||||
|
@ -172,7 +167,7 @@ func (k *DNSKEY) KeyTag() uint16 {
|
||||||
keytag += int(v) << 8
|
keytag += int(v) << 8
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
keytag += (keytag >> 16) & 0xFFFF
|
keytag += keytag >> 16 & 0xFFFF
|
||||||
keytag &= 0xFFFF
|
keytag &= 0xFFFF
|
||||||
}
|
}
|
||||||
return uint16(keytag)
|
return uint16(keytag)
|
||||||
|
@ -239,7 +234,7 @@ func (k *DNSKEY) ToDS(h uint8) *DS {
|
||||||
// ToCDNSKEY converts a DNSKEY record to a CDNSKEY record.
|
// ToCDNSKEY converts a DNSKEY record to a CDNSKEY record.
|
||||||
func (k *DNSKEY) ToCDNSKEY() *CDNSKEY {
|
func (k *DNSKEY) ToCDNSKEY() *CDNSKEY {
|
||||||
c := &CDNSKEY{DNSKEY: *k}
|
c := &CDNSKEY{DNSKEY: *k}
|
||||||
c.Hdr = *k.Hdr.copyHeader()
|
c.Hdr = k.Hdr
|
||||||
c.Hdr.Rrtype = TypeCDNSKEY
|
c.Hdr.Rrtype = TypeCDNSKEY
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
@ -247,7 +242,7 @@ func (k *DNSKEY) ToCDNSKEY() *CDNSKEY {
|
||||||
// ToCDS converts a DS record to a CDS record.
|
// ToCDS converts a DS record to a CDS record.
|
||||||
func (d *DS) ToCDS() *CDS {
|
func (d *DS) ToCDS() *CDS {
|
||||||
c := &CDS{DS: *d}
|
c := &CDS{DS: *d}
|
||||||
c.Hdr = *d.Hdr.copyHeader()
|
c.Hdr = d.Hdr
|
||||||
c.Hdr.Rrtype = TypeCDS
|
c.Hdr.Rrtype = TypeCDS
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
@ -267,16 +262,17 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
|
||||||
return ErrKey
|
return ErrKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h0 := rrset[0].Header()
|
||||||
rr.Hdr.Rrtype = TypeRRSIG
|
rr.Hdr.Rrtype = TypeRRSIG
|
||||||
rr.Hdr.Name = rrset[0].Header().Name
|
rr.Hdr.Name = h0.Name
|
||||||
rr.Hdr.Class = rrset[0].Header().Class
|
rr.Hdr.Class = h0.Class
|
||||||
if rr.OrigTtl == 0 { // If set don't override
|
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.TypeCovered = h0.Rrtype
|
||||||
rr.Labels = uint8(CountLabel(rrset[0].Header().Name))
|
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
|
rr.Labels-- // wildcard, remove from label count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,7 +396,7 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
|
||||||
if rr.Algorithm != k.Algorithm {
|
if rr.Algorithm != k.Algorithm {
|
||||||
return ErrKey
|
return ErrKey
|
||||||
}
|
}
|
||||||
if strings.ToLower(rr.SignerName) != strings.ToLower(k.Hdr.Name) {
|
if !strings.EqualFold(rr.SignerName, k.Hdr.Name) {
|
||||||
return ErrKey
|
return ErrKey
|
||||||
}
|
}
|
||||||
if k.Protocol != 3 {
|
if k.Protocol != 3 {
|
||||||
|
@ -410,10 +406,7 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
|
||||||
// IsRRset checked that we have at least one RR and that the RRs in
|
// 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
|
// the set have consistent type, class, and name. Also check that type and
|
||||||
// class matches the RRSIG record.
|
// class matches the RRSIG record.
|
||||||
if rrset[0].Header().Class != rr.Hdr.Class {
|
if h0 := rrset[0].Header(); h0.Class != rr.Hdr.Class || h0.Rrtype != rr.TypeCovered {
|
||||||
return ErrRRset
|
|
||||||
}
|
|
||||||
if rrset[0].Header().Rrtype != rr.TypeCovered {
|
|
||||||
return ErrRRset
|
return ErrRRset
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -511,8 +504,8 @@ func (rr *RRSIG) ValidityPeriod(t time.Time) bool {
|
||||||
}
|
}
|
||||||
modi := (int64(rr.Inception) - utc) / year68
|
modi := (int64(rr.Inception) - utc) / year68
|
||||||
mode := (int64(rr.Expiration) - utc) / year68
|
mode := (int64(rr.Expiration) - utc) / year68
|
||||||
ti := int64(rr.Inception) + (modi * year68)
|
ti := int64(rr.Inception) + modi*year68
|
||||||
te := int64(rr.Expiration) + (mode * year68)
|
te := int64(rr.Expiration) + mode*year68
|
||||||
return ti <= utc && utc <= te
|
return ti <= utc && utc <= te
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -532,6 +525,11 @@ func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(keybuf) < 1+1+64 {
|
||||||
|
// Exponent must be at least 1 byte and modulus at least 64
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// RFC 2537/3110, section 2. RSA Public KEY Resource Records
|
// RFC 2537/3110, section 2. RSA Public KEY Resource Records
|
||||||
// Length is in the 0th byte, unless its zero, then it
|
// Length is in the 0th byte, unless its zero, then it
|
||||||
// it in bytes 1 and 2 and its a 16 bit number
|
// it in bytes 1 and 2 and its a 16 bit number
|
||||||
|
@ -541,25 +539,36 @@ func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey {
|
||||||
explen = uint16(keybuf[1])<<8 | uint16(keybuf[2])
|
explen = uint16(keybuf[1])<<8 | uint16(keybuf[2])
|
||||||
keyoff = 3
|
keyoff = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if explen > 4 || explen == 0 || keybuf[keyoff] == 0 {
|
||||||
|
// Exponent larger than supported by the crypto package,
|
||||||
|
// empty, or contains prohibited leading zero.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
modoff := keyoff + int(explen)
|
||||||
|
modlen := len(keybuf) - modoff
|
||||||
|
if modlen < 64 || modlen > 512 || keybuf[modoff] == 0 {
|
||||||
|
// Modulus is too small, large, or contains prohibited leading zero.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
pubkey := new(rsa.PublicKey)
|
pubkey := new(rsa.PublicKey)
|
||||||
|
|
||||||
pubkey.N = big.NewInt(0)
|
var expo uint64
|
||||||
shift := uint64((explen - 1) * 8)
|
for i := 0; i < int(explen); i++ {
|
||||||
expo := uint64(0)
|
expo <<= 8
|
||||||
for i := int(explen - 1); i > 0; i-- {
|
expo |= uint64(keybuf[keyoff+i])
|
||||||
expo += uint64(keybuf[keyoff+i]) << shift
|
|
||||||
shift -= 8
|
|
||||||
}
|
}
|
||||||
// Remainder
|
if expo > 1<<31-1 {
|
||||||
expo += uint64(keybuf[keyoff])
|
// Larger exponent than supported by the crypto package.
|
||||||
if expo > (2<<31)+1 {
|
|
||||||
// Larger expo than supported.
|
|
||||||
// println("dns: F5 primes (or larger) are not supported")
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
pubkey.E = int(expo)
|
pubkey.E = int(expo)
|
||||||
|
|
||||||
pubkey.N.SetBytes(keybuf[keyoff+int(explen):])
|
pubkey.N = big.NewInt(0)
|
||||||
|
pubkey.N.SetBytes(keybuf[modoff:])
|
||||||
|
|
||||||
return pubkey
|
return pubkey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -641,15 +650,16 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
|
||||||
wires := make(wireSlice, len(rrset))
|
wires := make(wireSlice, len(rrset))
|
||||||
for i, r := range rrset {
|
for i, r := range rrset {
|
||||||
r1 := r.copy()
|
r1 := r.copy()
|
||||||
r1.Header().Ttl = s.OrigTtl
|
h := r1.Header()
|
||||||
labels := SplitDomainName(r1.Header().Name)
|
h.Ttl = s.OrigTtl
|
||||||
|
labels := SplitDomainName(h.Name)
|
||||||
// 6.2. Canonical RR Form. (4) - wildcards
|
// 6.2. Canonical RR Form. (4) - wildcards
|
||||||
if len(labels) > int(s.Labels) {
|
if len(labels) > int(s.Labels) {
|
||||||
// Wildcard
|
// 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
|
// RFC 4034: 6.2. Canonical RR Form. (2) - domain name to lowercase
|
||||||
r1.Header().Name = strings.ToLower(r1.Header().Name)
|
h.Name = strings.ToLower(h.Name)
|
||||||
// 6.2. Canonical RR Form. (3) - domain rdata to lowercase.
|
// 6.2. Canonical RR Form. (3) - domain rdata to lowercase.
|
||||||
// NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
|
// NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
|
||||||
// HINFO, MINFO, MX, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX,
|
// HINFO, MINFO, MX, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX,
|
||||||
|
@ -707,7 +717,7 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
|
||||||
x.Target = strings.ToLower(x.Target)
|
x.Target = strings.ToLower(x.Target)
|
||||||
}
|
}
|
||||||
// 6.2. Canonical RR Form. (5) - origTTL
|
// 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)
|
off, err1 := PackRR(r1, wire, 0, nil, false)
|
||||||
if err1 != nil {
|
if err1 != nil {
|
||||||
return nil, err1
|
return nil, err1
|
||||||
|
|
185
vendor/github.com/miekg/dns/dnssec_keyscan.go
generated
vendored
185
vendor/github.com/miekg/dns/dnssec_keyscan.go
generated
vendored
|
@ -1,7 +1,7 @@
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bufio"
|
||||||
"crypto"
|
"crypto"
|
||||||
"crypto/dsa"
|
"crypto/dsa"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
|
@ -181,22 +181,10 @@ func readPrivateKeyED25519(m map[string]string) (ed25519.PrivateKey, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if len(p1) != 32 {
|
if len(p1) != ed25519.SeedSize {
|
||||||
return nil, ErrPrivKey
|
return nil, ErrPrivKey
|
||||||
}
|
}
|
||||||
// RFC 8080 and Golang's x/crypto/ed25519 differ as to how the
|
p = ed25519.NewKeyFromSeed(p1)
|
||||||
// private keys are represented. RFC 8080 specifies that private
|
|
||||||
// keys be stored solely as the seed value (p1 above) while the
|
|
||||||
// ed25519 package represents them as the seed value concatenated
|
|
||||||
// to the public key, which is derived from the seed value.
|
|
||||||
//
|
|
||||||
// ed25519.GenerateKey reads exactly 32 bytes from the passed in
|
|
||||||
// io.Reader and uses them as the seed. It also derives the
|
|
||||||
// public key and produces a compatible private key.
|
|
||||||
_, p, err = ed25519.GenerateKey(bytes.NewReader(p1))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
case "created", "publish", "activate":
|
case "created", "publish", "activate":
|
||||||
/* not used in Go (yet) */
|
/* not used in Go (yet) */
|
||||||
}
|
}
|
||||||
|
@ -207,23 +195,12 @@ func readPrivateKeyED25519(m map[string]string) (ed25519.PrivateKey, error) {
|
||||||
// parseKey reads a private key from r. It returns a map[string]string,
|
// parseKey reads a private key from r. It returns a map[string]string,
|
||||||
// with the key-value pairs, or an error when the file is not correct.
|
// with the key-value pairs, or an error when the file is not correct.
|
||||||
func parseKey(r io.Reader, file string) (map[string]string, error) {
|
func parseKey(r io.Reader, file string) (map[string]string, error) {
|
||||||
s, cancel := scanInit(r)
|
|
||||||
m := make(map[string]string)
|
m := make(map[string]string)
|
||||||
c := make(chan lex)
|
var k string
|
||||||
k := ""
|
|
||||||
defer func() {
|
c := newKLexer(r)
|
||||||
cancel()
|
|
||||||
// zlexer can send up to two tokens, the next one and possibly 1 remainders.
|
for l, ok := c.Next(); ok; l, ok = c.Next() {
|
||||||
// Do a non-blocking read.
|
|
||||||
_, ok := <-c
|
|
||||||
_, ok = <-c
|
|
||||||
if !ok {
|
|
||||||
// too bad
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
// Start the lexer
|
|
||||||
go klexer(s, c)
|
|
||||||
for l := range c {
|
|
||||||
// It should alternate
|
// It should alternate
|
||||||
switch l.value {
|
switch l.value {
|
||||||
case zKey:
|
case zKey:
|
||||||
|
@ -232,41 +209,111 @@ func parseKey(r io.Reader, file string) (map[string]string, error) {
|
||||||
if k == "" {
|
if k == "" {
|
||||||
return nil, &ParseError{file, "no private key seen", l}
|
return nil, &ParseError{file, "no private key seen", l}
|
||||||
}
|
}
|
||||||
//println("Setting", strings.ToLower(k), "to", l.token, "b")
|
|
||||||
m[strings.ToLower(k)] = l.token
|
m[strings.ToLower(k)] = l.token
|
||||||
k = ""
|
k = ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Surface any read errors from r.
|
||||||
|
if err := c.Err(); err != nil {
|
||||||
|
return nil, &ParseError{file: file, err: err.Error()}
|
||||||
|
}
|
||||||
|
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// klexer scans the sourcefile and returns tokens on the channel c.
|
type klexer struct {
|
||||||
func klexer(s *scan, c chan lex) {
|
br io.ByteReader
|
||||||
var l lex
|
|
||||||
str := "" // Hold the current read text
|
readErr error
|
||||||
commt := false
|
|
||||||
key := true
|
line int
|
||||||
x, err := s.tokenText()
|
column int
|
||||||
defer close(c)
|
|
||||||
for err == nil {
|
key bool
|
||||||
l.column = s.position.Column
|
|
||||||
l.line = s.position.Line
|
eol bool // end-of-line
|
||||||
|
}
|
||||||
|
|
||||||
|
func newKLexer(r io.Reader) *klexer {
|
||||||
|
br, ok := r.(io.ByteReader)
|
||||||
|
if !ok {
|
||||||
|
br = bufio.NewReaderSize(r, 1024)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &klexer{
|
||||||
|
br: br,
|
||||||
|
|
||||||
|
line: 1,
|
||||||
|
|
||||||
|
key: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (kl *klexer) Err() error {
|
||||||
|
if kl.readErr == io.EOF {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return kl.readErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// readByte returns the next byte from the input
|
||||||
|
func (kl *klexer) readByte() (byte, bool) {
|
||||||
|
if kl.readErr != nil {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := kl.br.ReadByte()
|
||||||
|
if err != nil {
|
||||||
|
kl.readErr = err
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// delay the newline handling until the next token is delivered,
|
||||||
|
// fixes off-by-one errors when reporting a parse error.
|
||||||
|
if kl.eol {
|
||||||
|
kl.line++
|
||||||
|
kl.column = 0
|
||||||
|
kl.eol = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if c == '\n' {
|
||||||
|
kl.eol = true
|
||||||
|
} else {
|
||||||
|
kl.column++
|
||||||
|
}
|
||||||
|
|
||||||
|
return c, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (kl *klexer) Next() (lex, bool) {
|
||||||
|
var (
|
||||||
|
l lex
|
||||||
|
|
||||||
|
str strings.Builder
|
||||||
|
|
||||||
|
commt bool
|
||||||
|
)
|
||||||
|
|
||||||
|
for x, ok := kl.readByte(); ok; x, ok = kl.readByte() {
|
||||||
|
l.line, l.column = kl.line, kl.column
|
||||||
|
|
||||||
switch x {
|
switch x {
|
||||||
case ':':
|
case ':':
|
||||||
if commt {
|
if commt || !kl.key {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
l.token = str
|
|
||||||
if key {
|
kl.key = false
|
||||||
l.value = zKey
|
|
||||||
c <- l
|
// Next token is a space, eat it
|
||||||
// Next token is a space, eat it
|
kl.readByte()
|
||||||
s.tokenText()
|
|
||||||
key = false
|
l.value = zKey
|
||||||
str = ""
|
l.token = str.String()
|
||||||
} else {
|
return l, true
|
||||||
l.value = zValue
|
|
||||||
}
|
|
||||||
case ';':
|
case ';':
|
||||||
commt = true
|
commt = true
|
||||||
case '\n':
|
case '\n':
|
||||||
|
@ -274,24 +321,32 @@ func klexer(s *scan, c chan lex) {
|
||||||
// Reset a comment
|
// Reset a comment
|
||||||
commt = false
|
commt = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kl.key = true
|
||||||
|
|
||||||
l.value = zValue
|
l.value = zValue
|
||||||
l.token = str
|
l.token = str.String()
|
||||||
c <- l
|
return l, true
|
||||||
str = ""
|
|
||||||
commt = false
|
|
||||||
key = true
|
|
||||||
default:
|
default:
|
||||||
if commt {
|
if commt {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
str += string(x)
|
|
||||||
|
str.WriteByte(x)
|
||||||
}
|
}
|
||||||
x, err = s.tokenText()
|
|
||||||
}
|
}
|
||||||
if len(str) > 0 {
|
|
||||||
|
if kl.readErr != nil && kl.readErr != io.EOF {
|
||||||
|
// Don't return any tokens after a read error occurs.
|
||||||
|
return lex{value: zEOF}, false
|
||||||
|
}
|
||||||
|
|
||||||
|
if str.Len() > 0 {
|
||||||
// Send remainder
|
// Send remainder
|
||||||
l.token = str
|
|
||||||
l.value = zValue
|
l.value = zValue
|
||||||
c <- l
|
l.token = str.String()
|
||||||
|
return l, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return lex{value: zEOF}, false
|
||||||
}
|
}
|
||||||
|
|
2
vendor/github.com/miekg/dns/dnssec_privkey.go
generated
vendored
2
vendor/github.com/miekg/dns/dnssec_privkey.go
generated
vendored
|
@ -82,7 +82,7 @@ func (r *DNSKEY) PrivateKeyString(p crypto.PrivateKey) string {
|
||||||
"Public_value(y): " + pub + "\n"
|
"Public_value(y): " + pub + "\n"
|
||||||
|
|
||||||
case ed25519.PrivateKey:
|
case ed25519.PrivateKey:
|
||||||
private := toBase64(p[:32])
|
private := toBase64(p.Seed())
|
||||||
return format +
|
return format +
|
||||||
"Algorithm: " + algorithm + "\n" +
|
"Algorithm: " + algorithm + "\n" +
|
||||||
"PrivateKey: " + private + "\n"
|
"PrivateKey: " + private + "\n"
|
||||||
|
|
111
vendor/github.com/miekg/dns/doc.go
generated
vendored
111
vendor/github.com/miekg/dns/doc.go
generated
vendored
|
@ -1,20 +1,20 @@
|
||||||
/*
|
/*
|
||||||
Package dns implements a full featured interface to the Domain Name System.
|
Package dns implements a full featured interface to the Domain Name System.
|
||||||
Server- and client-side programming is supported.
|
Both server- and client-side programming is supported. The package allows
|
||||||
The package allows complete control over what is sent out to the DNS. The package
|
complete control over what is sent out to the DNS. The API follows the
|
||||||
API follows the less-is-more principle, by presenting a small, clean interface.
|
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.
|
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.
|
names in a message will result in a packing failure.
|
||||||
|
|
||||||
Resource records are native types. They are not stored in wire format.
|
Resource records are native types. They are not stored in wire format. Basic
|
||||||
Basic usage pattern for creating a new resource record:
|
usage pattern for creating a new resource record:
|
||||||
|
|
||||||
r := new(dns.MX)
|
r := new(dns.MX)
|
||||||
r.Hdr = dns.RR_Header{Name: "miek.nl.", Rrtype: dns.TypeMX,
|
r.Hdr = dns.RR_Header{Name: "miek.nl.", Rrtype: dns.TypeMX, Class: dns.ClassINET, Ttl: 3600}
|
||||||
Class: dns.ClassINET, Ttl: 3600}
|
|
||||||
r.Preference = 10
|
r.Preference = 10
|
||||||
r.Mx = "mx.miek.nl."
|
r.Mx = "mx.miek.nl."
|
||||||
|
|
||||||
|
@ -30,8 +30,8 @@ Or even:
|
||||||
|
|
||||||
mx, err := dns.NewRR("$ORIGIN nl.\nmiek 1H IN MX 10 mx.miek")
|
mx, err := dns.NewRR("$ORIGIN nl.\nmiek 1H IN MX 10 mx.miek")
|
||||||
|
|
||||||
In the DNS messages are exchanged, these messages contain resource
|
In the DNS messages are exchanged, these messages contain resource records
|
||||||
records (sets). Use pattern for creating a message:
|
(sets). Use pattern for creating a message:
|
||||||
|
|
||||||
m := new(dns.Msg)
|
m := new(dns.Msg)
|
||||||
m.SetQuestion("miek.nl.", dns.TypeMX)
|
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)
|
m.SetQuestion(dns.Fqdn("miek.nl"), dns.TypeMX)
|
||||||
|
|
||||||
The message m is now a message with the question section set to ask
|
The message m is now a message with the question section set to ask the MX
|
||||||
the MX records for the miek.nl. zone.
|
records for the miek.nl. zone.
|
||||||
|
|
||||||
The following is slightly more verbose, but more flexible:
|
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 = make([]dns.Question, 1)
|
||||||
m1.Question[0] = dns.Question{"miek.nl.", dns.TypeMX, dns.ClassINET}
|
m1.Question[0] = dns.Question{"miek.nl.", dns.TypeMX, dns.ClassINET}
|
||||||
|
|
||||||
After creating a message it can be sent.
|
After creating a message it can be sent. Basic use pattern for synchronous
|
||||||
Basic use pattern for synchronous querying the DNS at a
|
querying the DNS at a server configured on 127.0.0.1 and port 53:
|
||||||
server configured on 127.0.0.1 and port 53:
|
|
||||||
|
|
||||||
c := new(dns.Client)
|
c := new(dns.Client)
|
||||||
in, rtt, err := c.Exchange(m1, "127.0.0.1:53")
|
in, rtt, err := c.Exchange(m1, "127.0.0.1:53")
|
||||||
|
@ -73,11 +72,11 @@ and port to use for the connection:
|
||||||
Port: 12345,
|
Port: 12345,
|
||||||
Zone: "",
|
Zone: "",
|
||||||
}
|
}
|
||||||
d := net.Dialer{
|
c.Dialer := &net.Dialer{
|
||||||
Timeout: 200 * time.Millisecond,
|
Timeout: 200 * time.Millisecond,
|
||||||
LocalAddr: &laddr,
|
LocalAddr: &laddr,
|
||||||
}
|
}
|
||||||
in, rtt, err := c.ExchangeWithDialer(&d, m1, "8.8.8.8:53")
|
in, rtt, err := c.Exchange(m1, "8.8.8.8:53")
|
||||||
|
|
||||||
If these "advanced" features are not needed, a simple UDP query can be sent,
|
If these "advanced" features are not needed, a simple UDP query can be sent,
|
||||||
with:
|
with:
|
||||||
|
@ -99,25 +98,24 @@ the Answer section:
|
||||||
|
|
||||||
Domain Name and TXT Character String Representations
|
Domain Name and TXT Character String Representations
|
||||||
|
|
||||||
Both domain names and TXT character strings are converted to presentation
|
Both domain names and TXT character strings are converted to presentation form
|
||||||
form both when unpacked and when converted to strings.
|
both when unpacked and when converted to strings.
|
||||||
|
|
||||||
For TXT character strings, tabs, carriage returns and line feeds will be
|
For TXT character strings, tabs, carriage returns and line feeds will be
|
||||||
converted to \t, \r and \n respectively. Back slashes and quotations marks
|
converted to \t, \r and \n respectively. Back slashes and quotations marks will
|
||||||
will be escaped. Bytes below 32 and above 127 will be converted to \DDD
|
be escaped. Bytes below 32 and above 127 will be converted to \DDD form.
|
||||||
form.
|
|
||||||
|
|
||||||
For domain names, in addition to the above rules brackets, periods,
|
For domain names, in addition to the above rules brackets, periods, spaces,
|
||||||
spaces, semicolons and the at symbol are escaped.
|
semicolons and the at symbol are escaped.
|
||||||
|
|
||||||
DNSSEC
|
DNSSEC
|
||||||
|
|
||||||
DNSSEC (DNS Security Extension) adds a layer of security to the DNS. It
|
DNSSEC (DNS Security Extension) adds a layer of security to the DNS. It uses
|
||||||
uses public key cryptography to sign resource records. The
|
public key cryptography to sign resource records. The public keys are stored in
|
||||||
public keys are stored in DNSKEY records and the signatures in RRSIG records.
|
DNSKEY records and the signatures in RRSIG records.
|
||||||
|
|
||||||
Requesting DNSSEC information for a zone is done by adding the DO (DNSSEC OK) bit
|
Requesting DNSSEC information for a zone is done by adding the DO (DNSSEC OK)
|
||||||
to a request.
|
bit to a request.
|
||||||
|
|
||||||
m := new(dns.Msg)
|
m := new(dns.Msg)
|
||||||
m.SetEdns0(4096, true)
|
m.SetEdns0(4096, true)
|
||||||
|
@ -126,9 +124,9 @@ Signature generation, signature verification and key generation are all supporte
|
||||||
|
|
||||||
DYNAMIC UPDATES
|
DYNAMIC UPDATES
|
||||||
|
|
||||||
Dynamic updates reuses the DNS message format, but renames three of
|
Dynamic updates reuses the DNS message format, but renames three of the
|
||||||
the sections. Question is Zone, Answer is Prerequisite, Authority is
|
sections. Question is Zone, Answer is Prerequisite, Authority is Update, only
|
||||||
Update, only the Additional is not renamed. See RFC 2136 for the gory details.
|
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
|
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
|
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
|
NONE rrset empty RRset does not exist dns.RRsetNotUsed
|
||||||
zone rrset rr RRset exists (value dep) dns.Used
|
zone rrset rr RRset exists (value dep) dns.Used
|
||||||
|
|
||||||
The prerequisite section can also be left empty.
|
The prerequisite section can also be left empty. If you have decided on the
|
||||||
If you have decided on the prerequisites you can tell what RRs should
|
prerequisites you can tell what RRs should be added or deleted. The next table
|
||||||
be added or deleted. The next table shows the options you have and
|
shows the options you have and what functions to call.
|
||||||
what functions to call.
|
|
||||||
|
|
||||||
3.4.2.6 - Table Of Metavalues Used In Update Section
|
3.4.2.6 - Table Of Metavalues Used In Update Section
|
||||||
|
|
||||||
|
@ -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 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
|
When requesting an zone transfer (almost all TSIG usage is when requesting zone
|
||||||
TSIG, this is the basic use pattern. In this example we request an AXFR for
|
transfers), with TSIG, this is the basic use pattern. In this example we
|
||||||
miek.nl. with TSIG key named "axfr." and secret "so6ZGir4GPAqINNh9U5c3A=="
|
request an AXFR for miek.nl. with TSIG key named "axfr." and secret
|
||||||
and using the server 176.58.119.54:
|
"so6ZGir4GPAqINNh9U5c3A==" and using the server 176.58.119.54:
|
||||||
|
|
||||||
t := new(dns.Transfer)
|
t := new(dns.Transfer)
|
||||||
m := new(dns.Msg)
|
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")
|
c, err := t.In(m, "176.58.119.54:53")
|
||||||
for r := range c { ... }
|
for r := range c { ... }
|
||||||
|
|
||||||
You can now read the records from the transfer as they come in. Each envelope is checked with TSIG.
|
You can now read the records from the transfer as they come in. Each envelope
|
||||||
If something is not correct an error is returned.
|
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.
|
Basic use pattern validating and replying to a message that has TSIG set.
|
||||||
|
|
||||||
|
@ -220,29 +217,30 @@ Basic use pattern validating and replying to a message that has TSIG set.
|
||||||
|
|
||||||
PRIVATE RRS
|
PRIVATE RRS
|
||||||
|
|
||||||
RFC 6895 sets aside a range of type codes for private use. This range
|
RFC 6895 sets aside a range of type codes for private use. This range is 65,280
|
||||||
is 65,280 - 65,534 (0xFF00 - 0xFFFE). When experimenting with new Resource Records these
|
- 65,534 (0xFF00 - 0xFFFE). When experimenting with new Resource Records these
|
||||||
can be used, before requesting an official type code from IANA.
|
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.
|
information.
|
||||||
|
|
||||||
EDNS0
|
EDNS0
|
||||||
|
|
||||||
EDNS0 is an extension mechanism for the DNS defined in RFC 2671 and updated
|
EDNS0 is an extension mechanism for the DNS defined in RFC 2671 and updated by
|
||||||
by RFC 6891. It defines an new RR type, the OPT RR, which is then completely
|
RFC 6891. It defines an new RR type, the OPT RR, which is then completely
|
||||||
abused.
|
abused.
|
||||||
|
|
||||||
Basic use pattern for creating an (empty) OPT RR:
|
Basic use pattern for creating an (empty) OPT RR:
|
||||||
|
|
||||||
o := new(dns.OPT)
|
o := new(dns.OPT)
|
||||||
o.Hdr.Name = "." // MUST be the root zone, per definition.
|
o.Hdr.Name = "." // MUST be the root zone, per definition.
|
||||||
o.Hdr.Rrtype = dns.TypeOPT
|
o.Hdr.Rrtype = dns.TypeOPT
|
||||||
|
|
||||||
The rdata of an OPT RR consists out of a slice of EDNS0 (RFC 6891)
|
The rdata of an OPT RR consists out of a slice of EDNS0 (RFC 6891) interfaces.
|
||||||
interfaces. Currently only a few have been standardized: EDNS0_NSID
|
Currently only a few have been standardized: EDNS0_NSID (RFC 5001) and
|
||||||
(RFC 5001) and EDNS0_SUBNET (draft-vandergaast-edns-client-subnet-02). Note
|
EDNS0_SUBNET (draft-vandergaast-edns-client-subnet-02). Note that these options
|
||||||
that these options may be combined in an OPT RR.
|
may be combined in an OPT RR. Basic use pattern for a server to check if (and
|
||||||
Basic use pattern for a server to check if (and which) options are set:
|
which) options are set:
|
||||||
|
|
||||||
// o is a dns.OPT
|
// o is a dns.OPT
|
||||||
for _, s := range o.Option {
|
for _, s := range o.Option {
|
||||||
|
@ -262,10 +260,9 @@ From RFC 2931:
|
||||||
... protection for glue records, DNS requests, protection for message headers
|
... protection for glue records, DNS requests, protection for message headers
|
||||||
on requests and responses, and protection of the overall integrity of a response.
|
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
|
It works like TSIG, except that SIG(0) uses public key cryptography, instead of
|
||||||
secret approach in TSIG.
|
the shared secret approach in TSIG. Supported algorithms: DSA, ECDSAP256SHA256,
|
||||||
Supported algorithms: DSA, ECDSAP256SHA256, ECDSAP384SHA384, RSASHA1, RSASHA256 and
|
ECDSAP384SHA384, RSASHA1, RSASHA256 and RSASHA512.
|
||||||
RSASHA512.
|
|
||||||
|
|
||||||
Signing subsequent messages in multi-message sessions is not implemented.
|
Signing subsequent messages in multi-message sessions is not implemented.
|
||||||
*/
|
*/
|
||||||
|
|
38
vendor/github.com/miekg/dns/duplicate.go
generated
vendored
Normal file
38
vendor/github.com/miekg/dns/duplicate.go
generated
vendored
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
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.
|
||||||
|
func IsDuplicate(r1, r2 RR) bool {
|
||||||
|
// Check whether the record header is identical.
|
||||||
|
if !r1.Header().isDuplicate(r2.Header()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.Name, r2.Name) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// ignore TTL
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// isDulicateName checks if the domain names s1 and s2 are equal.
|
||||||
|
func isDulicateName(s1, s2 string) bool { return equal(s1, s2) }
|
144
vendor/github.com/miekg/dns/duplicate_generate.go
generated
vendored
Normal file
144
vendor/github.com/miekg/dns/duplicate_generate.go
generated
vendored
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
//+build ignore
|
||||||
|
|
||||||
|
// types_generate.go is meant to run with go generate. It will use
|
||||||
|
// go/{importer,types} to track down all the RR struct types. Then for each type
|
||||||
|
// it will generate conversion tables (TypeToRR and TypeToString) and banal
|
||||||
|
// methods (len, Header, copy) based on the struct tags. The generated source is
|
||||||
|
// written to ztypes.go, and is meant to be checked into git.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"go/format"
|
||||||
|
"go/importer"
|
||||||
|
"go/types"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
var packageHdr = `
|
||||||
|
// Code generated by "go run duplicate_generate.go"; DO NOT EDIT.
|
||||||
|
|
||||||
|
package dns
|
||||||
|
|
||||||
|
`
|
||||||
|
|
||||||
|
func getTypeStruct(t types.Type, scope *types.Scope) (*types.Struct, bool) {
|
||||||
|
st, ok := t.Underlying().(*types.Struct)
|
||||||
|
if !ok {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
if st.Field(0).Type() == scope.Lookup("RR_Header").Type() {
|
||||||
|
return st, false
|
||||||
|
}
|
||||||
|
if st.Field(0).Anonymous() {
|
||||||
|
st, _ := getTypeStruct(st.Field(0).Type(), scope)
|
||||||
|
return st, true
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Import and type-check the package
|
||||||
|
pkg, err := importer.Default().Import("github.com/miekg/dns")
|
||||||
|
fatalIfErr(err)
|
||||||
|
scope := pkg.Scope()
|
||||||
|
|
||||||
|
// Collect actual types (*X)
|
||||||
|
var namedTypes []string
|
||||||
|
for _, name := range scope.Names() {
|
||||||
|
o := scope.Lookup(name)
|
||||||
|
if o == nil || !o.Exported() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if st, _ := getTypeStruct(o.Type(), scope); st == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if name == "PrivateRR" || name == "OPT" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
namedTypes = append(namedTypes, o.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
b := &bytes.Buffer{}
|
||||||
|
b.WriteString(packageHdr)
|
||||||
|
|
||||||
|
// Generate the duplicate check for each type.
|
||||||
|
fmt.Fprint(b, "// isDuplicate() functions\n\n")
|
||||||
|
for _, name := range namedTypes {
|
||||||
|
|
||||||
|
o := scope.Lookup(name)
|
||||||
|
st, isEmbedded := getTypeStruct(o.Type(), scope)
|
||||||
|
if isEmbedded {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Fprintf(b, "func (r1 *%s) isDuplicate(_r2 RR) bool {\n", name)
|
||||||
|
fmt.Fprintf(b, "r2, ok := _r2.(*%s)\n", name)
|
||||||
|
fmt.Fprint(b, "if !ok { return false }\n")
|
||||||
|
fmt.Fprint(b, "_ = r2\n")
|
||||||
|
for i := 1; i < st.NumFields(); i++ {
|
||||||
|
field := st.Field(i).Name()
|
||||||
|
o2 := func(s string) { fmt.Fprintf(b, s+"\n", field, field) }
|
||||||
|
o3 := func(s string) { fmt.Fprintf(b, s+"\n", field, field, field) }
|
||||||
|
|
||||||
|
// For some reason, a and aaaa don't pop up as *types.Slice here (mostly like because the are
|
||||||
|
// *indirectly* defined as a slice in the net package).
|
||||||
|
if _, ok := st.Field(i).Type().(*types.Slice); ok {
|
||||||
|
o2("if len(r1.%s) != len(r2.%s) {\nreturn false\n}")
|
||||||
|
|
||||||
|
if st.Tag(i) == `dns:"cdomain-name"` || st.Tag(i) == `dns:"domain-name"` {
|
||||||
|
o3(`for i := 0; i < len(r1.%s); i++ {
|
||||||
|
if !isDulicateName(r1.%s[i], r2.%s[i]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}`)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
o3(`for i := 0; i < len(r1.%s); i++ {
|
||||||
|
if r1.%s[i] != r2.%s[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}`)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
switch st.Tag(i) {
|
||||||
|
case `dns:"-"`:
|
||||||
|
// ignored
|
||||||
|
case `dns:"a"`, `dns:"aaaa"`:
|
||||||
|
o2("if !r1.%s.Equal(r2.%s) {\nreturn false\n}")
|
||||||
|
case `dns:"cdomain-name"`, `dns:"domain-name"`:
|
||||||
|
o2("if !isDulicateName(r1.%s, r2.%s) {\nreturn false\n}")
|
||||||
|
default:
|
||||||
|
o2("if r1.%s != r2.%s {\nreturn false\n}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Fprintf(b, "return true\n}\n\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// gofmt
|
||||||
|
res, err := format.Source(b.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
b.WriteTo(os.Stderr)
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// write result
|
||||||
|
f, err := os.Create("zduplicate.go")
|
||||||
|
fatalIfErr(err)
|
||||||
|
defer f.Close()
|
||||||
|
f.Write(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func fatalIfErr(err error) {
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
82
vendor/github.com/miekg/dns/edns.go
generated
vendored
82
vendor/github.com/miekg/dns/edns.go
generated
vendored
|
@ -78,8 +78,8 @@ func (rr *OPT) String() string {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rr *OPT) len() int {
|
func (rr *OPT) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
for i := 0; i < len(rr.Option); i++ {
|
for i := 0; i < len(rr.Option); i++ {
|
||||||
l += 4 // Account for 2-byte option code and 2-byte option length.
|
l += 4 // Account for 2-byte option code and 2-byte option length.
|
||||||
lo, _ := rr.Option[i].pack()
|
lo, _ := rr.Option[i].pack()
|
||||||
|
@ -88,26 +88,34 @@ func (rr *OPT) len() int {
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rr *OPT) parse(c *zlexer, origin, file 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?
|
// return the old value -> delete SetVersion?
|
||||||
|
|
||||||
// Version returns the EDNS version used. Only zero is defined.
|
// Version returns the EDNS version used. Only zero is defined.
|
||||||
func (rr *OPT) Version() uint8 {
|
func (rr *OPT) Version() uint8 {
|
||||||
return uint8((rr.Hdr.Ttl & 0x00FF0000) >> 16)
|
return uint8(rr.Hdr.Ttl & 0x00FF0000 >> 16)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetVersion sets the version of EDNS. This is usually zero.
|
// SetVersion sets the version of EDNS. This is usually zero.
|
||||||
func (rr *OPT) SetVersion(v uint8) {
|
func (rr *OPT) SetVersion(v uint8) {
|
||||||
rr.Hdr.Ttl = rr.Hdr.Ttl&0xFF00FFFF | (uint32(v) << 16)
|
rr.Hdr.Ttl = rr.Hdr.Ttl&0xFF00FFFF | uint32(v)<<16
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExtendedRcode returns the EDNS extended RCODE field (the upper 8 bits of the TTL).
|
// ExtendedRcode returns the EDNS extended RCODE field (the upper 8 bits of the TTL).
|
||||||
func (rr *OPT) ExtendedRcode() int {
|
func (rr *OPT) ExtendedRcode() int {
|
||||||
return int((rr.Hdr.Ttl & 0xFF000000) >> 24)
|
return int(rr.Hdr.Ttl&0xFF000000>>24) << 4
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetExtendedRcode sets the EDNS extended RCODE field.
|
// SetExtendedRcode sets the EDNS extended RCODE field.
|
||||||
func (rr *OPT) SetExtendedRcode(v uint8) {
|
//
|
||||||
rr.Hdr.Ttl = rr.Hdr.Ttl&0x00FFFFFF | (uint32(v) << 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.
|
// UDPSize returns the UDP buffer size.
|
||||||
|
@ -151,6 +159,8 @@ type EDNS0 interface {
|
||||||
unpack([]byte) error
|
unpack([]byte) error
|
||||||
// String returns the string representation of the option.
|
// String returns the string representation of the option.
|
||||||
String() string
|
String() string
|
||||||
|
// copy returns a deep-copy of the option.
|
||||||
|
copy() EDNS0
|
||||||
}
|
}
|
||||||
|
|
||||||
// EDNS0_NSID option is used to retrieve a nameserver
|
// EDNS0_NSID option is used to retrieve a nameserver
|
||||||
|
@ -181,7 +191,8 @@ func (e *EDNS0_NSID) pack() ([]byte, error) {
|
||||||
// Option implements the EDNS0 interface.
|
// Option implements the EDNS0 interface.
|
||||||
func (e *EDNS0_NSID) Option() uint16 { return EDNS0NSID } // Option returns the option code.
|
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) 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
|
// 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
|
// an idea of where the client lives. See RFC 7871. It can then give back a different
|
||||||
|
@ -271,22 +282,16 @@ func (e *EDNS0_SUBNET) unpack(b []byte) error {
|
||||||
if e.SourceNetmask > net.IPv4len*8 || e.SourceScope > net.IPv4len*8 {
|
if e.SourceNetmask > net.IPv4len*8 || e.SourceScope > net.IPv4len*8 {
|
||||||
return errors.New("dns: bad netmask")
|
return errors.New("dns: bad netmask")
|
||||||
}
|
}
|
||||||
addr := make([]byte, net.IPv4len)
|
addr := make(net.IP, net.IPv4len)
|
||||||
for i := 0; i < net.IPv4len && 4+i < len(b); i++ {
|
copy(addr, b[4:])
|
||||||
addr[i] = b[4+i]
|
e.Address = addr.To16()
|
||||||
}
|
|
||||||
e.Address = net.IPv4(addr[0], addr[1], addr[2], addr[3])
|
|
||||||
case 2:
|
case 2:
|
||||||
if e.SourceNetmask > net.IPv6len*8 || e.SourceScope > net.IPv6len*8 {
|
if e.SourceNetmask > net.IPv6len*8 || e.SourceScope > net.IPv6len*8 {
|
||||||
return errors.New("dns: bad netmask")
|
return errors.New("dns: bad netmask")
|
||||||
}
|
}
|
||||||
addr := make([]byte, net.IPv6len)
|
addr := make(net.IP, net.IPv6len)
|
||||||
for i := 0; i < net.IPv6len && 4+i < len(b); i++ {
|
copy(addr, b[4:])
|
||||||
addr[i] = b[4+i]
|
e.Address = addr
|
||||||
}
|
|
||||||
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]}
|
|
||||||
default:
|
default:
|
||||||
return errors.New("dns: bad address family")
|
return errors.New("dns: bad address family")
|
||||||
}
|
}
|
||||||
|
@ -305,6 +310,16 @@ func (e *EDNS0_SUBNET) String() (s string) {
|
||||||
return
|
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.
|
// The EDNS0_COOKIE option is used to add a DNS Cookie to a message.
|
||||||
//
|
//
|
||||||
// o := new(dns.OPT)
|
// o := new(dns.OPT)
|
||||||
|
@ -340,6 +355,7 @@ func (e *EDNS0_COOKIE) pack() ([]byte, error) {
|
||||||
func (e *EDNS0_COOKIE) Option() uint16 { return EDNS0COOKIE }
|
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) unpack(b []byte) error { e.Cookie = hex.EncodeToString(b); return nil }
|
||||||
func (e *EDNS0_COOKIE) String() string { return e.Cookie }
|
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
|
// 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
|
// an expiration on an update RR. This is helpful for clients that cannot clean
|
||||||
|
@ -361,6 +377,7 @@ type EDNS0_UL struct {
|
||||||
// Option implements the EDNS0 interface.
|
// Option implements the EDNS0 interface.
|
||||||
func (e *EDNS0_UL) Option() uint16 { return EDNS0UL }
|
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 strconv.FormatUint(uint64(e.Lease), 10) }
|
||||||
|
func (e *EDNS0_UL) copy() EDNS0 { return &EDNS0_UL{e.Code, e.Lease} }
|
||||||
|
|
||||||
// Copied: http://golang.org/src/pkg/net/dnsmsg.go
|
// Copied: http://golang.org/src/pkg/net/dnsmsg.go
|
||||||
func (e *EDNS0_UL) pack() ([]byte, error) {
|
func (e *EDNS0_UL) pack() ([]byte, error) {
|
||||||
|
@ -415,10 +432,13 @@ func (e *EDNS0_LLQ) unpack(b []byte) error {
|
||||||
|
|
||||||
func (e *EDNS0_LLQ) String() string {
|
func (e *EDNS0_LLQ) String() string {
|
||||||
s := strconv.FormatUint(uint64(e.Version), 10) + " " + strconv.FormatUint(uint64(e.Opcode), 10) +
|
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)
|
" " + strconv.FormatUint(uint64(e.LeaseLife), 10)
|
||||||
return s
|
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.
|
// EDNS0_DUA implements the EDNS0 "DNSSEC Algorithm Understood" option. See RFC 6975.
|
||||||
type EDNS0_DAU struct {
|
type EDNS0_DAU struct {
|
||||||
|
@ -442,6 +462,7 @@ func (e *EDNS0_DAU) String() string {
|
||||||
}
|
}
|
||||||
return s
|
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.
|
// EDNS0_DHU implements the EDNS0 "DS Hash Understood" option. See RFC 6975.
|
||||||
type EDNS0_DHU struct {
|
type EDNS0_DHU struct {
|
||||||
|
@ -465,6 +486,7 @@ func (e *EDNS0_DHU) String() string {
|
||||||
}
|
}
|
||||||
return s
|
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.
|
// EDNS0_N3U implements the EDNS0 "NSEC3 Hash Understood" option. See RFC 6975.
|
||||||
type EDNS0_N3U struct {
|
type EDNS0_N3U struct {
|
||||||
|
@ -489,6 +511,7 @@ func (e *EDNS0_N3U) String() string {
|
||||||
}
|
}
|
||||||
return s
|
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.
|
// EDNS0_EXPIRE implementes the EDNS0 option as described in RFC 7314.
|
||||||
type EDNS0_EXPIRE struct {
|
type EDNS0_EXPIRE struct {
|
||||||
|
@ -499,13 +522,11 @@ type EDNS0_EXPIRE struct {
|
||||||
// Option implements the EDNS0 interface.
|
// Option implements the EDNS0 interface.
|
||||||
func (e *EDNS0_EXPIRE) Option() uint16 { return EDNS0EXPIRE }
|
func (e *EDNS0_EXPIRE) Option() uint16 { return EDNS0EXPIRE }
|
||||||
func (e *EDNS0_EXPIRE) String() string { return strconv.FormatUint(uint64(e.Expire), 10) }
|
func (e *EDNS0_EXPIRE) 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) {
|
func (e *EDNS0_EXPIRE) pack() ([]byte, error) {
|
||||||
b := make([]byte, 4)
|
b := make([]byte, 4)
|
||||||
b[0] = byte(e.Expire >> 24)
|
binary.BigEndian.PutUint32(b, e.Expire)
|
||||||
b[1] = byte(e.Expire >> 16)
|
|
||||||
b[2] = byte(e.Expire >> 8)
|
|
||||||
b[3] = byte(e.Expire)
|
|
||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -540,6 +561,11 @@ func (e *EDNS0_LOCAL) Option() uint16 { return e.Code }
|
||||||
func (e *EDNS0_LOCAL) String() string {
|
func (e *EDNS0_LOCAL) String() string {
|
||||||
return strconv.FormatInt(int64(e.Code), 10) + ":0x" + hex.EncodeToString(e.Data)
|
return strconv.FormatInt(int64(e.Code), 10) + ":0x" + hex.EncodeToString(e.Data)
|
||||||
}
|
}
|
||||||
|
func (e *EDNS0_LOCAL) copy() EDNS0 {
|
||||||
|
b := make([]byte, len(e.Data))
|
||||||
|
copy(b, e.Data)
|
||||||
|
return &EDNS0_LOCAL{e.Code, b}
|
||||||
|
}
|
||||||
|
|
||||||
func (e *EDNS0_LOCAL) pack() ([]byte, error) {
|
func (e *EDNS0_LOCAL) pack() ([]byte, error) {
|
||||||
b := make([]byte, len(e.Data))
|
b := make([]byte, len(e.Data))
|
||||||
|
@ -612,6 +638,7 @@ func (e *EDNS0_TCP_KEEPALIVE) String() (s string) {
|
||||||
}
|
}
|
||||||
return
|
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
|
// EDNS0_PADDING option is used to add padding to a request/response. The default
|
||||||
// value of padding SHOULD be 0x0 but other values MAY be used, for instance if
|
// value of padding SHOULD be 0x0 but other values MAY be used, for instance if
|
||||||
|
@ -625,3 +652,8 @@ func (e *EDNS0_PADDING) Option() uint16 { return EDNS0PADDING }
|
||||||
func (e *EDNS0_PADDING) pack() ([]byte, error) { return e.Padding, nil }
|
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) 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) 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}
|
||||||
|
}
|
||||||
|
|
2
vendor/github.com/miekg/dns/format.go
generated
vendored
2
vendor/github.com/miekg/dns/format.go
generated
vendored
|
@ -20,7 +20,7 @@ func Field(r RR, i int) string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
d := reflect.ValueOf(r).Elem().Field(i)
|
d := reflect.ValueOf(r).Elem().Field(i)
|
||||||
switch k := d.Kind(); k {
|
switch d.Kind() {
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
return d.String()
|
return d.String()
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
|
309
vendor/github.com/miekg/dns/generate.go
generated
vendored
309
vendor/github.com/miekg/dns/generate.go
generated
vendored
|
@ -2,8 +2,8 @@ package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -18,142 +18,225 @@ import (
|
||||||
// * rhs (rdata)
|
// * rhs (rdata)
|
||||||
// But we are lazy here, only the range is parsed *all* occurrences
|
// But we are lazy here, only the range is parsed *all* occurrences
|
||||||
// of $ after that are interpreted.
|
// of $ after that are interpreted.
|
||||||
// Any error are returned as a string value, the empty string signals
|
func (zp *ZoneParser) generate(l lex) (RR, bool) {
|
||||||
// "no error".
|
token := l.token
|
||||||
func generate(l lex, c chan lex, t chan *Token, o string) string {
|
|
||||||
step := 1
|
step := 1
|
||||||
if i := strings.IndexAny(l.token, "/"); i != -1 {
|
if i := strings.IndexByte(token, '/'); i >= 0 {
|
||||||
if i+1 == len(l.token) {
|
if i+1 == len(token) {
|
||||||
return "bad step in $GENERATE range"
|
return zp.setParseError("bad step in $GENERATE range", l)
|
||||||
}
|
}
|
||||||
if s, err := strconv.Atoi(l.token[i+1:]); err == nil {
|
|
||||||
if s < 0 {
|
s, err := strconv.Atoi(token[i+1:])
|
||||||
return "bad step in $GENERATE range"
|
if err != nil || s <= 0 {
|
||||||
}
|
return zp.setParseError("bad step in $GENERATE range", l)
|
||||||
step = s
|
|
||||||
} else {
|
|
||||||
return "bad step in $GENERATE range"
|
|
||||||
}
|
}
|
||||||
l.token = l.token[:i]
|
|
||||||
|
step = s
|
||||||
|
token = token[:i]
|
||||||
}
|
}
|
||||||
sx := strings.SplitN(l.token, "-", 2)
|
|
||||||
|
sx := strings.SplitN(token, "-", 2)
|
||||||
if len(sx) != 2 {
|
if len(sx) != 2 {
|
||||||
return "bad start-stop in $GENERATE range"
|
return zp.setParseError("bad start-stop in $GENERATE range", l)
|
||||||
}
|
}
|
||||||
|
|
||||||
start, err := strconv.Atoi(sx[0])
|
start, err := strconv.Atoi(sx[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "bad start in $GENERATE range"
|
return zp.setParseError("bad start in $GENERATE range", l)
|
||||||
}
|
}
|
||||||
|
|
||||||
end, err := strconv.Atoi(sx[1])
|
end, err := strconv.Atoi(sx[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "bad stop in $GENERATE range"
|
return zp.setParseError("bad stop in $GENERATE range", l)
|
||||||
}
|
}
|
||||||
if end < 0 || start < 0 || end < start {
|
if end < 0 || start < 0 || end < start {
|
||||||
return "bad range in $GENERATE range"
|
return zp.setParseError("bad range in $GENERATE range", l)
|
||||||
}
|
}
|
||||||
|
|
||||||
<-c // _BLANK
|
zp.c.Next() // _BLANK
|
||||||
|
|
||||||
// Create a complete new string, which we then parse again.
|
// Create a complete new string, which we then parse again.
|
||||||
s := ""
|
var s string
|
||||||
BuildRR:
|
for l, ok := zp.c.Next(); ok; l, ok = zp.c.Next() {
|
||||||
l = <-c
|
if l.err {
|
||||||
if l.value != zNewline && l.value != zEOF {
|
return zp.setParseError("bad data in $GENERATE directive", l)
|
||||||
s += l.token
|
}
|
||||||
goto BuildRR
|
if l.value == zNewline {
|
||||||
}
|
break
|
||||||
for i := start; i <= end; i += step {
|
}
|
||||||
var (
|
|
||||||
escape bool
|
|
||||||
dom bytes.Buffer
|
|
||||||
mod string
|
|
||||||
err error
|
|
||||||
offset int
|
|
||||||
)
|
|
||||||
|
|
||||||
for j := 0; j < len(s); j++ { // No 'range' because we need to jump around
|
s += l.token
|
||||||
switch s[j] {
|
}
|
||||||
case '\\':
|
|
||||||
if escape {
|
r := &generateReader{
|
||||||
dom.WriteByte('\\')
|
s: s,
|
||||||
escape = false
|
|
||||||
continue
|
cur: start,
|
||||||
}
|
start: start,
|
||||||
escape = true
|
end: end,
|
||||||
case '$':
|
step: step,
|
||||||
mod = "%d"
|
|
||||||
offset = 0
|
file: zp.file,
|
||||||
if escape {
|
lex: &l,
|
||||||
dom.WriteByte('$')
|
}
|
||||||
escape = false
|
zp.sub = NewZoneParser(r, zp.origin, zp.file)
|
||||||
continue
|
zp.sub.includeDepth, zp.sub.includeAllowed = zp.includeDepth, zp.includeAllowed
|
||||||
}
|
zp.sub.SetDefaultTTL(defaultTtl)
|
||||||
escape = false
|
return zp.subNext()
|
||||||
if j+1 >= len(s) { // End of the string
|
}
|
||||||
dom.WriteString(fmt.Sprintf(mod, i+offset))
|
|
||||||
continue
|
type generateReader struct {
|
||||||
} else {
|
s string
|
||||||
if s[j+1] == '$' {
|
si int
|
||||||
dom.WriteByte('$')
|
|
||||||
j++
|
cur int
|
||||||
continue
|
start int
|
||||||
}
|
end int
|
||||||
}
|
step int
|
||||||
// Search for { and }
|
|
||||||
if s[j+1] == '{' { // Modifier block
|
mod bytes.Buffer
|
||||||
sep := strings.Index(s[j+2:], "}")
|
|
||||||
if sep == -1 {
|
escape bool
|
||||||
return "bad modifier in $GENERATE"
|
|
||||||
}
|
eof bool
|
||||||
mod, offset, err = modToPrintf(s[j+2 : j+2+sep])
|
|
||||||
if err != nil {
|
file string
|
||||||
return err.Error()
|
lex *lex
|
||||||
}
|
}
|
||||||
j += 2 + sep // Jump to it
|
|
||||||
}
|
func (r *generateReader) parseError(msg string, end int) *ParseError {
|
||||||
dom.WriteString(fmt.Sprintf(mod, i+offset))
|
r.eof = true // Make errors sticky.
|
||||||
default:
|
|
||||||
if escape { // Pretty useless here
|
l := *r.lex
|
||||||
escape = false
|
l.token = r.s[r.si-1 : end]
|
||||||
continue
|
l.column += r.si // l.column starts one zBLANK before r.s
|
||||||
}
|
|
||||||
dom.WriteByte(s[j])
|
return &ParseError{r.file, msg, l}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// Re-parse the RR and send it on the current channel t
|
func (r *generateReader) Read(p []byte) (int, error) {
|
||||||
rx, err := NewRR("$ORIGIN " + o + "\n" + dom.String())
|
// NewZLexer, through NewZoneParser, should use ReadByte and
|
||||||
if err != nil {
|
// not end up here.
|
||||||
return err.Error()
|
|
||||||
}
|
panic("not implemented")
|
||||||
t <- &Token{RR: rx}
|
}
|
||||||
// Its more efficient to first built the rrlist and then parse it in
|
|
||||||
// one go! But is this a problem?
|
func (r *generateReader) ReadByte() (byte, error) {
|
||||||
|
if r.eof {
|
||||||
|
return 0, io.EOF
|
||||||
|
}
|
||||||
|
if r.mod.Len() > 0 {
|
||||||
|
return r.mod.ReadByte()
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.si >= len(r.s) {
|
||||||
|
r.si = 0
|
||||||
|
r.cur += r.step
|
||||||
|
|
||||||
|
r.eof = r.cur > r.end || r.cur < 0
|
||||||
|
return '\n', nil
|
||||||
|
}
|
||||||
|
|
||||||
|
si := r.si
|
||||||
|
r.si++
|
||||||
|
|
||||||
|
switch r.s[si] {
|
||||||
|
case '\\':
|
||||||
|
if r.escape {
|
||||||
|
r.escape = false
|
||||||
|
return '\\', nil
|
||||||
|
}
|
||||||
|
|
||||||
|
r.escape = true
|
||||||
|
return r.ReadByte()
|
||||||
|
case '$':
|
||||||
|
if r.escape {
|
||||||
|
r.escape = false
|
||||||
|
return '$', nil
|
||||||
|
}
|
||||||
|
|
||||||
|
mod := "%d"
|
||||||
|
|
||||||
|
if si >= len(r.s)-1 {
|
||||||
|
// End of the string
|
||||||
|
fmt.Fprintf(&r.mod, mod, r.cur)
|
||||||
|
return r.mod.ReadByte()
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.s[si+1] == '$' {
|
||||||
|
r.si++
|
||||||
|
return '$', nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var offset int
|
||||||
|
|
||||||
|
// Search for { and }
|
||||||
|
if r.s[si+1] == '{' {
|
||||||
|
// Modifier block
|
||||||
|
sep := strings.Index(r.s[si+2:], "}")
|
||||||
|
if sep < 0 {
|
||||||
|
return 0, r.parseError("bad modifier in $GENERATE", len(r.s))
|
||||||
|
}
|
||||||
|
|
||||||
|
var errMsg string
|
||||||
|
mod, offset, errMsg = modToPrintf(r.s[si+2 : si+2+sep])
|
||||||
|
if errMsg != "" {
|
||||||
|
return 0, r.parseError(errMsg, si+3+sep)
|
||||||
|
}
|
||||||
|
if r.start+offset < 0 || r.end+offset > 1<<31-1 {
|
||||||
|
return 0, r.parseError("bad offset in $GENERATE", si+3+sep)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.si += 2 + sep // Jump to it
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(&r.mod, mod, r.cur+offset)
|
||||||
|
return r.mod.ReadByte()
|
||||||
|
default:
|
||||||
|
if r.escape { // Pretty useless here
|
||||||
|
r.escape = false
|
||||||
|
return r.ReadByte()
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.s[si], nil
|
||||||
}
|
}
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert a $GENERATE modifier 0,0,d to something Printf can deal with.
|
// Convert a $GENERATE modifier 0,0,d to something Printf can deal with.
|
||||||
func modToPrintf(s string) (string, int, error) {
|
func modToPrintf(s string) (string, int, string) {
|
||||||
xs := strings.SplitN(s, ",", 3)
|
// Modifier is { offset [ ,width [ ,base ] ] } - provide default
|
||||||
if len(xs) != 3 {
|
// values for optional width and type, if necessary.
|
||||||
return "", 0, errors.New("bad modifier in $GENERATE")
|
var offStr, widthStr, base string
|
||||||
|
switch xs := strings.Split(s, ","); len(xs) {
|
||||||
|
case 1:
|
||||||
|
offStr, widthStr, base = xs[0], "0", "d"
|
||||||
|
case 2:
|
||||||
|
offStr, widthStr, base = xs[0], xs[1], "d"
|
||||||
|
case 3:
|
||||||
|
offStr, widthStr, base = xs[0], xs[1], xs[2]
|
||||||
|
default:
|
||||||
|
return "", 0, "bad modifier in $GENERATE"
|
||||||
}
|
}
|
||||||
// xs[0] is offset, xs[1] is width, xs[2] is base
|
|
||||||
if xs[2] != "o" && xs[2] != "d" && xs[2] != "x" && xs[2] != "X" {
|
switch base {
|
||||||
return "", 0, errors.New("bad base in $GENERATE")
|
case "o", "d", "x", "X":
|
||||||
|
default:
|
||||||
|
return "", 0, "bad base in $GENERATE"
|
||||||
}
|
}
|
||||||
offset, err := strconv.Atoi(xs[0])
|
|
||||||
if err != nil || offset > 255 {
|
offset, err := strconv.Atoi(offStr)
|
||||||
return "", 0, errors.New("bad offset in $GENERATE")
|
if err != nil {
|
||||||
|
return "", 0, "bad offset in $GENERATE"
|
||||||
}
|
}
|
||||||
width, err := strconv.Atoi(xs[1])
|
|
||||||
if err != nil || width > 255 {
|
width, err := strconv.Atoi(widthStr)
|
||||||
return "", offset, errors.New("bad width in $GENERATE")
|
if err != nil || width < 0 || width > 255 {
|
||||||
|
return "", 0, "bad width in $GENERATE"
|
||||||
}
|
}
|
||||||
switch {
|
|
||||||
case width < 0:
|
if width == 0 {
|
||||||
return "", offset, errors.New("bad width in $GENERATE")
|
return "%" + base, offset, ""
|
||||||
case width == 0:
|
|
||||||
return "%" + xs[1] + xs[2], offset, nil
|
|
||||||
}
|
}
|
||||||
return "%0" + xs[1] + xs[2], offset, nil
|
|
||||||
|
return "%0" + widthStr + base, offset, ""
|
||||||
}
|
}
|
||||||
|
|
9
vendor/github.com/miekg/dns/labels.go
generated
vendored
9
vendor/github.com/miekg/dns/labels.go
generated
vendored
|
@ -16,7 +16,7 @@ func SplitDomainName(s string) (labels []string) {
|
||||||
fqdnEnd := 0 // offset of the final '.' or the length of the name
|
fqdnEnd := 0 // offset of the final '.' or the length of the name
|
||||||
idx := Split(s)
|
idx := Split(s)
|
||||||
begin := 0
|
begin := 0
|
||||||
if s[len(s)-1] == '.' {
|
if IsFqdn(s) {
|
||||||
fqdnEnd = len(s) - 1
|
fqdnEnd = len(s) - 1
|
||||||
} else {
|
} else {
|
||||||
fqdnEnd = len(s)
|
fqdnEnd = len(s)
|
||||||
|
@ -36,8 +36,7 @@ func SplitDomainName(s string) (labels []string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
labels = append(labels, s[begin:fqdnEnd])
|
return append(labels, s[begin:fqdnEnd])
|
||||||
return labels
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CompareDomainName compares the names s1 and s2 and
|
// CompareDomainName compares the names s1 and s2 and
|
||||||
|
@ -178,10 +177,10 @@ func equal(a, b string) bool {
|
||||||
ai := a[i]
|
ai := a[i]
|
||||||
bi := b[i]
|
bi := b[i]
|
||||||
if ai >= 'A' && ai <= 'Z' {
|
if ai >= 'A' && ai <= 'Z' {
|
||||||
ai |= ('a' - 'A')
|
ai |= 'a' - 'A'
|
||||||
}
|
}
|
||||||
if bi >= 'A' && bi <= 'Z' {
|
if bi >= 'A' && bi <= 'Z' {
|
||||||
bi |= ('a' - 'A')
|
bi |= 'a' - 'A'
|
||||||
}
|
}
|
||||||
if ai != bi {
|
if ai != bi {
|
||||||
return false
|
return false
|
||||||
|
|
44
vendor/github.com/miekg/dns/listen_go111.go
generated
vendored
Normal file
44
vendor/github.com/miekg/dns/listen_go111.go
generated
vendored
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
// +build go1.11
|
||||||
|
// +build aix darwin dragonfly freebsd linux netbsd openbsd
|
||||||
|
|
||||||
|
package dns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
const supportsReusePort = true
|
||||||
|
|
||||||
|
func reuseportControl(network, address string, c syscall.RawConn) error {
|
||||||
|
var opErr error
|
||||||
|
err := c.Control(func(fd uintptr) {
|
||||||
|
opErr = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return opErr
|
||||||
|
}
|
||||||
|
|
||||||
|
func listenTCP(network, addr string, reuseport bool) (net.Listener, error) {
|
||||||
|
var lc net.ListenConfig
|
||||||
|
if reuseport {
|
||||||
|
lc.Control = reuseportControl
|
||||||
|
}
|
||||||
|
|
||||||
|
return lc.Listen(context.Background(), network, addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func listenUDP(network, addr string, reuseport bool) (net.PacketConn, error) {
|
||||||
|
var lc net.ListenConfig
|
||||||
|
if reuseport {
|
||||||
|
lc.Control = reuseportControl
|
||||||
|
}
|
||||||
|
|
||||||
|
return lc.ListenPacket(context.Background(), network, addr)
|
||||||
|
}
|
23
vendor/github.com/miekg/dns/listen_go_not111.go
generated
vendored
Normal file
23
vendor/github.com/miekg/dns/listen_go_not111.go
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// +build !go1.11 !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd
|
||||||
|
|
||||||
|
package dns
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
const supportsReusePort = false
|
||||||
|
|
||||||
|
func listenTCP(network, addr string, reuseport bool) (net.Listener, error) {
|
||||||
|
if reuseport {
|
||||||
|
// TODO(tmthrgd): return an error?
|
||||||
|
}
|
||||||
|
|
||||||
|
return net.Listen(network, addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func listenUDP(network, addr string, reuseport bool) (net.PacketConn, error) {
|
||||||
|
if reuseport {
|
||||||
|
// TODO(tmthrgd): return an error?
|
||||||
|
}
|
||||||
|
|
||||||
|
return net.ListenPacket(network, addr)
|
||||||
|
}
|
713
vendor/github.com/miekg/dns/msg.go
generated
vendored
713
vendor/github.com/miekg/dns/msg.go
generated
vendored
|
@ -9,7 +9,6 @@
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
//go:generate go run msg_generate.go
|
//go:generate go run msg_generate.go
|
||||||
//go:generate go run compress_generate.go
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
crand "crypto/rand"
|
crand "crypto/rand"
|
||||||
|
@ -18,12 +17,35 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
maxCompressionOffset = 2 << 13 // We have 14 bits for the compression pointer
|
maxCompressionOffset = 2 << 13 // We have 14 bits for the compression pointer
|
||||||
maxDomainNameWireOctets = 255 // See RFC 1035 section 2.3.4
|
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.
|
// Errors defined in this package.
|
||||||
|
@ -46,10 +68,9 @@ var (
|
||||||
ErrRRset error = &Error{err: "bad rrset"}
|
ErrRRset error = &Error{err: "bad rrset"}
|
||||||
ErrSecret error = &Error{err: "no secrets defined"}
|
ErrSecret error = &Error{err: "no secrets defined"}
|
||||||
ErrShortRead error = &Error{err: "short read"}
|
ErrShortRead error = &Error{err: "short read"}
|
||||||
ErrSig error = &Error{err: "bad signature"} // ErrSig indicates that a signature can not be cryptographically validated.
|
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.
|
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.
|
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.
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Id by default, returns a 16 bits random number to be used as a
|
// Id by default, returns a 16 bits random number to be used as a
|
||||||
|
@ -151,7 +172,7 @@ var RcodeToString = map[int]string{
|
||||||
RcodeFormatError: "FORMERR",
|
RcodeFormatError: "FORMERR",
|
||||||
RcodeServerFailure: "SERVFAIL",
|
RcodeServerFailure: "SERVFAIL",
|
||||||
RcodeNameError: "NXDOMAIN",
|
RcodeNameError: "NXDOMAIN",
|
||||||
RcodeNotImplemented: "NOTIMPL",
|
RcodeNotImplemented: "NOTIMP",
|
||||||
RcodeRefused: "REFUSED",
|
RcodeRefused: "REFUSED",
|
||||||
RcodeYXDomain: "YXDOMAIN", // See RFC 2136
|
RcodeYXDomain: "YXDOMAIN", // See RFC 2136
|
||||||
RcodeYXRrset: "YXRRSET",
|
RcodeYXRrset: "YXRRSET",
|
||||||
|
@ -169,6 +190,39 @@ var RcodeToString = map[int]string{
|
||||||
RcodeBadCookie: "BADCOOKIE",
|
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
|
// Domain names are a sequence of counted strings
|
||||||
// split at the dots. They end with a zero-length string.
|
// split at the dots. They end with a zero-length string.
|
||||||
|
|
||||||
|
@ -177,143 +231,156 @@ var RcodeToString = map[int]string{
|
||||||
// map needs to hold a mapping between domain names and offsets
|
// map needs to hold a mapping between domain names and offsets
|
||||||
// pointing into msg.
|
// pointing into msg.
|
||||||
func PackDomainName(s string, msg []byte, off int, compression map[string]int, compress bool) (off1 int, err error) {
|
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 packDomainName(s, msg, off, compressionMap{ext: compression}, compress)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func packDomainName(s string, msg []byte, off int, compression map[string]int, compress bool) (off1 int, labels int, err error) {
|
func packDomainName(s string, msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
|
||||||
// special case if msg == nil
|
// XXX: A logical copy of this function exists in IsDomainName and
|
||||||
lenmsg := 256
|
// should be kept in sync with this function.
|
||||||
if msg != nil {
|
|
||||||
lenmsg = len(msg)
|
|
||||||
}
|
|
||||||
ls := len(s)
|
ls := len(s)
|
||||||
if ls == 0 { // Ok, for instance when dealing with update RR without any rdata.
|
if ls == 0 { // Ok, for instance when dealing with update RR without any rdata.
|
||||||
return off, 0, nil
|
return off, nil
|
||||||
}
|
}
|
||||||
// If not fully qualified, error out, but only if msg == nil #ugly
|
|
||||||
switch {
|
// If not fully qualified, error out.
|
||||||
case msg == nil:
|
if !IsFqdn(s) {
|
||||||
if s[ls-1] != '.' {
|
return len(msg), ErrFqdn
|
||||||
s += "."
|
|
||||||
ls++
|
|
||||||
}
|
|
||||||
case msg != nil:
|
|
||||||
if s[ls-1] != '.' {
|
|
||||||
return lenmsg, 0, ErrFqdn
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Each dot ends a segment of the name.
|
// Each dot ends a segment of the name.
|
||||||
// We trade each dot byte for a length byte.
|
// We trade each dot byte for a length byte.
|
||||||
// Except for escaped dots (\.), which are normal dots.
|
// Except for escaped dots (\.), which are normal dots.
|
||||||
// There is also a trailing zero.
|
// There is also a trailing zero.
|
||||||
|
|
||||||
// Compression
|
// Compression
|
||||||
nameoffset := -1
|
|
||||||
pointer := -1
|
pointer := -1
|
||||||
|
|
||||||
// Emit sequence of counted strings, chopping at dots.
|
// Emit sequence of counted strings, chopping at dots.
|
||||||
begin := 0
|
var (
|
||||||
bs := []byte(s)
|
begin int
|
||||||
roBs, bsFresh, escapedDot := s, true, false
|
compBegin int
|
||||||
|
compOff int
|
||||||
|
bs []byte
|
||||||
|
wasDot bool
|
||||||
|
)
|
||||||
|
loop:
|
||||||
for i := 0; i < ls; i++ {
|
for i := 0; i < ls; i++ {
|
||||||
if bs[i] == '\\' {
|
var c byte
|
||||||
for j := i; j < ls-1; j++ {
|
if bs == nil {
|
||||||
bs[j] = bs[j+1]
|
c = s[i]
|
||||||
}
|
} else {
|
||||||
ls--
|
c = bs[i]
|
||||||
if off+1 > lenmsg {
|
|
||||||
return lenmsg, labels, ErrBuf
|
|
||||||
}
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
escapedDot = bs[i] == '.'
|
|
||||||
bsFresh = false
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if bs[i] == '.' {
|
switch c {
|
||||||
if i > 0 && bs[i-1] == '.' && !escapedDot {
|
case '\\':
|
||||||
|
if off+1 > len(msg) {
|
||||||
|
return len(msg), ErrBuf
|
||||||
|
}
|
||||||
|
|
||||||
|
if bs == nil {
|
||||||
|
bs = []byte(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for \DDD
|
||||||
|
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++
|
||||||
|
}
|
||||||
|
|
||||||
|
wasDot = false
|
||||||
|
case '.':
|
||||||
|
if wasDot {
|
||||||
// two dots back to back is not legal
|
// 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
|
wasDot = true
|
||||||
return lenmsg, labels, ErrRdata
|
|
||||||
|
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)
|
// off can already (we're in a loop) be bigger than len(msg)
|
||||||
// this happens when a name isn't fully qualified
|
// this happens when a name isn't fully qualified
|
||||||
if off+1 > lenmsg {
|
if off+1+labelLen > len(msg) {
|
||||||
return lenmsg, labels, ErrBuf
|
return len(msg), 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't try to compress '.'
|
// 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).
|
// up names that can be used for *future* compression(s).
|
||||||
if compression != nil && roBs[begin:] != "." {
|
if compression.valid() && !isRootLabel(s, bs, begin, ls) {
|
||||||
if p, ok := compression[roBs[begin:]]; !ok {
|
if p, ok := compression.find(s[compBegin:]); ok {
|
||||||
// Only offsets smaller than this can be used.
|
|
||||||
if offset < maxCompressionOffset {
|
|
||||||
compression[roBs[begin:]] = offset
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// The first hit is the longest matching dname
|
// The first hit is the longest matching dname
|
||||||
// keep the pointer offset we get back and store
|
// keep the pointer offset we get back and store
|
||||||
// the offset of the current name, because that's
|
// the offset of the current name, because that's
|
||||||
// where we need to insert the pointer later
|
// where we need to insert the pointer later
|
||||||
|
|
||||||
// If compress is true, we're allowed to compress this dname
|
// If compress is true, we're allowed to compress this dname
|
||||||
if pointer == -1 && compress {
|
if compress {
|
||||||
pointer = p // Where to point to
|
pointer = p // Where to point to
|
||||||
nameoffset = offset // Where to point from
|
break loop
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
} 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
|
begin = i + 1
|
||||||
|
compBegin = begin + compOff
|
||||||
|
default:
|
||||||
|
wasDot = false
|
||||||
}
|
}
|
||||||
escapedDot = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Root label is special
|
// Root label is special
|
||||||
if len(bs) == 1 && bs[0] == '.' {
|
if isRootLabel(s, bs, 0, ls) {
|
||||||
return off, labels, nil
|
return off, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we did compression and we find something add the pointer here
|
// If we did compression and we find something add the pointer here
|
||||||
if pointer != -1 {
|
if pointer != -1 {
|
||||||
// We have two bytes (14 bits) to put the pointer in
|
// We have two bytes (14 bits) to put the pointer in
|
||||||
// if msg == nil, we will never do compression
|
binary.BigEndian.PutUint16(msg[off:], uint16(pointer^0xC000))
|
||||||
binary.BigEndian.PutUint16(msg[nameoffset:], uint16(pointer^0xC000))
|
return off + 2, nil
|
||||||
off = nameoffset + 1
|
|
||||||
goto End
|
|
||||||
}
|
}
|
||||||
if msg != nil && off < len(msg) {
|
|
||||||
|
if off < len(msg) {
|
||||||
msg[off] = 0
|
msg[off] = 0
|
||||||
}
|
}
|
||||||
End:
|
|
||||||
off++
|
return off + 1, nil
|
||||||
return off, labels, 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.
|
// Unpack a domain name.
|
||||||
|
@ -330,12 +397,16 @@ End:
|
||||||
// In theory, the pointers are only allowed to jump backward.
|
// In theory, the pointers are only allowed to jump backward.
|
||||||
// We let them jump anywhere and stop jumping after a while.
|
// 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) {
|
func UnpackDomainName(msg []byte, off int) (string, int, error) {
|
||||||
s := make([]byte, 0, 64)
|
s := make([]byte, 0, maxDomainNamePresentationLength)
|
||||||
off1 := 0
|
off1 := 0
|
||||||
lenmsg := len(msg)
|
lenmsg := len(msg)
|
||||||
maxLen := maxDomainNameWireOctets
|
budget := maxDomainNameWireOctets
|
||||||
ptr := 0 // number of pointers followed
|
ptr := 0 // number of pointers followed
|
||||||
Loop:
|
Loop:
|
||||||
for {
|
for {
|
||||||
|
@ -354,27 +425,19 @@ Loop:
|
||||||
if off+c > lenmsg {
|
if off+c > lenmsg {
|
||||||
return "", lenmsg, ErrBuf
|
return "", lenmsg, ErrBuf
|
||||||
}
|
}
|
||||||
|
budget -= c + 1 // +1 for the label separator
|
||||||
|
if budget <= 0 {
|
||||||
|
return "", lenmsg, ErrLongDomain
|
||||||
|
}
|
||||||
for j := off; j < off+c; j++ {
|
for j := off; j < off+c; j++ {
|
||||||
switch b := msg[j]; b {
|
switch b := msg[j]; b {
|
||||||
case '.', '(', ')', ';', ' ', '@':
|
case '.', '(', ')', ';', ' ', '@':
|
||||||
fallthrough
|
fallthrough
|
||||||
case '"', '\\':
|
case '"', '\\':
|
||||||
s = append(s, '\\', b)
|
s = append(s, '\\', b)
|
||||||
// presentation-format \X escapes add an extra byte
|
|
||||||
maxLen++
|
|
||||||
default:
|
default:
|
||||||
if b < 32 || b >= 127 { // unprintable, use \DDD
|
if b < ' ' || b > '~' { // unprintable, use \DDD
|
||||||
var buf [3]byte
|
s = append(s, escapeByte(b)...)
|
||||||
bufs := strconv.AppendInt(buf[:0], int64(b), 10)
|
|
||||||
s = append(s, '\\')
|
|
||||||
for i := 0; i < 3-len(bufs); i++ {
|
|
||||||
s = append(s, '0')
|
|
||||||
}
|
|
||||||
for _, r := range bufs {
|
|
||||||
s = append(s, r)
|
|
||||||
}
|
|
||||||
// presentation-format \DDD escapes add 3 extra bytes
|
|
||||||
maxLen += 3
|
|
||||||
} else {
|
} else {
|
||||||
s = append(s, b)
|
s = append(s, b)
|
||||||
}
|
}
|
||||||
|
@ -396,7 +459,7 @@ Loop:
|
||||||
if ptr == 0 {
|
if ptr == 0 {
|
||||||
off1 = off
|
off1 = off
|
||||||
}
|
}
|
||||||
if ptr++; ptr > 10 {
|
if ptr++; ptr > maxCompressionPointers {
|
||||||
return "", lenmsg, &Error{err: "too many compression pointers"}
|
return "", lenmsg, &Error{err: "too many compression pointers"}
|
||||||
}
|
}
|
||||||
// pointer should guarantee that it advances and points forwards at least
|
// pointer should guarantee that it advances and points forwards at least
|
||||||
|
@ -412,10 +475,7 @@ Loop:
|
||||||
off1 = off
|
off1 = off
|
||||||
}
|
}
|
||||||
if len(s) == 0 {
|
if len(s) == 0 {
|
||||||
s = []byte(".")
|
return ".", off1, nil
|
||||||
} else if len(s) >= maxLen {
|
|
||||||
// error if the name is too long, but don't throw it away
|
|
||||||
return string(s), lenmsg, ErrLongDomain
|
|
||||||
}
|
}
|
||||||
return string(s), off1, nil
|
return string(s), off1, nil
|
||||||
}
|
}
|
||||||
|
@ -512,7 +572,7 @@ func unpackTxt(msg []byte, off0 int) (ss []string, off int, err error) {
|
||||||
off = off0
|
off = off0
|
||||||
var s string
|
var s string
|
||||||
for off < len(msg) && err == nil {
|
for off < len(msg) && err == nil {
|
||||||
s, off, err = unpackTxtString(msg, off)
|
s, off, err = unpackString(msg, off)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
ss = append(ss, s)
|
ss = append(ss, s)
|
||||||
}
|
}
|
||||||
|
@ -520,43 +580,16 @@ func unpackTxt(msg []byte, off0 int) (ss []string, off int, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func unpackTxtString(msg []byte, offset int) (string, int, error) {
|
|
||||||
if offset+1 > len(msg) {
|
|
||||||
return "", offset, &Error{err: "overflow unpacking txt"}
|
|
||||||
}
|
|
||||||
l := int(msg[offset])
|
|
||||||
if offset+l+1 > len(msg) {
|
|
||||||
return "", offset, &Error{err: "overflow unpacking txt"}
|
|
||||||
}
|
|
||||||
s := make([]byte, 0, l)
|
|
||||||
for _, b := range msg[offset+1 : offset+1+l] {
|
|
||||||
switch b {
|
|
||||||
case '"', '\\':
|
|
||||||
s = append(s, '\\', b)
|
|
||||||
default:
|
|
||||||
if b < 32 || b > 127 { // unprintable
|
|
||||||
var buf [3]byte
|
|
||||||
bufs := strconv.AppendInt(buf[:0], int64(b), 10)
|
|
||||||
s = append(s, '\\')
|
|
||||||
for i := 0; i < 3-len(bufs); i++ {
|
|
||||||
s = append(s, '0')
|
|
||||||
}
|
|
||||||
for _, r := range bufs {
|
|
||||||
s = append(s, r)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
s = append(s, b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
offset += 1 + l
|
|
||||||
return string(s), offset, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helpers for dealing with escaped bytes
|
// Helpers for dealing with escaped bytes
|
||||||
func isDigit(b byte) bool { return b >= '0' && b <= '9' }
|
func isDigit(b byte) bool { return b >= '0' && b <= '9' }
|
||||||
|
|
||||||
func dddToByte(s []byte) byte {
|
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'))
|
return byte((s[0]-'0')*100 + (s[1]-'0')*10 + (s[2] - '0'))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -574,19 +607,38 @@ func intToBytes(i *big.Int, length int) []byte {
|
||||||
// PackRR packs a resource record rr into msg[off:].
|
// PackRR packs a resource record rr into msg[off:].
|
||||||
// See PackDomainName for documentation about the compression.
|
// 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) {
|
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 {
|
if rr == nil {
|
||||||
return len(msg), &Error{err: "nil rr"}
|
return len(msg), len(msg), &Error{err: "nil rr"}
|
||||||
}
|
}
|
||||||
|
|
||||||
off1, err = rr.pack(msg, off, compression, compress)
|
headerEnd, err = rr.Header().packHeader(msg, off, compression, compress)
|
||||||
if err != nil {
|
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) {
|
off1, err = rr.pack(msg, headerEnd, compression, compress)
|
||||||
return off1, nil
|
if err != nil {
|
||||||
|
return headerEnd, len(msg), err
|
||||||
}
|
}
|
||||||
return off, ErrRdata
|
|
||||||
|
rdlength := off1 - headerEnd
|
||||||
|
if int(uint16(rdlength)) != rdlength { // overflow
|
||||||
|
return headerEnd, len(msg), 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.
|
// UnpackRR unpacks msg[off:] into an RR.
|
||||||
|
@ -595,17 +647,35 @@ func UnpackRR(msg []byte, off int) (rr RR, off1 int, err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, len(msg), err
|
return nil, len(msg), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return UnpackRRWithHeader(h, msg, off)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
end := off + int(h.Rdlength)
|
||||||
|
|
||||||
if fn, known := typeToUnpack[h.Rrtype]; !known {
|
off, err = rr.unpack(msg, off)
|
||||||
rr, off, err = unpackRFC3597(h, msg, off)
|
if err != nil {
|
||||||
} else {
|
return nil, end, err
|
||||||
rr, off, err = fn(h, msg, off)
|
|
||||||
}
|
}
|
||||||
if off != end {
|
if off != end {
|
||||||
return &h, end, &Error{err: "bad rdlength"}
|
return &h, end, &Error{err: "bad rdlength"}
|
||||||
}
|
}
|
||||||
return rr, off, err
|
|
||||||
|
return rr, off, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// unpackRRslice unpacks msg[off:] into an []RR.
|
// unpackRRslice unpacks msg[off:] into an []RR.
|
||||||
|
@ -684,35 +754,37 @@ func (dns *Msg) Pack() (msg []byte, err error) {
|
||||||
return dns.PackBuffer(nil)
|
return dns.PackBuffer(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PackBuffer packs a Msg, using the given buffer buf. If buf is too small
|
// PackBuffer packs a Msg, using the given buffer buf. If buf is too small a new buffer is allocated.
|
||||||
// a new buffer is allocated.
|
|
||||||
func (dns *Msg) PackBuffer(buf []byte) (msg []byte, err error) {
|
func (dns *Msg) PackBuffer(buf []byte) (msg []byte, err error) {
|
||||||
// We use a similar function in tsig.go's stripTsig.
|
// If this message can't be compressed, avoid filling the
|
||||||
var (
|
// compression map and creating garbage.
|
||||||
dh Header
|
if dns.Compress && dns.isCompressible() {
|
||||||
compression map[string]int
|
compression := make(map[string]uint16) // Compression pointer mappings.
|
||||||
)
|
return dns.packBufferWithCompressionMap(buf, compressionMap{int: compression}, true)
|
||||||
|
|
||||||
if dns.Compress {
|
|
||||||
compression = make(map[string]int) // Compression pointer mappings
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return dns.packBufferWithCompressionMap(buf, compressionMap{}, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// packBufferWithCompressionMap packs a Msg, using the given buffer buf.
|
||||||
|
func (dns *Msg) packBufferWithCompressionMap(buf []byte, compression compressionMap, compress bool) (msg []byte, err error) {
|
||||||
if dns.Rcode < 0 || dns.Rcode > 0xFFF {
|
if dns.Rcode < 0 || dns.Rcode > 0xFFF {
|
||||||
return nil, ErrRcode
|
return nil, ErrRcode
|
||||||
}
|
}
|
||||||
if dns.Rcode > 0xF {
|
|
||||||
// Regular RCODE field is 4 bits
|
// Set extended rcode unconditionally if we have an opt, this will allow
|
||||||
opt := dns.IsEdns0()
|
// reseting the extended rcode bits if they need to.
|
||||||
if opt == nil {
|
if opt := dns.IsEdns0(); opt != nil {
|
||||||
return nil, ErrExtendedRcode
|
opt.SetExtendedRcode(uint16(dns.Rcode))
|
||||||
}
|
} else if dns.Rcode > 0xF {
|
||||||
opt.SetExtendedRcode(uint8(dns.Rcode >> 4))
|
// If Rcode is an extended one and opt is nil, error out.
|
||||||
dns.Rcode &= 0xF
|
return nil, ErrExtendedRcode
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert convenient Msg into wire-like Header.
|
// Convert convenient Msg into wire-like Header.
|
||||||
|
var dh Header
|
||||||
dh.Id = dns.Id
|
dh.Id = dns.Id
|
||||||
dh.Bits = uint16(dns.Opcode)<<11 | uint16(dns.Rcode)
|
dh.Bits = uint16(dns.Opcode)<<11 | uint16(dns.Rcode&0xF)
|
||||||
if dns.Response {
|
if dns.Response {
|
||||||
dh.Bits |= _QR
|
dh.Bits |= _QR
|
||||||
}
|
}
|
||||||
|
@ -738,50 +810,44 @@ func (dns *Msg) PackBuffer(buf []byte) (msg []byte, err error) {
|
||||||
dh.Bits |= _CD
|
dh.Bits |= _CD
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare variable sized arrays.
|
dh.Qdcount = uint16(len(dns.Question))
|
||||||
question := dns.Question
|
dh.Ancount = uint16(len(dns.Answer))
|
||||||
answer := dns.Answer
|
dh.Nscount = uint16(len(dns.Ns))
|
||||||
ns := dns.Ns
|
dh.Arcount = uint16(len(dns.Extra))
|
||||||
extra := dns.Extra
|
|
||||||
|
|
||||||
dh.Qdcount = uint16(len(question))
|
|
||||||
dh.Ancount = uint16(len(answer))
|
|
||||||
dh.Nscount = uint16(len(ns))
|
|
||||||
dh.Arcount = uint16(len(extra))
|
|
||||||
|
|
||||||
// We need the uncompressed length here, because we first pack it and then compress it.
|
// We need the uncompressed length here, because we first pack it and then compress it.
|
||||||
msg = buf
|
msg = buf
|
||||||
uncompressedLen := compressedLen(dns, false)
|
uncompressedLen := msgLenWithCompressionMap(dns, nil)
|
||||||
if packLen := uncompressedLen + 1; len(msg) < packLen {
|
if packLen := uncompressedLen + 1; len(msg) < packLen {
|
||||||
msg = make([]byte, packLen)
|
msg = make([]byte, packLen)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pack it in: header and then the pieces.
|
// Pack it in: header and then the pieces.
|
||||||
off := 0
|
off := 0
|
||||||
off, err = dh.pack(msg, off, compression, dns.Compress)
|
off, err = dh.pack(msg, off, compression, compress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for i := 0; i < len(question); i++ {
|
for _, r := range dns.Question {
|
||||||
off, err = question[i].pack(msg, off, compression, dns.Compress)
|
off, err = r.pack(msg, off, compression, compress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := 0; i < len(answer); i++ {
|
for _, r := range dns.Answer {
|
||||||
off, err = PackRR(answer[i], msg, off, compression, dns.Compress)
|
_, off, err = packRR(r, msg, off, compression, compress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := 0; i < len(ns); i++ {
|
for _, r := range dns.Ns {
|
||||||
off, err = PackRR(ns[i], msg, off, compression, dns.Compress)
|
_, off, err = packRR(r, msg, off, compression, compress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := 0; i < len(extra); i++ {
|
for _, r := range dns.Extra {
|
||||||
off, err = PackRR(extra[i], msg, off, compression, dns.Compress)
|
_, off, err = packRR(r, msg, off, compression, compress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -789,28 +855,7 @@ func (dns *Msg) PackBuffer(buf []byte) (msg []byte, err error) {
|
||||||
return msg[:off], nil
|
return msg[:off], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unpack unpacks a binary message to a Msg structure.
|
func (dns *Msg) unpack(dh Header, msg []byte, off int) (err error) {
|
||||||
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)
|
|
||||||
|
|
||||||
// If we are at the end of the message we should return *just* the
|
// 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
|
// header. This can still be useful to the caller. 9.9.9.9 sends these
|
||||||
// when responding with REFUSED for instance.
|
// when responding with REFUSED for instance.
|
||||||
|
@ -829,8 +874,6 @@ func (dns *Msg) Unpack(msg []byte) (err error) {
|
||||||
var q Question
|
var q Question
|
||||||
q, off, err = unpackQuestion(msg, off)
|
q, off, err = unpackQuestion(msg, off)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Even if Truncated is set, we only will set ErrTruncated if we
|
|
||||||
// actually got the questions
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if off1 == off { // Offset does not increase anymore, dh.Qdcount is a lie!
|
if off1 == off { // Offset does not increase anymore, dh.Qdcount is a lie!
|
||||||
|
@ -854,16 +897,29 @@ func (dns *Msg) Unpack(msg []byte) (err error) {
|
||||||
// The header counts might have been wrong so we need to update it
|
// The header counts might have been wrong so we need to update it
|
||||||
dh.Arcount = uint16(len(dns.Extra))
|
dh.Arcount = uint16(len(dns.Extra))
|
||||||
|
|
||||||
|
// Set extended Rcode
|
||||||
|
if opt := dns.IsEdns0(); opt != nil {
|
||||||
|
dns.Rcode |= opt.ExtendedRcode()
|
||||||
|
}
|
||||||
|
|
||||||
if off != len(msg) {
|
if off != len(msg) {
|
||||||
// TODO(miek) make this an error?
|
// TODO(miek) make this an error?
|
||||||
// use PackOpt to let people tell how detailed the error reporting should be?
|
// use PackOpt to let people tell how detailed the error reporting should be?
|
||||||
// println("dns: extra bytes in dns packet", off, "<", len(msg))
|
// 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
|
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.
|
// Convert a complete message to a string with dig-like output.
|
||||||
|
@ -909,107 +965,117 @@ func (dns *Msg) String() string {
|
||||||
return s
|
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.
|
// Len returns the message length when in (un)compressed wire format.
|
||||||
// If dns.Compress is true compression it is taken into account. Len()
|
// 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,
|
// 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.
|
// than packing it, measuring the size and discarding the buffer.
|
||||||
func (dns *Msg) Len() int { return compressedLen(dns, dns.Compress) }
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
// compressedLen returns the message length when in compressed wire format
|
return msgLenWithCompressionMap(dns, nil)
|
||||||
// when compress is true, otherwise the uncompressed length is returned.
|
}
|
||||||
func compressedLen(dns *Msg, compress bool) int {
|
|
||||||
// We always return one more than needed.
|
func msgLenWithCompressionMap(dns *Msg, compression map[string]struct{}) int {
|
||||||
l := 12 // Message header is always 12 bytes
|
l := headerSize
|
||||||
if compress {
|
|
||||||
compression := map[string]int{}
|
for _, r := range dns.Question {
|
||||||
for _, r := range dns.Question {
|
l += r.len(l, compression)
|
||||||
l += r.len()
|
}
|
||||||
compressionLenHelper(compression, r.Name)
|
for _, r := range dns.Answer {
|
||||||
}
|
if r != nil {
|
||||||
l += compressionLenSlice(compression, dns.Answer)
|
l += r.len(l, compression)
|
||||||
l += compressionLenSlice(compression, dns.Ns)
|
|
||||||
l += compressionLenSlice(compression, dns.Extra)
|
|
||||||
} else {
|
|
||||||
for _, r := range dns.Question {
|
|
||||||
l += r.len()
|
|
||||||
}
|
|
||||||
for _, r := range dns.Answer {
|
|
||||||
if r != nil {
|
|
||||||
l += r.len()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, r := range dns.Ns {
|
|
||||||
if r != nil {
|
|
||||||
l += r.len()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, r := range dns.Extra {
|
|
||||||
if r != nil {
|
|
||||||
l += r.len()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for _, r := range dns.Ns {
|
||||||
|
if r != nil {
|
||||||
|
l += r.len(l, compression)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, r := range dns.Extra {
|
||||||
|
if r != nil {
|
||||||
|
l += r.len(l, compression)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
func compressionLenSlice(c map[string]int, rs []RR) int {
|
func domainNameLen(s string, off int, compression map[string]struct{}, compress bool) int {
|
||||||
var l int
|
if s == "" || s == "." {
|
||||||
for _, r := range rs {
|
return 1
|
||||||
if r == nil {
|
}
|
||||||
|
|
||||||
|
escaped := strings.Contains(s, "\\")
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if escaped {
|
||||||
|
return escapedNameLen(s) + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return len(s) + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func escapedNameLen(s string) int {
|
||||||
|
nameLen := len(s)
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
if s[i] != '\\' {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
l += r.len()
|
|
||||||
k, ok := compressionLenSearch(c, r.Header().Name)
|
if i+3 < len(s) && isDigit(s[i+1]) && isDigit(s[i+2]) && isDigit(s[i+3]) {
|
||||||
if ok {
|
nameLen -= 3
|
||||||
l += 1 - k
|
i += 3
|
||||||
|
} else {
|
||||||
|
nameLen--
|
||||||
|
i++
|
||||||
}
|
}
|
||||||
compressionLenHelper(c, r.Header().Name)
|
|
||||||
k, ok = compressionLenSearchType(c, r)
|
|
||||||
if ok {
|
|
||||||
l += 1 - k
|
|
||||||
}
|
|
||||||
compressionLenHelperType(c, r)
|
|
||||||
}
|
}
|
||||||
return l
|
|
||||||
|
return nameLen
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put the parts of the name in the compression map.
|
func compressionLenSearch(c map[string]struct{}, s string, msgOff int) (int, bool) {
|
||||||
func compressionLenHelper(c map[string]int, s string) {
|
for off, end := 0, false; !end; off, end = NextLabel(s, off) {
|
||||||
pref := ""
|
|
||||||
lbs := Split(s)
|
|
||||||
for j := len(lbs) - 1; j >= 0; j-- {
|
|
||||||
pref = s[lbs[j]:]
|
|
||||||
if _, ok := c[pref]; !ok {
|
|
||||||
c[pref] = len(pref)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look for each part in the compression map and returns its length,
|
|
||||||
// keep on searching so we get the longest match.
|
|
||||||
func compressionLenSearch(c map[string]int, s string) (int, bool) {
|
|
||||||
off := 0
|
|
||||||
end := false
|
|
||||||
if s == "" { // don't bork on bogus data
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
for {
|
|
||||||
if _, ok := c[s[off:]]; ok {
|
if _, ok := c[s[off:]]; ok {
|
||||||
return len(s[off:]), true
|
return off, true
|
||||||
}
|
}
|
||||||
if end {
|
|
||||||
break
|
if msgOff+off < maxCompressionOffset {
|
||||||
|
c[s[off:]] = struct{}{}
|
||||||
}
|
}
|
||||||
off, end = NextLabel(s, off)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy returns a new RR which is a deep-copy of r.
|
// 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.
|
// 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.
|
// Copy returns a new *Msg which is a deep-copy of dns.
|
||||||
func (dns *Msg) Copy() *Msg { return dns.CopyTo(new(Msg)) }
|
func (dns *Msg) Copy() *Msg { return dns.CopyTo(new(Msg)) }
|
||||||
|
@ -1057,8 +1123,8 @@ func (dns *Msg) CopyTo(r1 *Msg) *Msg {
|
||||||
return r1
|
return r1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Question) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
|
func (q *Question) pack(msg []byte, off int, compression compressionMap, compress bool) (int, error) {
|
||||||
off, err := PackDomainName(q.Name, msg, off, compression, compress)
|
off, err := packDomainName(q.Name, msg, off, compression, compress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return off, err
|
return off, err
|
||||||
}
|
}
|
||||||
|
@ -1099,7 +1165,7 @@ func unpackQuestion(msg []byte, off int) (Question, int, error) {
|
||||||
return q, off, err
|
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)
|
off, err := packUint16(dh.Id, msg, off)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return off, err
|
return off, err
|
||||||
|
@ -1121,7 +1187,10 @@ func (dh *Header) pack(msg []byte, off int, compression map[string]int, compress
|
||||||
return off, err
|
return off, err
|
||||||
}
|
}
|
||||||
off, err = packUint16(dh.Arcount, msg, off)
|
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) {
|
func unpackMsgHdr(msg []byte, off int) (Header, int, error) {
|
||||||
|
@ -1150,5 +1219,23 @@ func unpackMsgHdr(msg []byte, off int) (Header, int, error) {
|
||||||
return dh, off, err
|
return dh, off, err
|
||||||
}
|
}
|
||||||
dh.Arcount, off, err = unpackUint16(msg, off)
|
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)
|
||||||
}
|
}
|
||||||
|
|
48
vendor/github.com/miekg/dns/msg_generate.go
generated
vendored
48
vendor/github.com/miekg/dns/msg_generate.go
generated
vendored
|
@ -80,13 +80,7 @@ func main() {
|
||||||
o := scope.Lookup(name)
|
o := scope.Lookup(name)
|
||||||
st, _ := getTypeStruct(o.Type(), scope)
|
st, _ := getTypeStruct(o.Type(), scope)
|
||||||
|
|
||||||
fmt.Fprintf(b, "func (rr *%s) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {\n", name)
|
fmt.Fprintf(b, "func (rr *%s) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {\n", name)
|
||||||
fmt.Fprint(b, `off, err := rr.Hdr.pack(msg, off, compression, compress)
|
|
||||||
if err != nil {
|
|
||||||
return off, err
|
|
||||||
}
|
|
||||||
headerEnd := off
|
|
||||||
`)
|
|
||||||
for i := 1; i < st.NumFields(); i++ {
|
for i := 1; i < st.NumFields(); i++ {
|
||||||
o := func(s string) {
|
o := func(s string) {
|
||||||
fmt.Fprintf(b, s, st.Field(i).Name())
|
fmt.Fprintf(b, s, st.Field(i).Name())
|
||||||
|
@ -106,7 +100,7 @@ return off, err
|
||||||
case `dns:"nsec"`:
|
case `dns:"nsec"`:
|
||||||
o("off, err = packDataNsec(rr.%s, msg, off)\n")
|
o("off, err = packDataNsec(rr.%s, msg, off)\n")
|
||||||
case `dns:"domain-name"`:
|
case `dns:"domain-name"`:
|
||||||
o("off, err = packDataDomainNames(rr.%s, msg, off, compression, compress)\n")
|
o("off, err = packDataDomainNames(rr.%s, msg, off, compression, false)\n")
|
||||||
default:
|
default:
|
||||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||||
}
|
}
|
||||||
|
@ -116,9 +110,9 @@ return off, err
|
||||||
switch {
|
switch {
|
||||||
case st.Tag(i) == `dns:"-"`: // ignored
|
case st.Tag(i) == `dns:"-"`: // ignored
|
||||||
case st.Tag(i) == `dns:"cdomain-name"`:
|
case st.Tag(i) == `dns:"cdomain-name"`:
|
||||||
o("off, err = PackDomainName(rr.%s, msg, off, compression, compress)\n")
|
o("off, err = packDomainName(rr.%s, msg, off, compression, compress)\n")
|
||||||
case st.Tag(i) == `dns:"domain-name"`:
|
case st.Tag(i) == `dns:"domain-name"`:
|
||||||
o("off, err = PackDomainName(rr.%s, msg, off, compression, false)\n")
|
o("off, err = packDomainName(rr.%s, msg, off, compression, false)\n")
|
||||||
case st.Tag(i) == `dns:"a"`:
|
case st.Tag(i) == `dns:"a"`:
|
||||||
o("off, err = packDataA(rr.%s, msg, off)\n")
|
o("off, err = packDataA(rr.%s, msg, off)\n")
|
||||||
case st.Tag(i) == `dns:"aaaa"`:
|
case st.Tag(i) == `dns:"aaaa"`:
|
||||||
|
@ -154,7 +148,8 @@ if rr.%s != "-" {
|
||||||
fallthrough
|
fallthrough
|
||||||
case st.Tag(i) == `dns:"hex"`:
|
case st.Tag(i) == `dns:"hex"`:
|
||||||
o("off, err = packStringHex(rr.%s, msg, off)\n")
|
o("off, err = packStringHex(rr.%s, msg, off)\n")
|
||||||
|
case st.Tag(i) == `dns:"any"`:
|
||||||
|
o("off, err = packStringAny(rr.%s, msg, off)\n")
|
||||||
case st.Tag(i) == `dns:"octet"`:
|
case st.Tag(i) == `dns:"octet"`:
|
||||||
o("off, err = packStringOctet(rr.%s, msg, off)\n")
|
o("off, err = packStringOctet(rr.%s, msg, off)\n")
|
||||||
case st.Tag(i) == "":
|
case st.Tag(i) == "":
|
||||||
|
@ -176,8 +171,6 @@ if rr.%s != "-" {
|
||||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// We have packed everything, only now we know the rdlength of this RR
|
|
||||||
fmt.Fprintln(b, "rr.Header().Rdlength = uint16(off-headerEnd)")
|
|
||||||
fmt.Fprintln(b, "return off, nil }\n")
|
fmt.Fprintln(b, "return off, nil }\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,14 +179,8 @@ if rr.%s != "-" {
|
||||||
o := scope.Lookup(name)
|
o := scope.Lookup(name)
|
||||||
st, _ := getTypeStruct(o.Type(), scope)
|
st, _ := getTypeStruct(o.Type(), scope)
|
||||||
|
|
||||||
fmt.Fprintf(b, "func unpack%s(h RR_Header, msg []byte, off int) (RR, int, error) {\n", name)
|
fmt.Fprintf(b, "func (rr *%s) unpack(msg []byte, off int) (off1 int, err error) {\n", name)
|
||||||
fmt.Fprintf(b, "rr := new(%s)\n", name)
|
fmt.Fprint(b, `rdStart := off
|
||||||
fmt.Fprint(b, "rr.Hdr = h\n")
|
|
||||||
fmt.Fprint(b, `if noRdata(h) {
|
|
||||||
return rr, off, nil
|
|
||||||
}
|
|
||||||
var err error
|
|
||||||
rdStart := off
|
|
||||||
_ = rdStart
|
_ = rdStart
|
||||||
|
|
||||||
`)
|
`)
|
||||||
|
@ -201,7 +188,7 @@ _ = rdStart
|
||||||
o := func(s string) {
|
o := func(s string) {
|
||||||
fmt.Fprintf(b, s, st.Field(i).Name())
|
fmt.Fprintf(b, s, st.Field(i).Name())
|
||||||
fmt.Fprint(b, `if err != nil {
|
fmt.Fprint(b, `if err != nil {
|
||||||
return rr, off, err
|
return off, err
|
||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
@ -221,7 +208,7 @@ return rr, off, err
|
||||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||||
}
|
}
|
||||||
fmt.Fprint(b, `if err != nil {
|
fmt.Fprint(b, `if err != nil {
|
||||||
return rr, off, err
|
return off, err
|
||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
continue
|
continue
|
||||||
|
@ -264,6 +251,8 @@ return rr, off, err
|
||||||
o("rr.%s, off, err = unpackStringBase64(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
|
o("rr.%s, off, err = unpackStringBase64(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
|
||||||
case `dns:"hex"`:
|
case `dns:"hex"`:
|
||||||
o("rr.%s, off, err = unpackStringHex(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
|
o("rr.%s, off, err = unpackStringHex(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
|
||||||
|
case `dns:"any"`:
|
||||||
|
o("rr.%s, off, err = unpackStringAny(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
|
||||||
case `dns:"octet"`:
|
case `dns:"octet"`:
|
||||||
o("rr.%s, off, err = unpackStringOctet(msg, off)\n")
|
o("rr.%s, off, err = unpackStringOctet(msg, off)\n")
|
||||||
case "":
|
case "":
|
||||||
|
@ -287,22 +276,13 @@ return rr, off, err
|
||||||
// If we've hit len(msg) we return without error.
|
// If we've hit len(msg) we return without error.
|
||||||
if i < st.NumFields()-1 {
|
if i < st.NumFields()-1 {
|
||||||
fmt.Fprintf(b, `if off == len(msg) {
|
fmt.Fprintf(b, `if off == len(msg) {
|
||||||
return rr, off, nil
|
return off, nil
|
||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Fprintf(b, "return rr, off, err }\n\n")
|
fmt.Fprintf(b, "return off, nil }\n\n")
|
||||||
}
|
}
|
||||||
// Generate typeToUnpack map
|
|
||||||
fmt.Fprintln(b, "var typeToUnpack = map[uint16]func(RR_Header, []byte, int) (RR, int, error){")
|
|
||||||
for _, name := range namedTypes {
|
|
||||||
if name == "RFC3597" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fmt.Fprintf(b, "Type%s: unpack%s,\n", name, name)
|
|
||||||
}
|
|
||||||
fmt.Fprintln(b, "}\n")
|
|
||||||
|
|
||||||
// gofmt
|
// gofmt
|
||||||
res, err := format.Source(b.Bytes())
|
res, err := format.Source(b.Bytes())
|
||||||
|
|
82
vendor/github.com/miekg/dns/msg_helpers.go
generated
vendored
82
vendor/github.com/miekg/dns/msg_helpers.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// helper functions called from the generated zmsg.go
|
// helper functions called from the generated zmsg.go
|
||||||
|
@ -99,14 +99,14 @@ func unpackHeader(msg []byte, off int) (rr RR_Header, off1 int, truncmsg []byte,
|
||||||
return hdr, off, msg, err
|
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.
|
// 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) {
|
if off == len(msg) {
|
||||||
return off, nil
|
return off, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
off, err = PackDomainName(hdr.Name, msg, off, compression, compress)
|
off, err := packDomainName(hdr.Name, msg, off, compression, compress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return len(msg), err
|
return len(msg), err
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,7 @@ func (hdr RR_Header) pack(msg []byte, off int, compression map[string]int, compr
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return len(msg), err
|
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 {
|
if err != nil {
|
||||||
return len(msg), err
|
return len(msg), err
|
||||||
}
|
}
|
||||||
|
@ -141,20 +141,24 @@ func truncateMsgFromRdlength(msg []byte, off int, rdlength uint16) (truncmsg []b
|
||||||
return msg[:lenrd], nil
|
return msg[:lenrd], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var base32HexNoPadEncoding = base32.HexEncoding.WithPadding(base32.NoPadding)
|
||||||
|
|
||||||
func fromBase32(s []byte) (buf []byte, err error) {
|
func fromBase32(s []byte) (buf []byte, err error) {
|
||||||
for i, b := range s {
|
for i, b := range s {
|
||||||
if b >= 'a' && b <= 'z' {
|
if b >= 'a' && b <= 'z' {
|
||||||
s[i] = b - 32
|
s[i] = b - 32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buflen := base32.HexEncoding.DecodedLen(len(s))
|
buflen := base32HexNoPadEncoding.DecodedLen(len(s))
|
||||||
buf = make([]byte, buflen)
|
buf = make([]byte, buflen)
|
||||||
n, err := base32.HexEncoding.Decode(buf, s)
|
n, err := base32HexNoPadEncoding.Decode(buf, s)
|
||||||
buf = buf[:n]
|
buf = buf[:n]
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func toBase32(b []byte) string { return base32.HexEncoding.EncodeToString(b) }
|
func toBase32(b []byte) string {
|
||||||
|
return base32HexNoPadEncoding.EncodeToString(b)
|
||||||
|
}
|
||||||
|
|
||||||
func fromBase64(s []byte) (buf []byte, err error) {
|
func fromBase64(s []byte) (buf []byte, err error) {
|
||||||
buflen := base64.StdEncoding.DecodedLen(len(s))
|
buflen := base64.StdEncoding.DecodedLen(len(s))
|
||||||
|
@ -173,14 +177,14 @@ func unpackUint8(msg []byte, off int) (i uint8, off1 int, err error) {
|
||||||
if off+1 > len(msg) {
|
if off+1 > len(msg) {
|
||||||
return 0, len(msg), &Error{err: "overflow unpacking uint8"}
|
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) {
|
func packUint8(i uint8, msg []byte, off int) (off1 int, err error) {
|
||||||
if off+1 > len(msg) {
|
if off+1 > len(msg) {
|
||||||
return len(msg), &Error{err: "overflow packing uint8"}
|
return len(msg), &Error{err: "overflow packing uint8"}
|
||||||
}
|
}
|
||||||
msg[off] = byte(i)
|
msg[off] = i
|
||||||
return off + 1, nil
|
return off + 1, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,8 +223,8 @@ func unpackUint48(msg []byte, off int) (i uint64, off1 int, err error) {
|
||||||
return 0, len(msg), &Error{err: "overflow unpacking uint64 as uint48"}
|
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)
|
// 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 |
|
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])))
|
uint64(msg[off+4])<<8 | uint64(msg[off+5])
|
||||||
off += 6
|
off += 6
|
||||||
return i, off, nil
|
return i, off, nil
|
||||||
}
|
}
|
||||||
|
@ -263,29 +267,21 @@ func unpackString(msg []byte, off int) (string, int, error) {
|
||||||
if off+l+1 > len(msg) {
|
if off+l+1 > len(msg) {
|
||||||
return "", off, &Error{err: "overflow unpacking txt"}
|
return "", off, &Error{err: "overflow unpacking txt"}
|
||||||
}
|
}
|
||||||
s := make([]byte, 0, l)
|
var s strings.Builder
|
||||||
|
s.Grow(l)
|
||||||
for _, b := range msg[off+1 : off+1+l] {
|
for _, b := range msg[off+1 : off+1+l] {
|
||||||
switch b {
|
switch {
|
||||||
case '"', '\\':
|
case b == '"' || b == '\\':
|
||||||
s = append(s, '\\', b)
|
s.WriteByte('\\')
|
||||||
|
s.WriteByte(b)
|
||||||
|
case b < ' ' || b > '~': // unprintable
|
||||||
|
s.WriteString(escapeByte(b))
|
||||||
default:
|
default:
|
||||||
if b < 32 || b > 127 { // unprintable
|
s.WriteByte(b)
|
||||||
var buf [3]byte
|
|
||||||
bufs := strconv.AppendInt(buf[:0], int64(b), 10)
|
|
||||||
s = append(s, '\\')
|
|
||||||
for i := 0; i < 3-len(bufs); i++ {
|
|
||||||
s = append(s, '0')
|
|
||||||
}
|
|
||||||
for _, r := range bufs {
|
|
||||||
s = append(s, r)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
s = append(s, b)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
off += 1 + l
|
off += 1 + l
|
||||||
return string(s), off, nil
|
return s.String(), off, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func packString(s string, msg []byte, off int) (int, error) {
|
func packString(s string, msg []byte, off int) (int, error) {
|
||||||
|
@ -359,7 +355,7 @@ func packStringHex(s string, msg []byte, off int) (int, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return len(msg), err
|
return len(msg), err
|
||||||
}
|
}
|
||||||
if off+(len(h)) > len(msg) {
|
if off+len(h) > len(msg) {
|
||||||
return len(msg), &Error{err: "overflow packing hex"}
|
return len(msg), &Error{err: "overflow packing hex"}
|
||||||
}
|
}
|
||||||
copy(msg[off:off+len(h)], h)
|
copy(msg[off:off+len(h)], h)
|
||||||
|
@ -367,6 +363,22 @@ func packStringHex(s string, msg []byte, off int) (int, error) {
|
||||||
return off, nil
|
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) {
|
func unpackStringTxt(msg []byte, off int) ([]string, int, error) {
|
||||||
txt, off, err := unpackTxt(msg, off)
|
txt, off, err := unpackTxt(msg, off)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -387,7 +399,7 @@ func packStringTxt(s []string, msg []byte, off int) (int, error) {
|
||||||
func unpackDataOpt(msg []byte, off int) ([]EDNS0, int, error) {
|
func unpackDataOpt(msg []byte, off int) ([]EDNS0, int, error) {
|
||||||
var edns []EDNS0
|
var edns []EDNS0
|
||||||
Option:
|
Option:
|
||||||
code := uint16(0)
|
var code uint16
|
||||||
if off+4 > len(msg) {
|
if off+4 > len(msg) {
|
||||||
return nil, len(msg), &Error{err: "overflow unpacking opt"}
|
return nil, len(msg), &Error{err: "overflow unpacking opt"}
|
||||||
}
|
}
|
||||||
|
@ -599,7 +611,7 @@ func packDataNsec(bitmap []uint16, msg []byte, off int) (int, error) {
|
||||||
// Setting the octets length
|
// Setting the octets length
|
||||||
msg[off+1] = byte(length)
|
msg[off+1] = byte(length)
|
||||||
// Setting the bit value for the type in the right octet
|
// Setting the bit value for the type in the right octet
|
||||||
msg[off+1+int(length)] |= byte(1 << (7 - (t % 8)))
|
msg[off+1+int(length)] |= byte(1 << (7 - t%8))
|
||||||
lastwindow, lastlength = window, length
|
lastwindow, lastlength = window, length
|
||||||
}
|
}
|
||||||
off += int(lastlength) + 2
|
off += int(lastlength) + 2
|
||||||
|
@ -625,10 +637,10 @@ func unpackDataDomainNames(msg []byte, off, end int) ([]string, int, error) {
|
||||||
return servers, off, nil
|
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
|
var err error
|
||||||
for j := 0; j < len(names); j++ {
|
for j := 0; j < len(names); j++ {
|
||||||
off, err = PackDomainName(names[j], msg, off, compression, false && compress)
|
off, err = packDomainName(names[j], msg, off, compression, compress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return len(msg), err
|
return len(msg), err
|
||||||
}
|
}
|
||||||
|
|
47
vendor/github.com/miekg/dns/nsecx.go
generated
vendored
47
vendor/github.com/miekg/dns/nsecx.go
generated
vendored
|
@ -2,49 +2,44 @@ package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"hash"
|
"encoding/hex"
|
||||||
"strings"
|
"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.
|
// 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 {
|
func HashName(label string, ha uint8, iter uint16, salt string) string {
|
||||||
saltwire := new(saltWireFmt)
|
if ha != SHA1 {
|
||||||
saltwire.Salt = salt
|
return ""
|
||||||
wire := make([]byte, DefaultMsgSize)
|
}
|
||||||
n, err := packSaltWire(saltwire, wire)
|
|
||||||
|
wireSalt := make([]byte, hex.DecodedLen(len(salt)))
|
||||||
|
n, err := packStringHex(salt, wireSalt, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
wire = wire[:n]
|
wireSalt = wireSalt[:n]
|
||||||
|
|
||||||
name := make([]byte, 255)
|
name := make([]byte, 255)
|
||||||
off, err := PackDomainName(strings.ToLower(label), name, 0, nil, false)
|
off, err := PackDomainName(strings.ToLower(label), name, 0, nil, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
name = name[:off]
|
name = name[:off]
|
||||||
var s hash.Hash
|
|
||||||
switch ha {
|
|
||||||
case SHA1:
|
|
||||||
s = sha1.New()
|
|
||||||
default:
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
|
s := sha1.New()
|
||||||
// k = 0
|
// k = 0
|
||||||
s.Write(name)
|
s.Write(name)
|
||||||
s.Write(wire)
|
s.Write(wireSalt)
|
||||||
nsec3 := s.Sum(nil)
|
nsec3 := s.Sum(nil)
|
||||||
|
|
||||||
// k > 0
|
// k > 0
|
||||||
for k := uint16(0); k < iter; k++ {
|
for k := uint16(0); k < iter; k++ {
|
||||||
s.Reset()
|
s.Reset()
|
||||||
s.Write(nsec3)
|
s.Write(nsec3)
|
||||||
s.Write(wire)
|
s.Write(wireSalt)
|
||||||
nsec3 = s.Sum(nsec3[:0])
|
nsec3 = s.Sum(nsec3[:0])
|
||||||
}
|
}
|
||||||
|
|
||||||
return toBase32(nsec3)
|
return toBase32(nsec3)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,8 +58,10 @@ func (rr *NSEC3) Cover(name string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
nextHash := rr.NextDomain
|
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 ownerHash > nextHash { // end of zone
|
||||||
if nameHash > ownerHash { // covered since there is nothing after ownerHash
|
if nameHash > ownerHash { // covered since there is nothing after ownerHash
|
||||||
|
@ -96,11 +93,3 @@ func (rr *NSEC3) Match(name string) bool {
|
||||||
}
|
}
|
||||||
return false
|
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
|
|
||||||
}
|
|
||||||
|
|
109
vendor/github.com/miekg/dns/privaterr.go
generated
vendored
109
vendor/github.com/miekg/dns/privaterr.go
generated
vendored
|
@ -39,11 +39,12 @@ func mkPrivateRR(rrtype uint16) *PrivateRR {
|
||||||
}
|
}
|
||||||
|
|
||||||
anyrr := rrfunc()
|
anyrr := rrfunc()
|
||||||
switch rr := anyrr.(type) {
|
rr, ok := anyrr.(*PrivateRR)
|
||||||
case *PrivateRR:
|
if !ok {
|
||||||
return rr
|
panic(fmt.Sprintf("dns: RR is not a PrivateRR, TypeToRR[%d] generator returned %T", rrtype, anyrr))
|
||||||
}
|
}
|
||||||
panic(fmt.Sprintf("dns: RR is not a PrivateRR, TypeToRR[%d] generator returned %T", rrtype, anyrr))
|
|
||||||
|
return rr
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header return the RR header of r.
|
// Header return the RR header of r.
|
||||||
|
@ -52,12 +53,16 @@ func (r *PrivateRR) Header() *RR_Header { return &r.Hdr }
|
||||||
func (r *PrivateRR) String() string { return r.Hdr.String() + r.Data.String() }
|
func (r *PrivateRR) String() string { return r.Hdr.String() + r.Data.String() }
|
||||||
|
|
||||||
// Private len and copy parts to satisfy RR interface.
|
// 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 {
|
func (r *PrivateRR) copy() RR {
|
||||||
// make new RR like this:
|
// make new RR like this:
|
||||||
rr := mkPrivateRR(r.Hdr.Rrtype)
|
rr := mkPrivateRR(r.Hdr.Rrtype)
|
||||||
newh := r.Hdr.copyHeader()
|
rr.Hdr = r.Hdr
|
||||||
rr.Hdr = *newh
|
|
||||||
|
|
||||||
err := r.Data.Copy(rr.Data)
|
err := r.Data.Copy(rr.Data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -65,21 +70,47 @@ func (r *PrivateRR) copy() RR {
|
||||||
}
|
}
|
||||||
return rr
|
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)
|
func (r *PrivateRR) pack(msg []byte, off int, compression compressionMap, compress bool) (int, error) {
|
||||||
if err != nil {
|
|
||||||
return off, err
|
|
||||||
}
|
|
||||||
headerEnd := off
|
|
||||||
n, err := r.Data.Pack(msg[off:])
|
n, err := r.Data.Pack(msg[off:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return len(msg), err
|
return len(msg), err
|
||||||
}
|
}
|
||||||
off += n
|
off += n
|
||||||
r.Header().Rdlength = uint16(off - headerEnd)
|
|
||||||
return off, nil
|
return off, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *PrivateRR) unpack(msg []byte, off int) (int, error) {
|
||||||
|
off1, err := r.Data.Unpack(msg[off:])
|
||||||
|
off += off1
|
||||||
|
return off, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *PrivateRR) parse(c *zlexer, origin, file 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err := r.Data.Parse(text)
|
||||||
|
if err != nil {
|
||||||
|
return &ParseError{file, err.Error(), l}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r1 *PrivateRR) isDuplicate(r2 RR) bool { return false }
|
||||||
|
|
||||||
// PrivateHandle registers a private resource record type. It requires
|
// PrivateHandle registers a private resource record type. It requires
|
||||||
// string and numeric representation of private RR type and generator function as argument.
|
// string and numeric representation of private RR type and generator function as argument.
|
||||||
func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata) {
|
func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata) {
|
||||||
|
@ -88,62 +119,14 @@ func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata)
|
||||||
TypeToRR[rtype] = func() RR { return &PrivateRR{RR_Header{}, generator()} }
|
TypeToRR[rtype] = func() RR { return &PrivateRR{RR_Header{}, generator()} }
|
||||||
TypeToString[rtype] = rtypestr
|
TypeToString[rtype] = rtypestr
|
||||||
StringToType[rtypestr] = rtype
|
StringToType[rtypestr] = rtype
|
||||||
|
|
||||||
typeToUnpack[rtype] = func(h RR_Header, msg []byte, off int) (RR, int, error) {
|
|
||||||
if noRdata(h) {
|
|
||||||
return &h, off, nil
|
|
||||||
}
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
setPrivateRR := func(h RR_Header, c chan lex, 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; l.value {
|
|
||||||
case zNewline, zEOF:
|
|
||||||
break Fetch
|
|
||||||
case zString:
|
|
||||||
text = append(text, l.token)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err := rr.Data.Parse(text)
|
|
||||||
if err != nil {
|
|
||||||
return nil, &ParseError{f, err.Error(), l}, ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return rr, nil, ""
|
|
||||||
}
|
|
||||||
|
|
||||||
typeToparserFunc[rtype] = parserFunc{setPrivateRR, true}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrivateHandleRemove removes defenitions required to support private RR type.
|
// PrivateHandleRemove removes definitions required to support private RR type.
|
||||||
func PrivateHandleRemove(rtype uint16) {
|
func PrivateHandleRemove(rtype uint16) {
|
||||||
rtypestr, ok := TypeToString[rtype]
|
rtypestr, ok := TypeToString[rtype]
|
||||||
if ok {
|
if ok {
|
||||||
delete(TypeToRR, rtype)
|
delete(TypeToRR, rtype)
|
||||||
delete(TypeToString, rtype)
|
delete(TypeToString, rtype)
|
||||||
delete(typeToparserFunc, rtype)
|
|
||||||
delete(StringToType, rtypestr)
|
delete(StringToType, rtypestr)
|
||||||
delete(typeToUnpack, rtype)
|
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
49
vendor/github.com/miekg/dns/rawmsg.go
generated
vendored
49
vendor/github.com/miekg/dns/rawmsg.go
generated
vendored
|
@ -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
|
|
||||||
}
|
|
14
vendor/github.com/miekg/dns/reverse.go
generated
vendored
14
vendor/github.com/miekg/dns/reverse.go
generated
vendored
|
@ -12,6 +12,20 @@ var StringToOpcode = reverseInt(OpcodeToString)
|
||||||
// StringToRcode is a map of rcodes to strings.
|
// StringToRcode is a map of rcodes to strings.
|
||||||
var StringToRcode = reverseInt(RcodeToString)
|
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
|
// Reverse a map
|
||||||
func reverseInt8(m map[uint8]string) map[string]uint8 {
|
func reverseInt8(m map[uint8]string) map[string]uint8 {
|
||||||
n := make(map[string]uint8, len(m))
|
n := make(map[string]uint8, len(m))
|
||||||
|
|
8
vendor/github.com/miekg/dns/sanitize.go
generated
vendored
8
vendor/github.com/miekg/dns/sanitize.go
generated
vendored
|
@ -5,6 +5,7 @@ package dns
|
||||||
// rrs.
|
// rrs.
|
||||||
// m is used to store the RRs temporary. If it is nil a new map will be allocated.
|
// m is used to store the RRs temporary. If it is nil a new map will be allocated.
|
||||||
func Dedup(rrs []RR, m map[string]RR) []RR {
|
func Dedup(rrs []RR, m map[string]RR) []RR {
|
||||||
|
|
||||||
if m == nil {
|
if m == nil {
|
||||||
m = make(map[string]RR)
|
m = make(map[string]RR)
|
||||||
}
|
}
|
||||||
|
@ -14,10 +15,11 @@ func Dedup(rrs []RR, m map[string]RR) []RR {
|
||||||
for _, r := range rrs {
|
for _, r := range rrs {
|
||||||
key := normalizedString(r)
|
key := normalizedString(r)
|
||||||
keys = append(keys, &key)
|
keys = append(keys, &key)
|
||||||
if _, ok := m[key]; ok {
|
if mr, ok := m[key]; ok {
|
||||||
// Shortest TTL wins.
|
// Shortest TTL wins.
|
||||||
if m[key].Header().Ttl > r.Header().Ttl {
|
rh, mrh := r.Header(), mr.Header()
|
||||||
m[key].Header().Ttl = r.Header().Ttl
|
if mrh.Ttl > rh.Ttl {
|
||||||
|
mrh.Ttl = rh.Ttl
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
1048
vendor/github.com/miekg/dns/scan.go
generated
vendored
1048
vendor/github.com/miekg/dns/scan.go
generated
vendored
File diff suppressed because it is too large
Load diff
1734
vendor/github.com/miekg/dns/scan_rr.go
generated
vendored
1734
vendor/github.com/miekg/dns/scan_rr.go
generated
vendored
File diff suppressed because it is too large
Load diff
56
vendor/github.com/miekg/dns/scanner.go
generated
vendored
56
vendor/github.com/miekg/dns/scanner.go
generated
vendored
|
@ -1,56 +0,0 @@
|
||||||
package dns
|
|
||||||
|
|
||||||
// Implement a simple scanner, return a byte stream from an io reader.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"context"
|
|
||||||
"io"
|
|
||||||
"text/scanner"
|
|
||||||
)
|
|
||||||
|
|
||||||
type scan struct {
|
|
||||||
src *bufio.Reader
|
|
||||||
position scanner.Position
|
|
||||||
eof bool // Have we just seen a eof
|
|
||||||
ctx context.Context
|
|
||||||
}
|
|
||||||
|
|
||||||
func scanInit(r io.Reader) (*scan, context.CancelFunc) {
|
|
||||||
s := new(scan)
|
|
||||||
s.src = bufio.NewReader(r)
|
|
||||||
s.position.Line = 1
|
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
s.ctx = ctx
|
|
||||||
|
|
||||||
return s, cancel
|
|
||||||
}
|
|
||||||
|
|
||||||
// tokenText returns the next byte from the input
|
|
||||||
func (s *scan) tokenText() (byte, error) {
|
|
||||||
c, err := s.src.ReadByte()
|
|
||||||
if err != nil {
|
|
||||||
return c, err
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
case <-s.ctx.Done():
|
|
||||||
return c, context.Canceled
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// delay the newline handling until the next token is delivered,
|
|
||||||
// fixes off-by-one errors when reporting a parse error.
|
|
||||||
if s.eof == true {
|
|
||||||
s.position.Line++
|
|
||||||
s.position.Column = 0
|
|
||||||
s.eof = false
|
|
||||||
}
|
|
||||||
if c == '\n' {
|
|
||||||
s.eof = true
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
s.position.Column++
|
|
||||||
return c, nil
|
|
||||||
}
|
|
147
vendor/github.com/miekg/dns/serve_mux.go
generated
vendored
Normal file
147
vendor/github.com/miekg/dns/serve_mux.go
generated
vendored
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
package dns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ServeMux is an DNS request multiplexer. It matches the zone name of
|
||||||
|
// each incoming request against a list of registered patterns add calls
|
||||||
|
// the handler for the pattern that most closely matches the zone name.
|
||||||
|
//
|
||||||
|
// ServeMux is DNSSEC aware, meaning that queries for the DS record are
|
||||||
|
// redirected to the parent zone (if that is also registered), otherwise
|
||||||
|
// the child gets the query.
|
||||||
|
//
|
||||||
|
// ServeMux is also safe for concurrent access from multiple goroutines.
|
||||||
|
//
|
||||||
|
// The zero ServeMux is empty and ready for use.
|
||||||
|
type ServeMux struct {
|
||||||
|
z map[string]Handler
|
||||||
|
m sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewServeMux allocates and returns a new ServeMux.
|
||||||
|
func NewServeMux() *ServeMux {
|
||||||
|
return new(ServeMux)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultServeMux is the default ServeMux used by Serve.
|
||||||
|
var DefaultServeMux = NewServeMux()
|
||||||
|
|
||||||
|
func (mux *ServeMux) match(q string, t uint16) Handler {
|
||||||
|
mux.m.RLock()
|
||||||
|
defer mux.m.RUnlock()
|
||||||
|
if mux.z == nil {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
for off, end := 0, false; !end; off, end = NextLabel(q, off) {
|
||||||
|
if h, ok := mux.z[q[off:]]; ok {
|
||||||
|
if t != TypeDS {
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
// Continue for DS to see if we have a parent too, if so delegate to the parent
|
||||||
|
handler = h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wildcard match, if we have found nothing try the root zone as a last resort.
|
||||||
|
if h, ok := mux.z["."]; ok {
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
return handler
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle adds a handler to the ServeMux for pattern.
|
||||||
|
func (mux *ServeMux) Handle(pattern string, handler Handler) {
|
||||||
|
if pattern == "" {
|
||||||
|
panic("dns: invalid pattern " + pattern)
|
||||||
|
}
|
||||||
|
mux.m.Lock()
|
||||||
|
if mux.z == nil {
|
||||||
|
mux.z = make(map[string]Handler)
|
||||||
|
}
|
||||||
|
mux.z[Fqdn(pattern)] = handler
|
||||||
|
mux.m.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleFunc adds a handler function to the ServeMux for pattern.
|
||||||
|
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) {
|
||||||
|
mux.Handle(pattern, HandlerFunc(handler))
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleRemove deregisters the handler specific for pattern from the ServeMux.
|
||||||
|
func (mux *ServeMux) HandleRemove(pattern string) {
|
||||||
|
if pattern == "" {
|
||||||
|
panic("dns: invalid pattern " + pattern)
|
||||||
|
}
|
||||||
|
mux.m.Lock()
|
||||||
|
delete(mux.z, Fqdn(pattern))
|
||||||
|
mux.m.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServeDNS dispatches the request to the handler whose pattern most
|
||||||
|
// closely matches the request message.
|
||||||
|
//
|
||||||
|
// ServeDNS is DNSSEC aware, meaning that queries for the DS record
|
||||||
|
// 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
|
||||||
|
// message is returned
|
||||||
|
func (mux *ServeMux) ServeDNS(w ResponseWriter, req *Msg) {
|
||||||
|
var h Handler
|
||||||
|
if len(req.Question) >= 1 { // allow more than one question
|
||||||
|
h = mux.match(req.Question[0].Name, req.Question[0].Qtype)
|
||||||
|
}
|
||||||
|
|
||||||
|
if h != nil {
|
||||||
|
h.ServeDNS(w, req)
|
||||||
|
} else {
|
||||||
|
HandleFailed(w, req)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle registers the handler with the given pattern
|
||||||
|
// in the DefaultServeMux. The documentation for
|
||||||
|
// ServeMux explains how patterns are matched.
|
||||||
|
func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) }
|
||||||
|
|
||||||
|
// HandleRemove deregisters the handle with the given pattern
|
||||||
|
// in the DefaultServeMux.
|
||||||
|
func HandleRemove(pattern string) { DefaultServeMux.HandleRemove(pattern) }
|
||||||
|
|
||||||
|
// HandleFunc registers the handler function with the given pattern
|
||||||
|
// in the DefaultServeMux.
|
||||||
|
func HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) {
|
||||||
|
DefaultServeMux.HandleFunc(pattern, handler)
|
||||||
|
}
|
721
vendor/github.com/miekg/dns/server.go
generated
vendored
721
vendor/github.com/miekg/dns/server.go
generated
vendored
|
@ -4,22 +4,54 @@ package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Maximum number of TCP queries before we close the socket.
|
// Default maximum number of TCP queries before we close the socket.
|
||||||
const maxTCPQueries = 128
|
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)
|
||||||
|
|
||||||
// Handler is implemented by any value that implements ServeDNS.
|
// Handler is implemented by any value that implements ServeDNS.
|
||||||
type Handler interface {
|
type Handler interface {
|
||||||
ServeDNS(w ResponseWriter, r *Msg)
|
ServeDNS(w ResponseWriter, r *Msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The HandlerFunc type is an adapter to allow the use of
|
||||||
|
// ordinary functions as DNS handlers. If f is a function
|
||||||
|
// with the appropriate signature, HandlerFunc(f) is a
|
||||||
|
// Handler object that calls f.
|
||||||
|
type HandlerFunc func(ResponseWriter, *Msg)
|
||||||
|
|
||||||
|
// ServeDNS calls f(w, r).
|
||||||
|
func (f HandlerFunc) ServeDNS(w ResponseWriter, r *Msg) {
|
||||||
|
f(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
// A ResponseWriter interface is used by an DNS handler to
|
// A ResponseWriter interface is used by an DNS handler to
|
||||||
// construct an DNS response.
|
// construct an DNS response.
|
||||||
type ResponseWriter interface {
|
type ResponseWriter interface {
|
||||||
|
@ -42,46 +74,25 @@ type ResponseWriter interface {
|
||||||
Hijack()
|
Hijack()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A ConnectionStater interface is used by a DNS Handler to access TLS connection state
|
||||||
|
// when available.
|
||||||
|
type ConnectionStater interface {
|
||||||
|
ConnectionState() *tls.ConnectionState
|
||||||
|
}
|
||||||
|
|
||||||
type response struct {
|
type response struct {
|
||||||
|
msg []byte
|
||||||
|
closed bool // connection has been closed
|
||||||
hijacked bool // connection has been hijacked by handler
|
hijacked bool // connection has been hijacked by handler
|
||||||
tsigStatus error
|
|
||||||
tsigTimersOnly bool
|
tsigTimersOnly bool
|
||||||
|
tsigStatus error
|
||||||
tsigRequestMAC string
|
tsigRequestMAC string
|
||||||
tsigSecret map[string]string // the tsig secrets
|
tsigSecret map[string]string // the tsig secrets
|
||||||
udp *net.UDPConn // i/o connection if UDP was used
|
udp *net.UDPConn // i/o connection if UDP was used
|
||||||
tcp net.Conn // i/o connection if TCP was used
|
tcp net.Conn // i/o connection if TCP was used
|
||||||
udpSession *SessionUDP // oob data to get egress interface right
|
udpSession *SessionUDP // oob data to get egress interface right
|
||||||
remoteAddr net.Addr // address of the client
|
|
||||||
writer Writer // writer to output the raw DNS bits
|
writer Writer // writer to output the raw DNS bits
|
||||||
}
|
wg *sync.WaitGroup // for gracefull shutdown
|
||||||
|
|
||||||
// ServeMux is an DNS request multiplexer. It matches the
|
|
||||||
// zone name of each incoming request against a list of
|
|
||||||
// registered patterns add calls the handler for the pattern
|
|
||||||
// that most closely matches the zone name. ServeMux is DNSSEC aware, meaning
|
|
||||||
// that queries for the DS record are redirected to the parent zone (if that
|
|
||||||
// is also registered), otherwise the child gets the query.
|
|
||||||
// ServeMux is also safe for concurrent access from multiple goroutines.
|
|
||||||
type ServeMux struct {
|
|
||||||
z map[string]Handler
|
|
||||||
m *sync.RWMutex
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewServeMux allocates and returns a new ServeMux.
|
|
||||||
func NewServeMux() *ServeMux { return &ServeMux{z: make(map[string]Handler), m: new(sync.RWMutex)} }
|
|
||||||
|
|
||||||
// DefaultServeMux is the default ServeMux used by Serve.
|
|
||||||
var DefaultServeMux = NewServeMux()
|
|
||||||
|
|
||||||
// The HandlerFunc type is an adapter to allow the use of
|
|
||||||
// ordinary functions as DNS handlers. If f is a function
|
|
||||||
// with the appropriate signature, HandlerFunc(f) is a
|
|
||||||
// Handler object that calls f.
|
|
||||||
type HandlerFunc func(ResponseWriter, *Msg)
|
|
||||||
|
|
||||||
// ServeDNS calls f(w, r).
|
|
||||||
func (f HandlerFunc) ServeDNS(w ResponseWriter, r *Msg) {
|
|
||||||
f(w, r)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleFailed returns a HandlerFunc that returns SERVFAIL for every request it gets.
|
// HandleFailed returns a HandlerFunc that returns SERVFAIL for every request it gets.
|
||||||
|
@ -92,8 +103,6 @@ func HandleFailed(w ResponseWriter, r *Msg) {
|
||||||
w.WriteMsg(m)
|
w.WriteMsg(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
func failedHandler() Handler { return HandlerFunc(HandleFailed) }
|
|
||||||
|
|
||||||
// ListenAndServe Starts a server on address and network specified Invoke handler
|
// ListenAndServe Starts a server on address and network specified Invoke handler
|
||||||
// for incoming queries.
|
// for incoming queries.
|
||||||
func ListenAndServe(addr string, network string, handler Handler) error {
|
func ListenAndServe(addr string, network string, handler Handler) error {
|
||||||
|
@ -132,99 +141,6 @@ func ActivateAndServe(l net.Listener, p net.PacketConn, handler Handler) error {
|
||||||
return server.ActivateAndServe()
|
return server.ActivateAndServe()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mux *ServeMux) match(q string, t uint16) Handler {
|
|
||||||
mux.m.RLock()
|
|
||||||
defer mux.m.RUnlock()
|
|
||||||
var handler Handler
|
|
||||||
b := make([]byte, len(q)) // worst case, one label of length q
|
|
||||||
off := 0
|
|
||||||
end := false
|
|
||||||
for {
|
|
||||||
l := len(q[off:])
|
|
||||||
for i := 0; i < l; i++ {
|
|
||||||
b[i] = q[off+i]
|
|
||||||
if b[i] >= 'A' && b[i] <= 'Z' {
|
|
||||||
b[i] |= ('a' - 'A')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if h, ok := mux.z[string(b[:l])]; ok { // causes garbage, might want to change the map key
|
|
||||||
if t != TypeDS {
|
|
||||||
return h
|
|
||||||
}
|
|
||||||
// Continue for DS to see if we have a parent too, if so delegeate to the parent
|
|
||||||
handler = h
|
|
||||||
}
|
|
||||||
off, end = NextLabel(q, off)
|
|
||||||
if end {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Wildcard match, if we have found nothing try the root zone as a last resort.
|
|
||||||
if h, ok := mux.z["."]; ok {
|
|
||||||
return h
|
|
||||||
}
|
|
||||||
return handler
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle adds a handler to the ServeMux for pattern.
|
|
||||||
func (mux *ServeMux) Handle(pattern string, handler Handler) {
|
|
||||||
if pattern == "" {
|
|
||||||
panic("dns: invalid pattern " + pattern)
|
|
||||||
}
|
|
||||||
mux.m.Lock()
|
|
||||||
mux.z[Fqdn(pattern)] = handler
|
|
||||||
mux.m.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
// HandleFunc adds a handler function to the ServeMux for pattern.
|
|
||||||
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) {
|
|
||||||
mux.Handle(pattern, HandlerFunc(handler))
|
|
||||||
}
|
|
||||||
|
|
||||||
// HandleRemove deregistrars the handler specific for pattern from the ServeMux.
|
|
||||||
func (mux *ServeMux) HandleRemove(pattern string) {
|
|
||||||
if pattern == "" {
|
|
||||||
panic("dns: invalid pattern " + pattern)
|
|
||||||
}
|
|
||||||
mux.m.Lock()
|
|
||||||
delete(mux.z, Fqdn(pattern))
|
|
||||||
mux.m.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServeDNS dispatches the request to the handler whose
|
|
||||||
// pattern most closely matches the request message. If DefaultServeMux
|
|
||||||
// is used the correct thing for DS queries is done: a possible parent
|
|
||||||
// is sought.
|
|
||||||
// If no handler is found a standard SERVFAIL message is returned
|
|
||||||
// If the request message does not have exactly one question in the
|
|
||||||
// question section a SERVFAIL is returned, unlesss Unsafe is true.
|
|
||||||
func (mux *ServeMux) ServeDNS(w ResponseWriter, request *Msg) {
|
|
||||||
var h Handler
|
|
||||||
if len(request.Question) < 1 { // allow more than one question
|
|
||||||
h = failedHandler()
|
|
||||||
} else {
|
|
||||||
if h = mux.match(request.Question[0].Name, request.Question[0].Qtype); h == nil {
|
|
||||||
h = failedHandler()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
h.ServeDNS(w, request)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle registers the handler with the given pattern
|
|
||||||
// in the DefaultServeMux. The documentation for
|
|
||||||
// ServeMux explains how patterns are matched.
|
|
||||||
func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) }
|
|
||||||
|
|
||||||
// HandleRemove deregisters the handle with the given pattern
|
|
||||||
// in the DefaultServeMux.
|
|
||||||
func HandleRemove(pattern string) { DefaultServeMux.HandleRemove(pattern) }
|
|
||||||
|
|
||||||
// HandleFunc registers the handler function with the given pattern
|
|
||||||
// in the DefaultServeMux.
|
|
||||||
func HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) {
|
|
||||||
DefaultServeMux.HandleFunc(pattern, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writer writes raw DNS messages; each call to Write should send an entire message.
|
// Writer writes raw DNS messages; each call to Write should send an entire message.
|
||||||
type Writer interface {
|
type Writer interface {
|
||||||
io.Writer
|
io.Writer
|
||||||
|
@ -246,11 +162,11 @@ type defaultReader struct {
|
||||||
*Server
|
*Server
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dr *defaultReader) ReadTCP(conn net.Conn, timeout time.Duration) ([]byte, error) {
|
func (dr defaultReader) ReadTCP(conn net.Conn, timeout time.Duration) ([]byte, error) {
|
||||||
return dr.readTCP(conn, timeout)
|
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)
|
return dr.readUDP(conn, timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,87 +203,170 @@ type Server struct {
|
||||||
IdleTimeout func() time.Duration
|
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).
|
// Secret(s) for Tsig map[<zonename>]<base64 secret>. The zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2).
|
||||||
TsigSecret map[string]string
|
TsigSecret map[string]string
|
||||||
// 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.
|
// If NotifyStartedFunc is set it is called once the server has started listening.
|
||||||
NotifyStartedFunc func()
|
NotifyStartedFunc func()
|
||||||
// DecorateReader is optional, allows customization of the process that reads raw DNS messages.
|
// DecorateReader is optional, allows customization of the process that reads raw DNS messages.
|
||||||
DecorateReader DecorateReader
|
DecorateReader DecorateReader
|
||||||
// DecorateWriter is optional, allows customization of the process that writes raw DNS messages.
|
// DecorateWriter is optional, allows customization of the process that writes raw DNS messages.
|
||||||
DecorateWriter DecorateWriter
|
DecorateWriter DecorateWriter
|
||||||
|
// Maximum number of TCP queries before we close the socket. Default is maxTCPQueries (unlimited if -1).
|
||||||
|
MaxTCPQueries int
|
||||||
|
// 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
|
||||||
|
// AcceptMsgFunc will check the incoming message and will reject it early in the process.
|
||||||
|
// By default DefaultMsgAcceptFunc will be used.
|
||||||
|
MsgAcceptFunc MsgAcceptFunc
|
||||||
|
|
||||||
|
// UDP packet or TCP connection queue
|
||||||
|
queue chan *response
|
||||||
|
// Workers count
|
||||||
|
workersCount int32
|
||||||
|
|
||||||
// Shutdown handling
|
// Shutdown handling
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
started bool
|
started bool
|
||||||
|
shutdown chan struct{}
|
||||||
|
conns map[net.Conn]struct{}
|
||||||
|
|
||||||
|
// A pool for UDP message buffers.
|
||||||
|
udpPool sync.Pool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (srv *Server) isStarted() bool {
|
||||||
|
srv.lock.RLock()
|
||||||
|
started := srv.started
|
||||||
|
srv.lock.RUnlock()
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
srv.udpPool.New = makeUDPBuffer(srv.UDPSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
func unlockOnce(l sync.Locker) func() {
|
||||||
|
var once sync.Once
|
||||||
|
return func() { once.Do(l.Unlock) }
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenAndServe starts a nameserver on the configured address in *Server.
|
// ListenAndServe starts a nameserver on the configured address in *Server.
|
||||||
func (srv *Server) ListenAndServe() error {
|
func (srv *Server) ListenAndServe() error {
|
||||||
|
unlock := unlockOnce(&srv.lock)
|
||||||
srv.lock.Lock()
|
srv.lock.Lock()
|
||||||
defer srv.lock.Unlock()
|
defer unlock()
|
||||||
|
|
||||||
if srv.started {
|
if srv.started {
|
||||||
return &Error{err: "server already started"}
|
return &Error{err: "server already started"}
|
||||||
}
|
}
|
||||||
|
|
||||||
addr := srv.Addr
|
addr := srv.Addr
|
||||||
if addr == "" {
|
if addr == "" {
|
||||||
addr = ":domain"
|
addr = ":domain"
|
||||||
}
|
}
|
||||||
if srv.UDPSize == 0 {
|
|
||||||
srv.UDPSize = MinMsgSize
|
srv.init()
|
||||||
}
|
defer close(srv.queue)
|
||||||
|
|
||||||
switch srv.Net {
|
switch srv.Net {
|
||||||
case "tcp", "tcp4", "tcp6":
|
case "tcp", "tcp4", "tcp6":
|
||||||
a, err := net.ResolveTCPAddr(srv.Net, addr)
|
l, err := listenTCP(srv.Net, addr, srv.ReusePort)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
l, err := net.ListenTCP(srv.Net, a)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
srv.Listener = l
|
srv.Listener = l
|
||||||
srv.started = true
|
srv.started = true
|
||||||
srv.lock.Unlock()
|
unlock()
|
||||||
err = srv.serveTCP(l)
|
return srv.serveTCP(l)
|
||||||
srv.lock.Lock() // to satisfy the defer at the top
|
|
||||||
return err
|
|
||||||
case "tcp-tls", "tcp4-tls", "tcp6-tls":
|
case "tcp-tls", "tcp4-tls", "tcp6-tls":
|
||||||
network := "tcp"
|
if srv.TLSConfig == nil || (len(srv.TLSConfig.Certificates) == 0 && srv.TLSConfig.GetCertificate == nil) {
|
||||||
if srv.Net == "tcp4-tls" {
|
return errors.New("dns: neither Certificates nor GetCertificate set in Config")
|
||||||
network = "tcp4"
|
|
||||||
} else if srv.Net == "tcp6-tls" {
|
|
||||||
network = "tcp6"
|
|
||||||
}
|
}
|
||||||
|
network := strings.TrimSuffix(srv.Net, "-tls")
|
||||||
l, err := tls.Listen(network, addr, srv.TLSConfig)
|
l, err := listenTCP(network, addr, srv.ReusePort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
l = tls.NewListener(l, srv.TLSConfig)
|
||||||
srv.Listener = l
|
srv.Listener = l
|
||||||
srv.started = true
|
srv.started = true
|
||||||
srv.lock.Unlock()
|
unlock()
|
||||||
err = srv.serveTCP(l)
|
return srv.serveTCP(l)
|
||||||
srv.lock.Lock() // to satisfy the defer at the top
|
|
||||||
return err
|
|
||||||
case "udp", "udp4", "udp6":
|
case "udp", "udp4", "udp6":
|
||||||
a, err := net.ResolveUDPAddr(srv.Net, addr)
|
l, err := listenUDP(srv.Net, addr, srv.ReusePort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
l, err := net.ListenUDP(srv.Net, a)
|
u := l.(*net.UDPConn)
|
||||||
if err != nil {
|
if e := setUDPSocketOptions(u); e != nil {
|
||||||
return err
|
|
||||||
}
|
|
||||||
if e := setUDPSocketOptions(l); e != nil {
|
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
srv.PacketConn = l
|
srv.PacketConn = l
|
||||||
srv.started = true
|
srv.started = true
|
||||||
srv.lock.Unlock()
|
unlock()
|
||||||
err = srv.serveUDP(l)
|
return srv.serveUDP(u)
|
||||||
srv.lock.Lock() // to satisfy the defer at the top
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
return &Error{err: "bad network"}
|
return &Error{err: "bad network"}
|
||||||
}
|
}
|
||||||
|
@ -375,17 +374,20 @@ func (srv *Server) ListenAndServe() error {
|
||||||
// ActivateAndServe starts a nameserver with the PacketConn or Listener
|
// ActivateAndServe starts a nameserver with the PacketConn or Listener
|
||||||
// configured in *Server. Its main use is to start a server from systemd.
|
// configured in *Server. Its main use is to start a server from systemd.
|
||||||
func (srv *Server) ActivateAndServe() error {
|
func (srv *Server) ActivateAndServe() error {
|
||||||
|
unlock := unlockOnce(&srv.lock)
|
||||||
srv.lock.Lock()
|
srv.lock.Lock()
|
||||||
defer srv.lock.Unlock()
|
defer unlock()
|
||||||
|
|
||||||
if srv.started {
|
if srv.started {
|
||||||
return &Error{err: "server already started"}
|
return &Error{err: "server already started"}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
srv.init()
|
||||||
|
defer close(srv.queue)
|
||||||
|
|
||||||
pConn := srv.PacketConn
|
pConn := srv.PacketConn
|
||||||
l := srv.Listener
|
l := srv.Listener
|
||||||
if pConn != nil {
|
if pConn != nil {
|
||||||
if srv.UDPSize == 0 {
|
|
||||||
srv.UDPSize = MinMsgSize
|
|
||||||
}
|
|
||||||
// Check PacketConn interface's type is valid and value
|
// Check PacketConn interface's type is valid and value
|
||||||
// is not nil
|
// is not nil
|
||||||
if t, ok := pConn.(*net.UDPConn); ok && t != nil {
|
if t, ok := pConn.(*net.UDPConn); ok && t != nil {
|
||||||
|
@ -393,18 +395,14 @@ func (srv *Server) ActivateAndServe() error {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
srv.started = true
|
srv.started = true
|
||||||
srv.lock.Unlock()
|
unlock()
|
||||||
e := srv.serveUDP(t)
|
return srv.serveUDP(t)
|
||||||
srv.lock.Lock() // to satisfy the defer at the top
|
|
||||||
return e
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if l != nil {
|
if l != nil {
|
||||||
srv.started = true
|
srv.started = true
|
||||||
srv.lock.Unlock()
|
unlock()
|
||||||
e := srv.serveTCP(l)
|
return srv.serveTCP(l)
|
||||||
srv.lock.Lock() // to satisfy the defer at the top
|
|
||||||
return e
|
|
||||||
}
|
}
|
||||||
return &Error{err: "bad listeners"}
|
return &Error{err: "bad listeners"}
|
||||||
}
|
}
|
||||||
|
@ -412,34 +410,66 @@ func (srv *Server) ActivateAndServe() error {
|
||||||
// Shutdown shuts down a server. After a call to Shutdown, ListenAndServe and
|
// Shutdown shuts down a server. After a call to Shutdown, ListenAndServe and
|
||||||
// ActivateAndServe will return.
|
// ActivateAndServe will return.
|
||||||
func (srv *Server) Shutdown() error {
|
func (srv *Server) Shutdown() error {
|
||||||
|
return srv.ShutdownContext(context.Background())
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShutdownContext shuts down a server. After a call to ShutdownContext,
|
||||||
|
// ListenAndServe and ActivateAndServe will return.
|
||||||
|
//
|
||||||
|
// A context.Context may be passed to limit how long to wait for connections
|
||||||
|
// to terminate.
|
||||||
|
func (srv *Server) ShutdownContext(ctx context.Context) error {
|
||||||
srv.lock.Lock()
|
srv.lock.Lock()
|
||||||
if !srv.started {
|
if !srv.started {
|
||||||
srv.lock.Unlock()
|
srv.lock.Unlock()
|
||||||
return &Error{err: "server not started"}
|
return &Error{err: "server not started"}
|
||||||
}
|
}
|
||||||
|
|
||||||
srv.started = false
|
srv.started = false
|
||||||
|
|
||||||
|
if srv.PacketConn != nil {
|
||||||
|
srv.PacketConn.SetReadDeadline(aLongTimeAgo) // Unblock reads
|
||||||
|
}
|
||||||
|
|
||||||
|
if srv.Listener != nil {
|
||||||
|
srv.Listener.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
for rw := range srv.conns {
|
||||||
|
rw.SetReadDeadline(aLongTimeAgo) // Unblock reads
|
||||||
|
}
|
||||||
|
|
||||||
srv.lock.Unlock()
|
srv.lock.Unlock()
|
||||||
|
|
||||||
|
if testShutdownNotify != nil {
|
||||||
|
testShutdownNotify.Broadcast()
|
||||||
|
}
|
||||||
|
|
||||||
|
var ctxErr error
|
||||||
|
select {
|
||||||
|
case <-srv.shutdown:
|
||||||
|
case <-ctx.Done():
|
||||||
|
ctxErr = ctx.Err()
|
||||||
|
}
|
||||||
|
|
||||||
if srv.PacketConn != nil {
|
if srv.PacketConn != nil {
|
||||||
srv.PacketConn.Close()
|
srv.PacketConn.Close()
|
||||||
}
|
}
|
||||||
if srv.Listener != nil {
|
|
||||||
srv.Listener.Close()
|
return ctxErr
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var testShutdownNotify *sync.Cond
|
||||||
|
|
||||||
// getReadTimeout is a helper func to use system timeout if server did not intend to change it.
|
// getReadTimeout is a helper func to use system timeout if server did not intend to change it.
|
||||||
func (srv *Server) getReadTimeout() time.Duration {
|
func (srv *Server) getReadTimeout() time.Duration {
|
||||||
rtimeout := dnsTimeout
|
|
||||||
if srv.ReadTimeout != 0 {
|
if srv.ReadTimeout != 0 {
|
||||||
rtimeout = srv.ReadTimeout
|
return srv.ReadTimeout
|
||||||
}
|
}
|
||||||
return rtimeout
|
return dnsTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
// serveTCP starts a TCP listener for the server.
|
// serveTCP starts a TCP listener for the server.
|
||||||
// Each request is handled in a separate goroutine.
|
|
||||||
func (srv *Server) serveTCP(l net.Listener) error {
|
func (srv *Server) serveTCP(l net.Listener) error {
|
||||||
defer l.Close()
|
defer l.Close()
|
||||||
|
|
||||||
|
@ -447,44 +477,39 @@ func (srv *Server) serveTCP(l net.Listener) error {
|
||||||
srv.NotifyStartedFunc()
|
srv.NotifyStartedFunc()
|
||||||
}
|
}
|
||||||
|
|
||||||
reader := Reader(&defaultReader{srv})
|
var wg sync.WaitGroup
|
||||||
if srv.DecorateReader != nil {
|
defer func() {
|
||||||
reader = srv.DecorateReader(reader)
|
wg.Wait()
|
||||||
}
|
close(srv.shutdown)
|
||||||
|
}()
|
||||||
|
|
||||||
handler := srv.Handler
|
for srv.isStarted() {
|
||||||
if handler == nil {
|
|
||||||
handler = DefaultServeMux
|
|
||||||
}
|
|
||||||
rtimeout := srv.getReadTimeout()
|
|
||||||
// deadline is not used here
|
|
||||||
for {
|
|
||||||
rw, err := l.Accept()
|
rw, err := l.Accept()
|
||||||
srv.lock.RLock()
|
|
||||||
if !srv.started {
|
|
||||||
srv.lock.RUnlock()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
srv.lock.RUnlock()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if !srv.isStarted() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
if neterr, ok := err.(net.Error); ok && neterr.Temporary() {
|
if neterr, ok := err.(net.Error); ok && neterr.Temporary() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
go func() {
|
srv.lock.Lock()
|
||||||
m, err := reader.ReadTCP(rw, rtimeout)
|
// Track the connection to allow unblocking reads on shutdown.
|
||||||
if err != nil {
|
srv.conns[rw] = struct{}{}
|
||||||
rw.Close()
|
srv.lock.Unlock()
|
||||||
return
|
wg.Add(1)
|
||||||
}
|
srv.spawnWorker(&response{
|
||||||
srv.serve(rw.RemoteAddr(), handler, m, nil, nil, rw)
|
tsigSecret: srv.TsigSecret,
|
||||||
}()
|
tcp: rw,
|
||||||
|
wg: &wg,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// serveUDP starts a UDP listener for the server.
|
// serveUDP starts a UDP listener for the server.
|
||||||
// Each request is handled in a separate goroutine.
|
|
||||||
func (srv *Server) serveUDP(l *net.UDPConn) error {
|
func (srv *Server) serveUDP(l *net.UDPConn) error {
|
||||||
defer l.Close()
|
defer l.Close()
|
||||||
|
|
||||||
|
@ -492,112 +517,187 @@ func (srv *Server) serveUDP(l *net.UDPConn) error {
|
||||||
srv.NotifyStartedFunc()
|
srv.NotifyStartedFunc()
|
||||||
}
|
}
|
||||||
|
|
||||||
reader := Reader(&defaultReader{srv})
|
reader := Reader(defaultReader{srv})
|
||||||
if srv.DecorateReader != nil {
|
if srv.DecorateReader != nil {
|
||||||
reader = srv.DecorateReader(reader)
|
reader = srv.DecorateReader(reader)
|
||||||
}
|
}
|
||||||
|
|
||||||
handler := srv.Handler
|
var wg sync.WaitGroup
|
||||||
if handler == nil {
|
defer func() {
|
||||||
handler = DefaultServeMux
|
wg.Wait()
|
||||||
}
|
close(srv.shutdown)
|
||||||
|
}()
|
||||||
|
|
||||||
rtimeout := srv.getReadTimeout()
|
rtimeout := srv.getReadTimeout()
|
||||||
// deadline is not used here
|
// deadline is not used here
|
||||||
for {
|
for srv.isStarted() {
|
||||||
m, s, err := reader.ReadUDP(l, rtimeout)
|
m, s, err := reader.ReadUDP(l, rtimeout)
|
||||||
srv.lock.RLock()
|
|
||||||
if !srv.started {
|
|
||||||
srv.lock.RUnlock()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
srv.lock.RUnlock()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if !srv.isStarted() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
if netErr, ok := err.(net.Error); ok && netErr.Temporary() {
|
if netErr, ok := err.(net.Error); ok && netErr.Temporary() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(m) < headerSize {
|
if len(m) < headerSize {
|
||||||
|
if cap(m) == srv.UDPSize {
|
||||||
|
srv.udpPool.Put(m[:srv.UDPSize])
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
go srv.serve(s.RemoteAddr(), handler, m, l, s, nil)
|
wg.Add(1)
|
||||||
|
srv.spawnWorker(&response{
|
||||||
|
msg: m,
|
||||||
|
tsigSecret: srv.TsigSecret,
|
||||||
|
udp: l,
|
||||||
|
udpSession: s,
|
||||||
|
wg: &wg,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serve a new connection.
|
func (srv *Server) serve(w *response) {
|
||||||
func (srv *Server) serve(a net.Addr, h Handler, m []byte, u *net.UDPConn, s *SessionUDP, t net.Conn) {
|
|
||||||
w := &response{tsigSecret: srv.TsigSecret, udp: u, tcp: t, remoteAddr: a, udpSession: s}
|
|
||||||
if srv.DecorateWriter != nil {
|
if srv.DecorateWriter != nil {
|
||||||
w.writer = srv.DecorateWriter(w)
|
w.writer = srv.DecorateWriter(w)
|
||||||
} else {
|
} else {
|
||||||
w.writer = w
|
w.writer = w
|
||||||
}
|
}
|
||||||
|
|
||||||
q := 0 // counter for the amount of TCP queries we get
|
if w.udp != nil {
|
||||||
|
// serve UDP
|
||||||
|
srv.serveDNS(w)
|
||||||
|
|
||||||
reader := Reader(&defaultReader{srv})
|
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})
|
||||||
if srv.DecorateReader != nil {
|
if srv.DecorateReader != nil {
|
||||||
reader = srv.DecorateReader(reader)
|
reader = srv.DecorateReader(reader)
|
||||||
}
|
}
|
||||||
Redo:
|
|
||||||
req := new(Msg)
|
idleTimeout := tcpIdleTimeout
|
||||||
err := req.Unpack(m)
|
if srv.IdleTimeout != nil {
|
||||||
if err != nil { // Send a FormatError back
|
idleTimeout = srv.IdleTimeout()
|
||||||
x := new(Msg)
|
|
||||||
x.SetRcodeFormatError(req)
|
|
||||||
w.WriteMsg(x)
|
|
||||||
goto Exit
|
|
||||||
}
|
}
|
||||||
if !srv.Unsafe && req.Response {
|
|
||||||
goto Exit
|
timeout := srv.getReadTimeout()
|
||||||
|
|
||||||
|
limit := srv.MaxTCPQueries
|
||||||
|
if limit == 0 {
|
||||||
|
limit = maxTCPQueries
|
||||||
|
}
|
||||||
|
|
||||||
|
for q := 0; (q < limit || limit == -1) && srv.isStarted(); q++ {
|
||||||
|
var err error
|
||||||
|
w.msg, err = reader.ReadTCP(w.tcp, timeout)
|
||||||
|
if err != nil {
|
||||||
|
// TODO(tmthrgd): handle error
|
||||||
|
break
|
||||||
|
}
|
||||||
|
srv.serveDNS(w)
|
||||||
|
if w.tcp == nil {
|
||||||
|
break // Close() was called
|
||||||
|
}
|
||||||
|
if w.hijacked {
|
||||||
|
break // client will call Close() themselves
|
||||||
|
}
|
||||||
|
// The first read uses the read timeout, the rest use the
|
||||||
|
// idle timeout.
|
||||||
|
timeout = idleTimeout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (srv *Server) disposeBuffer(w *response) {
|
||||||
|
if w.udp != nil && cap(w.msg) == srv.UDPSize {
|
||||||
|
srv.udpPool.Put(w.msg[:srv.UDPSize])
|
||||||
|
}
|
||||||
|
w.msg = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (srv *Server) serveDNS(w *response) {
|
||||||
|
dh, off, err := unpackMsgHdr(w.msg, 0)
|
||||||
|
if err != nil {
|
||||||
|
// Let client hang, they are sending crap; any reply can be used to amplify.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req := new(Msg)
|
||||||
|
req.setHdr(dh)
|
||||||
|
|
||||||
|
switch srv.MsgAcceptFunc(dh) {
|
||||||
|
case MsgAccept:
|
||||||
|
case MsgIgnore:
|
||||||
|
return
|
||||||
|
case MsgReject:
|
||||||
|
req.SetRcodeFormatError(req)
|
||||||
|
// Are we allowed to delete any OPT records here?
|
||||||
|
req.Ns, req.Answer, req.Extra = nil, nil, nil
|
||||||
|
|
||||||
|
w.WriteMsg(req)
|
||||||
|
srv.disposeBuffer(w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := req.unpack(dh, w.msg, off); err != nil {
|
||||||
|
req.SetRcodeFormatError(req)
|
||||||
|
req.Ns, req.Answer, req.Extra = nil, nil, nil
|
||||||
|
|
||||||
|
w.WriteMsg(req)
|
||||||
|
srv.disposeBuffer(w)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w.tsigStatus = nil
|
w.tsigStatus = nil
|
||||||
if w.tsigSecret != nil {
|
if w.tsigSecret != nil {
|
||||||
if t := req.IsTsig(); t != nil {
|
if t := req.IsTsig(); t != nil {
|
||||||
secret := t.Hdr.Name
|
if secret, ok := w.tsigSecret[t.Hdr.Name]; ok {
|
||||||
if _, ok := w.tsigSecret[secret]; !ok {
|
w.tsigStatus = TsigVerify(w.msg, secret, "", false)
|
||||||
w.tsigStatus = ErrKeyAlg
|
} else {
|
||||||
|
w.tsigStatus = ErrSecret
|
||||||
}
|
}
|
||||||
w.tsigStatus = TsigVerify(m, w.tsigSecret[secret], "", false)
|
|
||||||
w.tsigTimersOnly = false
|
w.tsigTimersOnly = false
|
||||||
w.tsigRequestMAC = req.Extra[len(req.Extra)-1].(*TSIG).MAC
|
w.tsigRequestMAC = req.Extra[len(req.Extra)-1].(*TSIG).MAC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
h.ServeDNS(w, req) // Writes back to the client
|
|
||||||
|
|
||||||
Exit:
|
srv.disposeBuffer(w)
|
||||||
if w.tcp == nil {
|
|
||||||
return
|
handler := srv.Handler
|
||||||
}
|
if handler == nil {
|
||||||
// TODO(miek): make this number configurable?
|
handler = DefaultServeMux
|
||||||
if q > maxTCPQueries { // close socket after this many queries
|
|
||||||
w.Close()
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if w.hijacked {
|
handler.ServeDNS(w, req) // Writes back to the client
|
||||||
return // client calls Close()
|
|
||||||
}
|
|
||||||
if u != nil { // UDP, "close" and return
|
|
||||||
w.Close()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
idleTimeout := tcpIdleTimeout
|
|
||||||
if srv.IdleTimeout != nil {
|
|
||||||
idleTimeout = srv.IdleTimeout()
|
|
||||||
}
|
|
||||||
m, err = reader.ReadTCP(w.tcp, idleTimeout)
|
|
||||||
if err == nil {
|
|
||||||
q++
|
|
||||||
goto Redo
|
|
||||||
}
|
|
||||||
w.Close()
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (srv *Server) readTCP(conn net.Conn, timeout time.Duration) ([]byte, error) {
|
func (srv *Server) readTCP(conn net.Conn, timeout time.Duration) ([]byte, error) {
|
||||||
conn.SetReadDeadline(time.Now().Add(timeout))
|
// If we race with ShutdownContext, the read deadline may
|
||||||
|
// have been set in the distant past to unblock the read
|
||||||
|
// below. We must not override it, otherwise we may block
|
||||||
|
// ShutdownContext.
|
||||||
|
srv.lock.RLock()
|
||||||
|
if srv.started {
|
||||||
|
conn.SetReadDeadline(time.Now().Add(timeout))
|
||||||
|
}
|
||||||
|
srv.lock.RUnlock()
|
||||||
|
|
||||||
l := make([]byte, 2)
|
l := make([]byte, 2)
|
||||||
n, err := conn.Read(l)
|
n, err := conn.Read(l)
|
||||||
if err != nil || n != 2 {
|
if err != nil || n != 2 {
|
||||||
|
@ -632,10 +732,17 @@ func (srv *Server) readTCP(conn net.Conn, timeout time.Duration) ([]byte, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (srv *Server) readUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error) {
|
func (srv *Server) readUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error) {
|
||||||
conn.SetReadDeadline(time.Now().Add(timeout))
|
srv.lock.RLock()
|
||||||
m := make([]byte, srv.UDPSize)
|
if srv.started {
|
||||||
|
// See the comment in readTCP above.
|
||||||
|
conn.SetReadDeadline(time.Now().Add(timeout))
|
||||||
|
}
|
||||||
|
srv.lock.RUnlock()
|
||||||
|
|
||||||
|
m := srv.udpPool.Get().([]byte)
|
||||||
n, s, err := ReadFromSessionUDP(conn, m)
|
n, s, err := ReadFromSessionUDP(conn, m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
srv.udpPool.Put(m)
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
m = m[:n]
|
m = m[:n]
|
||||||
|
@ -644,6 +751,10 @@ func (srv *Server) readUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *S
|
||||||
|
|
||||||
// WriteMsg implements the ResponseWriter.WriteMsg method.
|
// WriteMsg implements the ResponseWriter.WriteMsg method.
|
||||||
func (w *response) WriteMsg(m *Msg) (err error) {
|
func (w *response) WriteMsg(m *Msg) (err error) {
|
||||||
|
if w.closed {
|
||||||
|
return &Error{err: "WriteMsg called after Close"}
|
||||||
|
}
|
||||||
|
|
||||||
var data []byte
|
var data []byte
|
||||||
if w.tsigSecret != nil { // if no secrets, dont check for the tsig (which is a longer check)
|
if w.tsigSecret != nil { // if no secrets, dont check for the tsig (which is a longer check)
|
||||||
if t := m.IsTsig(); t != nil {
|
if t := m.IsTsig(); t != nil {
|
||||||
|
@ -665,10 +776,13 @@ func (w *response) WriteMsg(m *Msg) (err error) {
|
||||||
|
|
||||||
// Write implements the ResponseWriter.Write method.
|
// Write implements the ResponseWriter.Write method.
|
||||||
func (w *response) Write(m []byte) (int, error) {
|
func (w *response) Write(m []byte) (int, error) {
|
||||||
|
if w.closed {
|
||||||
|
return 0, &Error{err: "Write called after Close"}
|
||||||
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case w.udp != nil:
|
case w.udp != nil:
|
||||||
n, err := WriteToSessionUDP(w.udp, m, w.udpSession)
|
return WriteToSessionUDP(w.udp, m, w.udpSession)
|
||||||
return n, err
|
|
||||||
case w.tcp != nil:
|
case w.tcp != nil:
|
||||||
lm := len(m)
|
lm := len(m)
|
||||||
if lm < 2 {
|
if lm < 2 {
|
||||||
|
@ -683,20 +797,34 @@ func (w *response) Write(m []byte) (int, error) {
|
||||||
|
|
||||||
n, err := io.Copy(w.tcp, bytes.NewReader(m))
|
n, err := io.Copy(w.tcp, bytes.NewReader(m))
|
||||||
return int(n), err
|
return int(n), err
|
||||||
|
default:
|
||||||
|
panic("dns: internal error: udp and tcp both nil")
|
||||||
}
|
}
|
||||||
panic("not reached")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// LocalAddr implements the ResponseWriter.LocalAddr method.
|
// LocalAddr implements the ResponseWriter.LocalAddr method.
|
||||||
func (w *response) LocalAddr() net.Addr {
|
func (w *response) LocalAddr() net.Addr {
|
||||||
if w.tcp != nil {
|
switch {
|
||||||
|
case w.udp != nil:
|
||||||
|
return w.udp.LocalAddr()
|
||||||
|
case w.tcp != nil:
|
||||||
return w.tcp.LocalAddr()
|
return w.tcp.LocalAddr()
|
||||||
|
default:
|
||||||
|
panic("dns: internal error: udp and tcp both nil")
|
||||||
}
|
}
|
||||||
return w.udp.LocalAddr()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoteAddr implements the ResponseWriter.RemoteAddr method.
|
// RemoteAddr implements the ResponseWriter.RemoteAddr method.
|
||||||
func (w *response) RemoteAddr() net.Addr { return w.remoteAddr }
|
func (w *response) RemoteAddr() net.Addr {
|
||||||
|
switch {
|
||||||
|
case w.udpSession != nil:
|
||||||
|
return w.udpSession.RemoteAddr()
|
||||||
|
case w.tcp != nil:
|
||||||
|
return w.tcp.RemoteAddr()
|
||||||
|
default:
|
||||||
|
panic("dns: internal error: udpSession and tcp both nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TsigStatus implements the ResponseWriter.TsigStatus method.
|
// TsigStatus implements the ResponseWriter.TsigStatus method.
|
||||||
func (w *response) TsigStatus() error { return w.tsigStatus }
|
func (w *response) TsigStatus() error { return w.tsigStatus }
|
||||||
|
@ -709,11 +837,30 @@ func (w *response) Hijack() { w.hijacked = true }
|
||||||
|
|
||||||
// Close implements the ResponseWriter.Close method
|
// Close implements the ResponseWriter.Close method
|
||||||
func (w *response) Close() error {
|
func (w *response) Close() error {
|
||||||
// Can't close the udp conn, as that is actually the listener.
|
if w.closed {
|
||||||
if w.tcp != nil {
|
return &Error{err: "connection already closed"}
|
||||||
e := w.tcp.Close()
|
}
|
||||||
w.tcp = nil
|
w.closed = true
|
||||||
return e
|
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConnectionState() implements the ConnectionStater.ConnectionState() interface.
|
||||||
|
func (w *response) ConnectionState() *tls.ConnectionState {
|
||||||
|
type tlsConnectionStater interface {
|
||||||
|
ConnectionState() tls.ConnectionState
|
||||||
|
}
|
||||||
|
if v, ok := w.tcp.(tlsConnectionStater); ok {
|
||||||
|
t := v.ConnectionState()
|
||||||
|
return &t
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
19
vendor/github.com/miekg/dns/sig0.go
generated
vendored
19
vendor/github.com/miekg/dns/sig0.go
generated
vendored
|
@ -21,15 +21,11 @@ func (rr *SIG) Sign(k crypto.Signer, m *Msg) ([]byte, error) {
|
||||||
if rr.KeyTag == 0 || len(rr.SignerName) == 0 || rr.Algorithm == 0 {
|
if rr.KeyTag == 0 || len(rr.SignerName) == 0 || rr.Algorithm == 0 {
|
||||||
return nil, ErrKey
|
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)
|
mbuf, err := m.PackBuffer(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -107,7 +103,7 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
|
||||||
anc := binary.BigEndian.Uint16(buf[6:])
|
anc := binary.BigEndian.Uint16(buf[6:])
|
||||||
auc := binary.BigEndian.Uint16(buf[8:])
|
auc := binary.BigEndian.Uint16(buf[8:])
|
||||||
adc := binary.BigEndian.Uint16(buf[10:])
|
adc := binary.BigEndian.Uint16(buf[10:])
|
||||||
offset := 12
|
offset := headerSize
|
||||||
var err error
|
var err error
|
||||||
for i := uint16(0); i < qdc && offset < buflen; i++ {
|
for i := uint16(0); i < qdc && offset < buflen; i++ {
|
||||||
_, offset, err = UnpackDomainName(buf, offset)
|
_, offset, err = UnpackDomainName(buf, offset)
|
||||||
|
@ -127,8 +123,7 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
|
||||||
if offset+1 >= buflen {
|
if offset+1 >= buflen {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var rdlen uint16
|
rdlen := binary.BigEndian.Uint16(buf[offset:])
|
||||||
rdlen = binary.BigEndian.Uint16(buf[offset:])
|
|
||||||
offset += 2
|
offset += 2
|
||||||
offset += int(rdlen)
|
offset += int(rdlen)
|
||||||
}
|
}
|
||||||
|
@ -168,7 +163,7 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
|
||||||
}
|
}
|
||||||
// If key has come from the DNS name compression might
|
// If key has come from the DNS name compression might
|
||||||
// have mangled the case of the name
|
// 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"}
|
return &Error{err: "signer name doesn't match key name"}
|
||||||
}
|
}
|
||||||
sigend := offset
|
sigend := offset
|
||||||
|
|
10
vendor/github.com/miekg/dns/singleinflight.go
generated
vendored
10
vendor/github.com/miekg/dns/singleinflight.go
generated
vendored
|
@ -23,6 +23,8 @@ type call struct {
|
||||||
type singleflight struct {
|
type singleflight struct {
|
||||||
sync.Mutex // protects m
|
sync.Mutex // protects m
|
||||||
m map[string]*call // lazily initialized
|
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
|
// 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.val, c.rtt, c.err = fn()
|
||||||
c.wg.Done()
|
c.wg.Done()
|
||||||
|
|
||||||
g.Lock()
|
if !g.dontDeleteForTesting {
|
||||||
delete(g.m, key)
|
g.Lock()
|
||||||
g.Unlock()
|
delete(g.m, key)
|
||||||
|
g.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
return c.val, c.rtt, c.err, c.dups > 0
|
return c.val, c.rtt, c.err, c.dups > 0
|
||||||
}
|
}
|
||||||
|
|
5
vendor/github.com/miekg/dns/smimea.go
generated
vendored
5
vendor/github.com/miekg/dns/smimea.go
generated
vendored
|
@ -14,10 +14,7 @@ func (r *SMIMEA) Sign(usage, selector, matchingType int, cert *x509.Certificate)
|
||||||
r.MatchingType = uint8(matchingType)
|
r.MatchingType = uint8(matchingType)
|
||||||
|
|
||||||
r.Certificate, err = CertificateToDANE(r.Selector, r.MatchingType, cert)
|
r.Certificate, err = CertificateToDANE(r.Selector, r.MatchingType, cert)
|
||||||
if err != nil {
|
return err
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify verifies a SMIMEA record against an SSL certificate. If it is OK
|
// Verify verifies a SMIMEA record against an SSL certificate. If it is OK
|
||||||
|
|
5
vendor/github.com/miekg/dns/tlsa.go
generated
vendored
5
vendor/github.com/miekg/dns/tlsa.go
generated
vendored
|
@ -14,10 +14,7 @@ func (r *TLSA) Sign(usage, selector, matchingType int, cert *x509.Certificate) (
|
||||||
r.MatchingType = uint8(matchingType)
|
r.MatchingType = uint8(matchingType)
|
||||||
|
|
||||||
r.Certificate, err = CertificateToDANE(r.Selector, r.MatchingType, cert)
|
r.Certificate, err = CertificateToDANE(r.Selector, r.MatchingType, cert)
|
||||||
if err != nil {
|
return err
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify verifies a TLSA record against an SSL certificate. If it is OK
|
// Verify verifies a TLSA record against an SSL certificate. If it is OK
|
||||||
|
|
21
vendor/github.com/miekg/dns/tsig.go
generated
vendored
21
vendor/github.com/miekg/dns/tsig.go
generated
vendored
|
@ -54,6 +54,10 @@ func (rr *TSIG) String() string {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rr *TSIG) parse(c *zlexer, origin, file 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.
|
// The following values must be put in wireformat, so that the MAC can be calculated.
|
||||||
// RFC 2845, section 3.4.2. TSIG Variables.
|
// RFC 2845, section 3.4.2. TSIG Variables.
|
||||||
type tsigWireFmt struct {
|
type tsigWireFmt struct {
|
||||||
|
@ -113,13 +117,13 @@ func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, s
|
||||||
var h hash.Hash
|
var h hash.Hash
|
||||||
switch strings.ToLower(rr.Algorithm) {
|
switch strings.ToLower(rr.Algorithm) {
|
||||||
case HmacMD5:
|
case HmacMD5:
|
||||||
h = hmac.New(md5.New, []byte(rawsecret))
|
h = hmac.New(md5.New, rawsecret)
|
||||||
case HmacSHA1:
|
case HmacSHA1:
|
||||||
h = hmac.New(sha1.New, []byte(rawsecret))
|
h = hmac.New(sha1.New, rawsecret)
|
||||||
case HmacSHA256:
|
case HmacSHA256:
|
||||||
h = hmac.New(sha256.New, []byte(rawsecret))
|
h = hmac.New(sha256.New, rawsecret)
|
||||||
case HmacSHA512:
|
case HmacSHA512:
|
||||||
h = hmac.New(sha512.New, []byte(rawsecret))
|
h = hmac.New(sha512.New, rawsecret)
|
||||||
default:
|
default:
|
||||||
return nil, "", ErrKeyAlg
|
return nil, "", ErrKeyAlg
|
||||||
}
|
}
|
||||||
|
@ -133,13 +137,12 @@ func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, s
|
||||||
t.Algorithm = rr.Algorithm
|
t.Algorithm = rr.Algorithm
|
||||||
t.OrigId = m.Id
|
t.OrigId = m.Id
|
||||||
|
|
||||||
tbuf := make([]byte, t.len())
|
tbuf := make([]byte, Len(t))
|
||||||
if off, err := PackRR(t, tbuf, 0, nil, false); err == nil {
|
off, err := PackRR(t, tbuf, 0, nil, false)
|
||||||
tbuf = tbuf[:off] // reset to actual size used
|
if err != nil {
|
||||||
} else {
|
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
mbuf = append(mbuf, tbuf...)
|
mbuf = append(mbuf, tbuf[:off]...)
|
||||||
// Update the ArCount directly in the buffer.
|
// Update the ArCount directly in the buffer.
|
||||||
binary.BigEndian.PutUint16(mbuf[10:], uint16(len(m.Extra)+1))
|
binary.BigEndian.PutUint16(mbuf[10:], uint16(len(m.Extra)+1))
|
||||||
|
|
||||||
|
|
257
vendor/github.com/miekg/dns/types.go
generated
vendored
257
vendor/github.com/miekg/dns/types.go
generated
vendored
|
@ -205,9 +205,6 @@ var CertTypeToString = map[uint16]string{
|
||||||
CertOID: "OID",
|
CertOID: "OID",
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringToCertType is the reverseof CertTypeToString.
|
|
||||||
var StringToCertType = reverseInt16(CertTypeToString)
|
|
||||||
|
|
||||||
//go:generate go run types_generate.go
|
//go:generate go run types_generate.go
|
||||||
|
|
||||||
// Question holds a DNS question. There can be multiple questions in the
|
// Question holds a DNS question. There can be multiple questions in the
|
||||||
|
@ -218,8 +215,10 @@ type Question struct {
|
||||||
Qclass uint16
|
Qclass uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Question) len() int {
|
func (q *Question) len(off int, compression map[string]struct{}) int {
|
||||||
return len(q.Name) + 1 + 2 + 2
|
l := domainNameLen(q.Name, off, compression, true)
|
||||||
|
l += 2 + 2
|
||||||
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Question) String() (s string) {
|
func (q *Question) String() (s string) {
|
||||||
|
@ -239,6 +238,25 @@ type ANY struct {
|
||||||
|
|
||||||
func (rr *ANY) String() string { return rr.Hdr.String() }
|
func (rr *ANY) String() string { return rr.Hdr.String() }
|
||||||
|
|
||||||
|
func (rr *ANY) parse(c *zlexer, origin, file 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, file string) *ParseError {
|
||||||
|
panic("dns: internal error: parse should never be called on NULL")
|
||||||
|
}
|
||||||
|
|
||||||
// CNAME RR. See RFC 1034.
|
// CNAME RR. See RFC 1034.
|
||||||
type CNAME struct {
|
type CNAME struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
|
@ -330,7 +348,7 @@ func (rr *MX) String() string {
|
||||||
type AFSDB struct {
|
type AFSDB struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Subtype uint16
|
Subtype uint16
|
||||||
Hostname string `dns:"cdomain-name"`
|
Hostname string `dns:"domain-name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rr *AFSDB) String() string {
|
func (rr *AFSDB) String() string {
|
||||||
|
@ -351,7 +369,7 @@ func (rr *X25) String() string {
|
||||||
type RT struct {
|
type RT struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Preference uint16
|
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 {
|
func (rr *RT) String() string {
|
||||||
|
@ -419,128 +437,154 @@ type TXT struct {
|
||||||
func (rr *TXT) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
|
func (rr *TXT) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
|
||||||
|
|
||||||
func sprintName(s string) string {
|
func sprintName(s string) string {
|
||||||
src := []byte(s)
|
var dst strings.Builder
|
||||||
dst := make([]byte, 0, len(src))
|
dst.Grow(len(s))
|
||||||
for i := 0; i < len(src); {
|
for i := 0; i < len(s); {
|
||||||
if i+1 < len(src) && src[i] == '\\' && src[i+1] == '.' {
|
if i+1 < len(s) && s[i] == '\\' && s[i+1] == '.' {
|
||||||
dst = append(dst, src[i:i+2]...)
|
dst.WriteString(s[i : i+2])
|
||||||
i += 2
|
i += 2
|
||||||
} else {
|
continue
|
||||||
b, n := nextByte(src, i)
|
|
||||||
if n == 0 {
|
|
||||||
i++ // dangling back slash
|
|
||||||
} else if b == '.' {
|
|
||||||
dst = append(dst, b)
|
|
||||||
} else {
|
|
||||||
dst = appendDomainNameByte(dst, b)
|
|
||||||
}
|
|
||||||
i += n
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b, n := nextByte(s, i)
|
||||||
|
switch {
|
||||||
|
case n == 0:
|
||||||
|
i++ // dangling back slash
|
||||||
|
case b == '.':
|
||||||
|
dst.WriteByte('.')
|
||||||
|
default:
|
||||||
|
writeDomainNameByte(&dst, b)
|
||||||
|
}
|
||||||
|
i += n
|
||||||
}
|
}
|
||||||
return string(dst)
|
return dst.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func sprintTxtOctet(s string) string {
|
func sprintTxtOctet(s string) string {
|
||||||
src := []byte(s)
|
var dst strings.Builder
|
||||||
dst := make([]byte, 0, len(src))
|
dst.Grow(2 + len(s))
|
||||||
dst = append(dst, '"')
|
dst.WriteByte('"')
|
||||||
for i := 0; i < len(src); {
|
for i := 0; i < len(s); {
|
||||||
if i+1 < len(src) && src[i] == '\\' && src[i+1] == '.' {
|
if i+1 < len(s) && s[i] == '\\' && s[i+1] == '.' {
|
||||||
dst = append(dst, src[i:i+2]...)
|
dst.WriteString(s[i : i+2])
|
||||||
i += 2
|
i += 2
|
||||||
} else {
|
continue
|
||||||
b, n := nextByte(src, i)
|
|
||||||
if n == 0 {
|
|
||||||
i++ // dangling back slash
|
|
||||||
} else if b == '.' {
|
|
||||||
dst = append(dst, b)
|
|
||||||
} else {
|
|
||||||
if b < ' ' || b > '~' {
|
|
||||||
dst = appendByte(dst, b)
|
|
||||||
} else {
|
|
||||||
dst = append(dst, b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i += n
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b, n := nextByte(s, i)
|
||||||
|
switch {
|
||||||
|
case n == 0:
|
||||||
|
i++ // dangling back slash
|
||||||
|
case b == '.':
|
||||||
|
dst.WriteByte('.')
|
||||||
|
case b < ' ' || b > '~':
|
||||||
|
dst.WriteString(escapeByte(b))
|
||||||
|
default:
|
||||||
|
dst.WriteByte(b)
|
||||||
|
}
|
||||||
|
i += n
|
||||||
}
|
}
|
||||||
dst = append(dst, '"')
|
dst.WriteByte('"')
|
||||||
return string(dst)
|
return dst.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func sprintTxt(txt []string) string {
|
func sprintTxt(txt []string) string {
|
||||||
var out []byte
|
var out strings.Builder
|
||||||
for i, s := range txt {
|
for i, s := range txt {
|
||||||
|
out.Grow(3 + len(s))
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
out = append(out, ` "`...)
|
out.WriteString(` "`)
|
||||||
} else {
|
} else {
|
||||||
out = append(out, '"')
|
out.WriteByte('"')
|
||||||
}
|
}
|
||||||
bs := []byte(s)
|
for j := 0; j < len(s); {
|
||||||
for j := 0; j < len(bs); {
|
b, n := nextByte(s, j)
|
||||||
b, n := nextByte(bs, j)
|
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
out = appendTXTStringByte(out, b)
|
writeTXTStringByte(&out, b)
|
||||||
j += n
|
j += n
|
||||||
}
|
}
|
||||||
out = append(out, '"')
|
out.WriteByte('"')
|
||||||
}
|
}
|
||||||
return string(out)
|
return out.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func appendDomainNameByte(s []byte, b byte) []byte {
|
func writeDomainNameByte(s *strings.Builder, b byte) {
|
||||||
switch b {
|
switch b {
|
||||||
case '.', ' ', '\'', '@', ';', '(', ')': // additional chars to escape
|
case '.', ' ', '\'', '@', ';', '(', ')': // additional chars to escape
|
||||||
return append(s, '\\', b)
|
s.WriteByte('\\')
|
||||||
|
s.WriteByte(b)
|
||||||
|
default:
|
||||||
|
writeTXTStringByte(s, b)
|
||||||
}
|
}
|
||||||
return appendTXTStringByte(s, b)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func appendTXTStringByte(s []byte, b byte) []byte {
|
func writeTXTStringByte(s *strings.Builder, b byte) {
|
||||||
switch b {
|
switch {
|
||||||
case '"', '\\':
|
case b == '"' || b == '\\':
|
||||||
return append(s, '\\', b)
|
s.WriteByte('\\')
|
||||||
|
s.WriteByte(b)
|
||||||
|
case b < ' ' || b > '~':
|
||||||
|
s.WriteString(escapeByte(b))
|
||||||
|
default:
|
||||||
|
s.WriteByte(b)
|
||||||
}
|
}
|
||||||
if b < ' ' || b > '~' {
|
|
||||||
return appendByte(s, b)
|
|
||||||
}
|
|
||||||
return append(s, b)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func appendByte(s []byte, b byte) []byte {
|
const (
|
||||||
var buf [3]byte
|
escapedByteSmall = "" +
|
||||||
bufs := strconv.AppendInt(buf[:0], int64(b), 10)
|
`\000\001\002\003\004\005\006\007\008\009` +
|
||||||
s = append(s, '\\')
|
`\010\011\012\013\014\015\016\017\018\019` +
|
||||||
for i := 0; i < 3-len(bufs); i++ {
|
`\020\021\022\023\024\025\026\027\028\029` +
|
||||||
s = append(s, '0')
|
`\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]
|
||||||
}
|
}
|
||||||
for _, r := range bufs {
|
|
||||||
s = append(s, r)
|
b -= '~' + 1
|
||||||
}
|
// The cast here is needed as b*4 may overflow byte.
|
||||||
return s
|
return escapedByteLarge[int(b)*4 : int(b)*4+4]
|
||||||
}
|
}
|
||||||
|
|
||||||
func nextByte(b []byte, offset int) (byte, int) {
|
func nextByte(s string, offset int) (byte, int) {
|
||||||
if offset >= len(b) {
|
if offset >= len(s) {
|
||||||
return 0, 0
|
return 0, 0
|
||||||
}
|
}
|
||||||
if b[offset] != '\\' {
|
if s[offset] != '\\' {
|
||||||
// not an escape sequence
|
// not an escape sequence
|
||||||
return b[offset], 1
|
return s[offset], 1
|
||||||
}
|
}
|
||||||
switch len(b) - offset {
|
switch len(s) - offset {
|
||||||
case 1: // dangling escape
|
case 1: // dangling escape
|
||||||
return 0, 0
|
return 0, 0
|
||||||
case 2, 3: // too short to be \ddd
|
case 2, 3: // too short to be \ddd
|
||||||
default: // maybe \ddd
|
default: // maybe \ddd
|
||||||
if isDigit(b[offset+1]) && isDigit(b[offset+2]) && isDigit(b[offset+3]) {
|
if isDigit(s[offset+1]) && isDigit(s[offset+2]) && isDigit(s[offset+3]) {
|
||||||
return dddToByte(b[offset+1:]), 4
|
return dddStringToByte(s[offset+1:]), 4
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// not \ddd, just an RFC 1035 "quoted" character
|
// not \ddd, just an RFC 1035 "quoted" character
|
||||||
return b[offset+1], 2
|
return s[offset+1], 2
|
||||||
}
|
}
|
||||||
|
|
||||||
// SPF RR. See RFC 4408, Section 3.1.1.
|
// SPF RR. See RFC 4408, Section 3.1.1.
|
||||||
|
@ -728,7 +772,7 @@ func (rr *LOC) String() string {
|
||||||
lat = lat % LOC_DEGREES
|
lat = lat % LOC_DEGREES
|
||||||
m := lat / LOC_HOURS
|
m := lat / LOC_HOURS
|
||||||
lat = lat % LOC_HOURS
|
lat = lat % LOC_HOURS
|
||||||
s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, (float64(lat) / 1000), ns)
|
s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, float64(lat)/1000, ns)
|
||||||
|
|
||||||
lon := rr.Longitude
|
lon := rr.Longitude
|
||||||
ew := "E"
|
ew := "E"
|
||||||
|
@ -742,7 +786,7 @@ func (rr *LOC) String() string {
|
||||||
lon = lon % LOC_DEGREES
|
lon = lon % LOC_DEGREES
|
||||||
m = lon / LOC_HOURS
|
m = lon / LOC_HOURS
|
||||||
lon = lon % LOC_HOURS
|
lon = lon % LOC_HOURS
|
||||||
s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, (float64(lon) / 1000), ew)
|
s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, float64(lon)/1000, ew)
|
||||||
|
|
||||||
var alt = float64(rr.Altitude) / 100
|
var alt = float64(rr.Altitude) / 100
|
||||||
alt -= LOC_ALTITUDEBASE
|
alt -= LOC_ALTITUDEBASE
|
||||||
|
@ -752,9 +796,9 @@ func (rr *LOC) String() string {
|
||||||
s += fmt.Sprintf("%.0fm ", alt)
|
s += fmt.Sprintf("%.0fm ", alt)
|
||||||
}
|
}
|
||||||
|
|
||||||
s += cmToM((rr.Size&0xf0)>>4, rr.Size&0x0f) + "m "
|
s += cmToM(rr.Size&0xf0>>4, rr.Size&0x0f) + "m "
|
||||||
s += cmToM((rr.HorizPre&0xf0)>>4, rr.HorizPre&0x0f) + "m "
|
s += cmToM(rr.HorizPre&0xf0>>4, rr.HorizPre&0x0f) + "m "
|
||||||
s += cmToM((rr.VertPre&0xf0)>>4, rr.VertPre&0x0f) + "m"
|
s += cmToM(rr.VertPre&0xf0>>4, rr.VertPre&0x0f) + "m"
|
||||||
|
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
@ -807,8 +851,9 @@ func (rr *NSEC) String() string {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rr *NSEC) len() int {
|
func (rr *NSEC) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len() + len(rr.NextDomain) + 1
|
l := rr.Hdr.len(off, compression)
|
||||||
|
l += domainNameLen(rr.NextDomain, off+l, compression, false)
|
||||||
lastwindow := uint32(2 ^ 32 + 1)
|
lastwindow := uint32(2 ^ 32 + 1)
|
||||||
for _, t := range rr.TypeBitMap {
|
for _, t := range rr.TypeBitMap {
|
||||||
window := t / 256
|
window := t / 256
|
||||||
|
@ -972,8 +1017,9 @@ func (rr *NSEC3) String() string {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rr *NSEC3) len() int {
|
func (rr *NSEC3) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len() + 6 + len(rr.Salt)/2 + 1 + len(rr.NextDomain) + 1
|
l := rr.Hdr.len(off, compression)
|
||||||
|
l += 6 + len(rr.Salt)/2 + 1 + len(rr.NextDomain) + 1
|
||||||
lastwindow := uint32(2 ^ 32 + 1)
|
lastwindow := uint32(2 ^ 32 + 1)
|
||||||
for _, t := range rr.TypeBitMap {
|
for _, t := range rr.TypeBitMap {
|
||||||
window := t / 256
|
window := t / 256
|
||||||
|
@ -1020,10 +1066,16 @@ type TKEY struct {
|
||||||
|
|
||||||
// TKEY has no official presentation format, but this will suffice.
|
// TKEY has no official presentation format, but this will suffice.
|
||||||
func (rr *TKEY) String() string {
|
func (rr *TKEY) String() string {
|
||||||
s := "\n;; TKEY PSEUDOSECTION:\n"
|
s := ";" + rr.Hdr.String() +
|
||||||
s += rr.Hdr.String() + " " + rr.Algorithm + " " +
|
" " + rr.Algorithm +
|
||||||
strconv.Itoa(int(rr.KeySize)) + " " + rr.Key + " " +
|
" " + TimeToString(rr.Inception) +
|
||||||
strconv.Itoa(int(rr.OtherLen)) + " " + rr.OtherData
|
" " + 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
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1289,8 +1341,9 @@ func (rr *CSYNC) String() string {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rr *CSYNC) len() int {
|
func (rr *CSYNC) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len() + 4 + 2
|
l := rr.Hdr.len(off, compression)
|
||||||
|
l += 4 + 2
|
||||||
lastwindow := uint32(2 ^ 32 + 1)
|
lastwindow := uint32(2 ^ 32 + 1)
|
||||||
for _, t := range rr.TypeBitMap {
|
for _, t := range rr.TypeBitMap {
|
||||||
window := t / 256
|
window := t / 256
|
||||||
|
@ -1306,11 +1359,11 @@ func (rr *CSYNC) len() int {
|
||||||
// string representation used when printing the record.
|
// string representation used when printing the record.
|
||||||
// It takes serial arithmetic (RFC 1982) into account.
|
// It takes serial arithmetic (RFC 1982) into account.
|
||||||
func TimeToString(t uint32) string {
|
func TimeToString(t uint32) string {
|
||||||
mod := ((int64(t) - time.Now().Unix()) / year68) - 1
|
mod := (int64(t)-time.Now().Unix())/year68 - 1
|
||||||
if mod < 0 {
|
if mod < 0 {
|
||||||
mod = 0
|
mod = 0
|
||||||
}
|
}
|
||||||
ti := time.Unix(int64(t)-(mod*year68), 0).UTC()
|
ti := time.Unix(int64(t)-mod*year68, 0).UTC()
|
||||||
return ti.Format("20060102150405")
|
return ti.Format("20060102150405")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1322,11 +1375,11 @@ func StringToTime(s string) (uint32, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
mod := (t.Unix() / year68) - 1
|
mod := t.Unix()/year68 - 1
|
||||||
if mod < 0 {
|
if mod < 0 {
|
||||||
mod = 0
|
mod = 0
|
||||||
}
|
}
|
||||||
return uint32(t.Unix() - (mod * year68)), nil
|
return uint32(t.Unix() - mod*year68), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// saltToString converts a NSECX salt to uppercase and returns "-" when it is empty.
|
// saltToString converts a NSECX salt to uppercase and returns "-" when it is empty.
|
||||||
|
|
27
vendor/github.com/miekg/dns/types_generate.go
generated
vendored
27
vendor/github.com/miekg/dns/types_generate.go
generated
vendored
|
@ -153,8 +153,8 @@ func main() {
|
||||||
if isEmbedded {
|
if isEmbedded {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
fmt.Fprintf(b, "func (rr *%s) len() int {\n", name)
|
fmt.Fprintf(b, "func (rr *%s) len(off int, compression map[string]struct{}) int {\n", name)
|
||||||
fmt.Fprintf(b, "l := rr.Hdr.len()\n")
|
fmt.Fprintf(b, "l := rr.Hdr.len(off, compression)\n")
|
||||||
for i := 1; i < st.NumFields(); i++ {
|
for i := 1; i < st.NumFields(); i++ {
|
||||||
o := func(s string) { fmt.Fprintf(b, s, st.Field(i).Name()) }
|
o := func(s string) { fmt.Fprintf(b, s, st.Field(i).Name()) }
|
||||||
|
|
||||||
|
@ -162,7 +162,11 @@ func main() {
|
||||||
switch st.Tag(i) {
|
switch st.Tag(i) {
|
||||||
case `dns:"-"`:
|
case `dns:"-"`:
|
||||||
// ignored
|
// ignored
|
||||||
case `dns:"cdomain-name"`, `dns:"domain-name"`, `dns:"txt"`:
|
case `dns:"cdomain-name"`:
|
||||||
|
o("for _, x := range rr.%s { l += domainNameLen(x, off+l, compression, true) }\n")
|
||||||
|
case `dns:"domain-name"`:
|
||||||
|
o("for _, x := range rr.%s { l += domainNameLen(x, off+l, compression, false) }\n")
|
||||||
|
case `dns:"txt"`:
|
||||||
o("for _, x := range rr.%s { l += len(x) + 1 }\n")
|
o("for _, x := range rr.%s { l += len(x) + 1 }\n")
|
||||||
default:
|
default:
|
||||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||||
|
@ -173,8 +177,10 @@ func main() {
|
||||||
switch {
|
switch {
|
||||||
case st.Tag(i) == `dns:"-"`:
|
case st.Tag(i) == `dns:"-"`:
|
||||||
// ignored
|
// ignored
|
||||||
case st.Tag(i) == `dns:"cdomain-name"`, st.Tag(i) == `dns:"domain-name"`:
|
case st.Tag(i) == `dns:"cdomain-name"`:
|
||||||
o("l += len(rr.%s) + 1\n")
|
o("l += domainNameLen(rr.%s, off+l, compression, true)\n")
|
||||||
|
case st.Tag(i) == `dns:"domain-name"`:
|
||||||
|
o("l += domainNameLen(rr.%s, off+l, compression, false)\n")
|
||||||
case st.Tag(i) == `dns:"octet"`:
|
case st.Tag(i) == `dns:"octet"`:
|
||||||
o("l += len(rr.%s)\n")
|
o("l += len(rr.%s)\n")
|
||||||
case strings.HasPrefix(st.Tag(i), `dns:"size-base64`):
|
case strings.HasPrefix(st.Tag(i), `dns:"size-base64`):
|
||||||
|
@ -187,6 +193,8 @@ func main() {
|
||||||
fallthrough
|
fallthrough
|
||||||
case st.Tag(i) == `dns:"hex"`:
|
case st.Tag(i) == `dns:"hex"`:
|
||||||
o("l += len(rr.%s)/2 + 1\n")
|
o("l += len(rr.%s)/2 + 1\n")
|
||||||
|
case st.Tag(i) == `dns:"any"`:
|
||||||
|
o("l += len(rr.%s)\n")
|
||||||
case st.Tag(i) == `dns:"a"`:
|
case st.Tag(i) == `dns:"a"`:
|
||||||
o("l += net.IPv4len // %s\n")
|
o("l += net.IPv4len // %s\n")
|
||||||
case st.Tag(i) == `dns:"aaaa"`:
|
case st.Tag(i) == `dns:"aaaa"`:
|
||||||
|
@ -226,7 +234,7 @@ func main() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
fmt.Fprintf(b, "func (rr *%s) copy() RR {\n", name)
|
fmt.Fprintf(b, "func (rr *%s) copy() RR {\n", name)
|
||||||
fields := []string{"*rr.Hdr.copyHeader()"}
|
fields := []string{"rr.Hdr"}
|
||||||
for i := 1; i < st.NumFields(); i++ {
|
for i := 1; i < st.NumFields(); i++ {
|
||||||
f := st.Field(i).Name()
|
f := st.Field(i).Name()
|
||||||
if sl, ok := st.Field(i).Type().(*types.Slice); ok {
|
if sl, ok := st.Field(i).Type().(*types.Slice); ok {
|
||||||
|
@ -236,6 +244,13 @@ func main() {
|
||||||
splits := strings.Split(t, ".")
|
splits := strings.Split(t, ".")
|
||||||
t = splits[len(splits)-1]
|
t = splits[len(splits)-1]
|
||||||
}
|
}
|
||||||
|
// For the EDNS0 interface (used in the OPT RR), we need to call the copy method on each element.
|
||||||
|
if t == "EDNS0" {
|
||||||
|
fmt.Fprintf(b, "%s := make([]%s, len(rr.%s));\nfor i,e := range rr.%s {\n %s[i] = e.copy()\n}\n",
|
||||||
|
f, t, f, f, f)
|
||||||
|
fields = append(fields, f)
|
||||||
|
continue
|
||||||
|
}
|
||||||
fmt.Fprintf(b, "%s := make([]%s, len(rr.%s)); copy(%s, rr.%s)\n",
|
fmt.Fprintf(b, "%s := make([]%s, len(rr.%s)); copy(%s, rr.%s)\n",
|
||||||
f, t, f, f, f)
|
f, t, f, f, f)
|
||||||
fields = append(fields, f)
|
fields = append(fields, f)
|
||||||
|
|
33
vendor/github.com/miekg/dns/udp.go
generated
vendored
33
vendor/github.com/miekg/dns/udp.go
generated
vendored
|
@ -9,6 +9,22 @@ import (
|
||||||
"golang.org/x/net/ipv6"
|
"golang.org/x/net/ipv6"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// This is the required size of the OOB buffer to pass to ReadMsgUDP.
|
||||||
|
var udpOOBSize = func() int {
|
||||||
|
// We can't know whether we'll get an IPv4 control message or an
|
||||||
|
// IPv6 control message ahead of time. To get around this, we size
|
||||||
|
// the buffer equal to the largest of the two.
|
||||||
|
|
||||||
|
oob4 := ipv4.NewControlMessage(ipv4.FlagDst | ipv4.FlagInterface)
|
||||||
|
oob6 := ipv6.NewControlMessage(ipv6.FlagDst | ipv6.FlagInterface)
|
||||||
|
|
||||||
|
if len(oob4) > len(oob6) {
|
||||||
|
return len(oob4)
|
||||||
|
}
|
||||||
|
|
||||||
|
return len(oob6)
|
||||||
|
}()
|
||||||
|
|
||||||
// SessionUDP holds the remote address and the associated
|
// SessionUDP holds the remote address and the associated
|
||||||
// out-of-band data.
|
// out-of-band data.
|
||||||
type SessionUDP struct {
|
type SessionUDP struct {
|
||||||
|
@ -22,7 +38,7 @@ func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
|
||||||
// ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
|
// ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
|
||||||
// net.UDPAddr.
|
// net.UDPAddr.
|
||||||
func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
|
func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
|
||||||
oob := make([]byte, 40)
|
oob := make([]byte, udpOOBSize)
|
||||||
n, oobn, _, raddr, err := conn.ReadMsgUDP(b, oob)
|
n, oobn, _, raddr, err := conn.ReadMsgUDP(b, oob)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return n, nil, err
|
return n, nil, err
|
||||||
|
@ -53,18 +69,15 @@ func parseDstFromOOB(oob []byte) net.IP {
|
||||||
// Start with IPv6 and then fallback to IPv4
|
// Start with IPv6 and then fallback to IPv4
|
||||||
// TODO(fastest963): Figure out a way to prefer one or the other. Looking at
|
// TODO(fastest963): Figure out a way to prefer one or the other. Looking at
|
||||||
// the lvl of the header for a 0 or 41 isn't cross-platform.
|
// the lvl of the header for a 0 or 41 isn't cross-platform.
|
||||||
var dst net.IP
|
|
||||||
cm6 := new(ipv6.ControlMessage)
|
cm6 := new(ipv6.ControlMessage)
|
||||||
if cm6.Parse(oob) == nil {
|
if cm6.Parse(oob) == nil && cm6.Dst != nil {
|
||||||
dst = cm6.Dst
|
return cm6.Dst
|
||||||
}
|
}
|
||||||
if dst == nil {
|
cm4 := new(ipv4.ControlMessage)
|
||||||
cm4 := new(ipv4.ControlMessage)
|
if cm4.Parse(oob) == nil && cm4.Dst != nil {
|
||||||
if cm4.Parse(oob) == nil {
|
return cm4.Dst
|
||||||
dst = cm4.Dst
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return dst
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// correctSource takes oob data and returns new oob data with the Src equal to the Dst
|
// correctSource takes oob data and returns new oob data with the Src equal to the Dst
|
||||||
|
|
6
vendor/github.com/miekg/dns/udp_windows.go
generated
vendored
6
vendor/github.com/miekg/dns/udp_windows.go
generated
vendored
|
@ -20,15 +20,13 @@ func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return n, nil, err
|
return n, nil, err
|
||||||
}
|
}
|
||||||
session := &SessionUDP{raddr.(*net.UDPAddr)}
|
return n, &SessionUDP{raddr.(*net.UDPAddr)}, err
|
||||||
return n, session, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteToSessionUDP acts just like net.UDPConn.WriteTo(), but uses a *SessionUDP instead of a net.Addr.
|
// WriteToSessionUDP acts just like net.UDPConn.WriteTo(), but uses a *SessionUDP instead of a net.Addr.
|
||||||
// TODO(fastest963): Once go1.10 is released, use WriteMsgUDP.
|
// TODO(fastest963): Once go1.10 is released, use WriteMsgUDP.
|
||||||
func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
|
func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
|
||||||
n, err := conn.WriteTo(b, session.raddr)
|
return conn.WriteTo(b, session.raddr)
|
||||||
return n, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(fastest963): Once go1.10 is released and we can use *MsgUDP methods
|
// TODO(fastest963): Once go1.10 is released and we can use *MsgUDP methods
|
||||||
|
|
14
vendor/github.com/miekg/dns/update.go
generated
vendored
14
vendor/github.com/miekg/dns/update.go
generated
vendored
|
@ -44,7 +44,8 @@ func (u *Msg) RRsetUsed(rr []RR) {
|
||||||
u.Answer = make([]RR, 0, len(rr))
|
u.Answer = make([]RR, 0, len(rr))
|
||||||
}
|
}
|
||||||
for _, r := range 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))
|
u.Answer = make([]RR, 0, len(rr))
|
||||||
}
|
}
|
||||||
for _, r := range 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))
|
u.Ns = make([]RR, 0, len(rr))
|
||||||
}
|
}
|
||||||
for _, r := range 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))
|
u.Ns = make([]RR, 0, len(rr))
|
||||||
}
|
}
|
||||||
for _, r := range rr {
|
for _, r := range rr {
|
||||||
r.Header().Class = ClassNONE
|
h := r.Header()
|
||||||
r.Header().Ttl = 0
|
h.Class = ClassNONE
|
||||||
|
h.Ttl = 0
|
||||||
u.Ns = append(u.Ns, r)
|
u.Ns = append(u.Ns, r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
vendor/github.com/miekg/dns/version.go
generated
vendored
2
vendor/github.com/miekg/dns/version.go
generated
vendored
|
@ -3,7 +3,7 @@ package dns
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
// Version is current version of this library.
|
// Version is current version of this library.
|
||||||
var Version = V{1, 0, 4}
|
var Version = V{1, 1, 4}
|
||||||
|
|
||||||
// V holds the version of this library.
|
// V holds the version of this library.
|
||||||
type V struct {
|
type V struct {
|
||||||
|
|
46
vendor/github.com/miekg/dns/xfr.go
generated
vendored
46
vendor/github.com/miekg/dns/xfr.go
generated
vendored
|
@ -35,30 +35,36 @@ type Transfer struct {
|
||||||
// channel, err := transfer.In(message, master)
|
// channel, err := transfer.In(message, master)
|
||||||
//
|
//
|
||||||
func (t *Transfer) In(q *Msg, a string) (env chan *Envelope, err error) {
|
func (t *Transfer) In(q *Msg, a string) (env chan *Envelope, err error) {
|
||||||
|
switch q.Question[0].Qtype {
|
||||||
|
case TypeAXFR, TypeIXFR:
|
||||||
|
default:
|
||||||
|
return nil, &Error{"unsupported question type"}
|
||||||
|
}
|
||||||
|
|
||||||
timeout := dnsTimeout
|
timeout := dnsTimeout
|
||||||
if t.DialTimeout != 0 {
|
if t.DialTimeout != 0 {
|
||||||
timeout = t.DialTimeout
|
timeout = t.DialTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.Conn == nil {
|
if t.Conn == nil {
|
||||||
t.Conn, err = DialTimeout("tcp", a, timeout)
|
t.Conn, err = DialTimeout("tcp", a, timeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := t.WriteMsg(q); err != nil {
|
if err := t.WriteMsg(q); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
env = make(chan *Envelope)
|
env = make(chan *Envelope)
|
||||||
go func() {
|
switch q.Question[0].Qtype {
|
||||||
if q.Question[0].Qtype == TypeAXFR {
|
case TypeAXFR:
|
||||||
go t.inAxfr(q, env)
|
go t.inAxfr(q, env)
|
||||||
return
|
case TypeIXFR:
|
||||||
}
|
go t.inIxfr(q, env)
|
||||||
if q.Question[0].Qtype == TypeIXFR {
|
}
|
||||||
go t.inIxfr(q, env)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
return env, nil
|
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) {
|
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
|
axfr := true
|
||||||
n := 0
|
n := 0
|
||||||
qser := q.Ns[0].(*SOA).Serial
|
qser := q.Ns[0].(*SOA).Serial
|
||||||
|
@ -237,24 +243,18 @@ func (t *Transfer) WriteMsg(m *Msg) (err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err = t.Write(out); err != nil {
|
_, err = t.Write(out)
|
||||||
return err
|
return err
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func isSOAFirst(in *Msg) bool {
|
func isSOAFirst(in *Msg) bool {
|
||||||
if len(in.Answer) > 0 {
|
return len(in.Answer) > 0 &&
|
||||||
return in.Answer[0].Header().Rrtype == TypeSOA
|
in.Answer[0].Header().Rrtype == TypeSOA
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func isSOALast(in *Msg) bool {
|
func isSOALast(in *Msg) bool {
|
||||||
if len(in.Answer) > 0 {
|
return len(in.Answer) > 0 &&
|
||||||
return in.Answer[len(in.Answer)-1].Header().Rrtype == TypeSOA
|
in.Answer[len(in.Answer)-1].Header().Rrtype == TypeSOA
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const errXFR = "bad xfr rcode: %d"
|
const errXFR = "bad xfr rcode: %d"
|
||||||
|
|
118
vendor/github.com/miekg/dns/zcompress.go
generated
vendored
118
vendor/github.com/miekg/dns/zcompress.go
generated
vendored
|
@ -1,118 +0,0 @@
|
||||||
// Code generated by "go run compress_generate.go"; DO NOT EDIT.
|
|
||||||
|
|
||||||
package dns
|
|
||||||
|
|
||||||
func compressionLenHelperType(c map[string]int, r RR) {
|
|
||||||
switch x := r.(type) {
|
|
||||||
case *AFSDB:
|
|
||||||
compressionLenHelper(c, x.Hostname)
|
|
||||||
case *CNAME:
|
|
||||||
compressionLenHelper(c, x.Target)
|
|
||||||
case *DNAME:
|
|
||||||
compressionLenHelper(c, x.Target)
|
|
||||||
case *HIP:
|
|
||||||
for i := range x.RendezvousServers {
|
|
||||||
compressionLenHelper(c, x.RendezvousServers[i])
|
|
||||||
}
|
|
||||||
case *KX:
|
|
||||||
compressionLenHelper(c, x.Exchanger)
|
|
||||||
case *LP:
|
|
||||||
compressionLenHelper(c, x.Fqdn)
|
|
||||||
case *MB:
|
|
||||||
compressionLenHelper(c, x.Mb)
|
|
||||||
case *MD:
|
|
||||||
compressionLenHelper(c, x.Md)
|
|
||||||
case *MF:
|
|
||||||
compressionLenHelper(c, x.Mf)
|
|
||||||
case *MG:
|
|
||||||
compressionLenHelper(c, x.Mg)
|
|
||||||
case *MINFO:
|
|
||||||
compressionLenHelper(c, x.Rmail)
|
|
||||||
compressionLenHelper(c, x.Email)
|
|
||||||
case *MR:
|
|
||||||
compressionLenHelper(c, x.Mr)
|
|
||||||
case *MX:
|
|
||||||
compressionLenHelper(c, x.Mx)
|
|
||||||
case *NAPTR:
|
|
||||||
compressionLenHelper(c, x.Replacement)
|
|
||||||
case *NS:
|
|
||||||
compressionLenHelper(c, x.Ns)
|
|
||||||
case *NSAPPTR:
|
|
||||||
compressionLenHelper(c, x.Ptr)
|
|
||||||
case *NSEC:
|
|
||||||
compressionLenHelper(c, x.NextDomain)
|
|
||||||
case *PTR:
|
|
||||||
compressionLenHelper(c, x.Ptr)
|
|
||||||
case *PX:
|
|
||||||
compressionLenHelper(c, x.Map822)
|
|
||||||
compressionLenHelper(c, x.Mapx400)
|
|
||||||
case *RP:
|
|
||||||
compressionLenHelper(c, x.Mbox)
|
|
||||||
compressionLenHelper(c, x.Txt)
|
|
||||||
case *RRSIG:
|
|
||||||
compressionLenHelper(c, x.SignerName)
|
|
||||||
case *RT:
|
|
||||||
compressionLenHelper(c, x.Host)
|
|
||||||
case *SIG:
|
|
||||||
compressionLenHelper(c, x.SignerName)
|
|
||||||
case *SOA:
|
|
||||||
compressionLenHelper(c, x.Ns)
|
|
||||||
compressionLenHelper(c, x.Mbox)
|
|
||||||
case *SRV:
|
|
||||||
compressionLenHelper(c, x.Target)
|
|
||||||
case *TALINK:
|
|
||||||
compressionLenHelper(c, x.PreviousName)
|
|
||||||
compressionLenHelper(c, x.NextName)
|
|
||||||
case *TKEY:
|
|
||||||
compressionLenHelper(c, x.Algorithm)
|
|
||||||
case *TSIG:
|
|
||||||
compressionLenHelper(c, x.Algorithm)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func compressionLenSearchType(c map[string]int, r RR) (int, bool) {
|
|
||||||
switch x := r.(type) {
|
|
||||||
case *AFSDB:
|
|
||||||
k1, ok1 := compressionLenSearch(c, x.Hostname)
|
|
||||||
return k1, ok1
|
|
||||||
case *CNAME:
|
|
||||||
k1, ok1 := compressionLenSearch(c, x.Target)
|
|
||||||
return k1, ok1
|
|
||||||
case *MB:
|
|
||||||
k1, ok1 := compressionLenSearch(c, x.Mb)
|
|
||||||
return k1, ok1
|
|
||||||
case *MD:
|
|
||||||
k1, ok1 := compressionLenSearch(c, x.Md)
|
|
||||||
return k1, ok1
|
|
||||||
case *MF:
|
|
||||||
k1, ok1 := compressionLenSearch(c, x.Mf)
|
|
||||||
return k1, ok1
|
|
||||||
case *MG:
|
|
||||||
k1, ok1 := compressionLenSearch(c, x.Mg)
|
|
||||||
return k1, ok1
|
|
||||||
case *MINFO:
|
|
||||||
k1, ok1 := compressionLenSearch(c, x.Rmail)
|
|
||||||
k2, ok2 := compressionLenSearch(c, x.Email)
|
|
||||||
return k1 + k2, ok1 && ok2
|
|
||||||
case *MR:
|
|
||||||
k1, ok1 := compressionLenSearch(c, x.Mr)
|
|
||||||
return k1, ok1
|
|
||||||
case *MX:
|
|
||||||
k1, ok1 := compressionLenSearch(c, x.Mx)
|
|
||||||
return k1, ok1
|
|
||||||
case *NS:
|
|
||||||
k1, ok1 := compressionLenSearch(c, x.Ns)
|
|
||||||
return k1, ok1
|
|
||||||
case *PTR:
|
|
||||||
k1, ok1 := compressionLenSearch(c, x.Ptr)
|
|
||||||
return k1, ok1
|
|
||||||
case *RT:
|
|
||||||
k1, ok1 := compressionLenSearch(c, x.Host)
|
|
||||||
return k1, ok1
|
|
||||||
case *SOA:
|
|
||||||
k1, ok1 := compressionLenSearch(c, x.Ns)
|
|
||||||
k2, ok2 := compressionLenSearch(c, x.Mbox)
|
|
||||||
return k1 + k2, ok1 && ok2
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
1140
vendor/github.com/miekg/dns/zduplicate.go
generated
vendored
Normal file
1140
vendor/github.com/miekg/dns/zduplicate.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
2039
vendor/github.com/miekg/dns/zmsg.go
generated
vendored
2039
vendor/github.com/miekg/dns/zmsg.go
generated
vendored
File diff suppressed because it is too large
Load diff
450
vendor/github.com/miekg/dns/ztypes.go
generated
vendored
450
vendor/github.com/miekg/dns/ztypes.go
generated
vendored
|
@ -54,6 +54,7 @@ var TypeToRR = map[uint16]func() RR{
|
||||||
TypeNSEC: func() RR { return new(NSEC) },
|
TypeNSEC: func() RR { return new(NSEC) },
|
||||||
TypeNSEC3: func() RR { return new(NSEC3) },
|
TypeNSEC3: func() RR { return new(NSEC3) },
|
||||||
TypeNSEC3PARAM: func() RR { return new(NSEC3PARAM) },
|
TypeNSEC3PARAM: func() RR { return new(NSEC3PARAM) },
|
||||||
|
TypeNULL: func() RR { return new(NULL) },
|
||||||
TypeOPENPGPKEY: func() RR { return new(OPENPGPKEY) },
|
TypeOPENPGPKEY: func() RR { return new(OPENPGPKEY) },
|
||||||
TypeOPT: func() RR { return new(OPT) },
|
TypeOPT: func() RR { return new(OPT) },
|
||||||
TypePTR: func() RR { return new(PTR) },
|
TypePTR: func() RR { return new(PTR) },
|
||||||
|
@ -209,6 +210,7 @@ func (rr *NSAPPTR) Header() *RR_Header { return &rr.Hdr }
|
||||||
func (rr *NSEC) 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 *NSEC3) Header() *RR_Header { return &rr.Hdr }
|
||||||
func (rr *NSEC3PARAM) 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 *OPENPGPKEY) Header() *RR_Header { return &rr.Hdr }
|
||||||
func (rr *OPT) Header() *RR_Header { return &rr.Hdr }
|
func (rr *OPT) Header() *RR_Header { return &rr.Hdr }
|
||||||
func (rr *PTR) Header() *RR_Header { return &rr.Hdr }
|
func (rr *PTR) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
@ -236,144 +238,144 @@ func (rr *URI) Header() *RR_Header { return &rr.Hdr }
|
||||||
func (rr *X25) Header() *RR_Header { return &rr.Hdr }
|
func (rr *X25) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
|
||||||
// len() functions
|
// len() functions
|
||||||
func (rr *A) len() int {
|
func (rr *A) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += net.IPv4len // A
|
l += net.IPv4len // A
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *AAAA) len() int {
|
func (rr *AAAA) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += net.IPv6len // AAAA
|
l += net.IPv6len // AAAA
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *AFSDB) len() int {
|
func (rr *AFSDB) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += 2 // Subtype
|
l += 2 // Subtype
|
||||||
l += len(rr.Hostname) + 1
|
l += domainNameLen(rr.Hostname, off+l, compression, false)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *ANY) len() int {
|
func (rr *ANY) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *AVC) len() int {
|
func (rr *AVC) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
for _, x := range rr.Txt {
|
for _, x := range rr.Txt {
|
||||||
l += len(x) + 1
|
l += len(x) + 1
|
||||||
}
|
}
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *CAA) len() int {
|
func (rr *CAA) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l++ // Flag
|
l++ // Flag
|
||||||
l += len(rr.Tag) + 1
|
l += len(rr.Tag) + 1
|
||||||
l += len(rr.Value)
|
l += len(rr.Value)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *CERT) len() int {
|
func (rr *CERT) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += 2 // Type
|
l += 2 // Type
|
||||||
l += 2 // KeyTag
|
l += 2 // KeyTag
|
||||||
l++ // Algorithm
|
l++ // Algorithm
|
||||||
l += base64.StdEncoding.DecodedLen(len(rr.Certificate))
|
l += base64.StdEncoding.DecodedLen(len(rr.Certificate))
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *CNAME) len() int {
|
func (rr *CNAME) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += len(rr.Target) + 1
|
l += domainNameLen(rr.Target, off+l, compression, true)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *DHCID) len() int {
|
func (rr *DHCID) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += base64.StdEncoding.DecodedLen(len(rr.Digest))
|
l += base64.StdEncoding.DecodedLen(len(rr.Digest))
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *DNAME) len() int {
|
func (rr *DNAME) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += len(rr.Target) + 1
|
l += domainNameLen(rr.Target, off+l, compression, false)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *DNSKEY) len() int {
|
func (rr *DNSKEY) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += 2 // Flags
|
l += 2 // Flags
|
||||||
l++ // Protocol
|
l++ // Protocol
|
||||||
l++ // Algorithm
|
l++ // Algorithm
|
||||||
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
|
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *DS) len() int {
|
func (rr *DS) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += 2 // KeyTag
|
l += 2 // KeyTag
|
||||||
l++ // Algorithm
|
l++ // Algorithm
|
||||||
l++ // DigestType
|
l++ // DigestType
|
||||||
l += len(rr.Digest)/2 + 1
|
l += len(rr.Digest)/2 + 1
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *EID) len() int {
|
func (rr *EID) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += len(rr.Endpoint)/2 + 1
|
l += len(rr.Endpoint)/2 + 1
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *EUI48) len() int {
|
func (rr *EUI48) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += 6 // Address
|
l += 6 // Address
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *EUI64) len() int {
|
func (rr *EUI64) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += 8 // Address
|
l += 8 // Address
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *GID) len() int {
|
func (rr *GID) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += 4 // Gid
|
l += 4 // Gid
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *GPOS) len() int {
|
func (rr *GPOS) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += len(rr.Longitude) + 1
|
l += len(rr.Longitude) + 1
|
||||||
l += len(rr.Latitude) + 1
|
l += len(rr.Latitude) + 1
|
||||||
l += len(rr.Altitude) + 1
|
l += len(rr.Altitude) + 1
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *HINFO) len() int {
|
func (rr *HINFO) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += len(rr.Cpu) + 1
|
l += len(rr.Cpu) + 1
|
||||||
l += len(rr.Os) + 1
|
l += len(rr.Os) + 1
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *HIP) len() int {
|
func (rr *HIP) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l++ // HitLength
|
l++ // HitLength
|
||||||
l++ // PublicKeyAlgorithm
|
l++ // PublicKeyAlgorithm
|
||||||
l += 2 // PublicKeyLength
|
l += 2 // PublicKeyLength
|
||||||
l += len(rr.Hit) / 2
|
l += len(rr.Hit) / 2
|
||||||
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
|
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
|
||||||
for _, x := range rr.RendezvousServers {
|
for _, x := range rr.RendezvousServers {
|
||||||
l += len(x) + 1
|
l += domainNameLen(x, off+l, compression, false)
|
||||||
}
|
}
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *KX) len() int {
|
func (rr *KX) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += 2 // Preference
|
l += 2 // Preference
|
||||||
l += len(rr.Exchanger) + 1
|
l += domainNameLen(rr.Exchanger, off+l, compression, false)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *L32) len() int {
|
func (rr *L32) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += 2 // Preference
|
l += 2 // Preference
|
||||||
l += net.IPv4len // Locator32
|
l += net.IPv4len // Locator32
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *L64) len() int {
|
func (rr *L64) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += 2 // Preference
|
l += 2 // Preference
|
||||||
l += 8 // Locator64
|
l += 8 // Locator64
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *LOC) len() int {
|
func (rr *LOC) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l++ // Version
|
l++ // Version
|
||||||
l++ // Size
|
l++ // Size
|
||||||
l++ // HorizPre
|
l++ // HorizPre
|
||||||
|
@ -383,89 +385,89 @@ func (rr *LOC) len() int {
|
||||||
l += 4 // Altitude
|
l += 4 // Altitude
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *LP) len() int {
|
func (rr *LP) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += 2 // Preference
|
l += 2 // Preference
|
||||||
l += len(rr.Fqdn) + 1
|
l += domainNameLen(rr.Fqdn, off+l, compression, false)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *MB) len() int {
|
func (rr *MB) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += len(rr.Mb) + 1
|
l += domainNameLen(rr.Mb, off+l, compression, true)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *MD) len() int {
|
func (rr *MD) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += len(rr.Md) + 1
|
l += domainNameLen(rr.Md, off+l, compression, true)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *MF) len() int {
|
func (rr *MF) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += len(rr.Mf) + 1
|
l += domainNameLen(rr.Mf, off+l, compression, true)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *MG) len() int {
|
func (rr *MG) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += len(rr.Mg) + 1
|
l += domainNameLen(rr.Mg, off+l, compression, true)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *MINFO) len() int {
|
func (rr *MINFO) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += len(rr.Rmail) + 1
|
l += domainNameLen(rr.Rmail, off+l, compression, true)
|
||||||
l += len(rr.Email) + 1
|
l += domainNameLen(rr.Email, off+l, compression, true)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *MR) len() int {
|
func (rr *MR) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += len(rr.Mr) + 1
|
l += domainNameLen(rr.Mr, off+l, compression, true)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *MX) len() int {
|
func (rr *MX) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += 2 // Preference
|
l += 2 // Preference
|
||||||
l += len(rr.Mx) + 1
|
l += domainNameLen(rr.Mx, off+l, compression, true)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *NAPTR) len() int {
|
func (rr *NAPTR) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += 2 // Order
|
l += 2 // Order
|
||||||
l += 2 // Preference
|
l += 2 // Preference
|
||||||
l += len(rr.Flags) + 1
|
l += len(rr.Flags) + 1
|
||||||
l += len(rr.Service) + 1
|
l += len(rr.Service) + 1
|
||||||
l += len(rr.Regexp) + 1
|
l += len(rr.Regexp) + 1
|
||||||
l += len(rr.Replacement) + 1
|
l += domainNameLen(rr.Replacement, off+l, compression, false)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *NID) len() int {
|
func (rr *NID) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += 2 // Preference
|
l += 2 // Preference
|
||||||
l += 8 // NodeID
|
l += 8 // NodeID
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *NIMLOC) len() int {
|
func (rr *NIMLOC) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += len(rr.Locator)/2 + 1
|
l += len(rr.Locator)/2 + 1
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *NINFO) len() int {
|
func (rr *NINFO) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
for _, x := range rr.ZSData {
|
for _, x := range rr.ZSData {
|
||||||
l += len(x) + 1
|
l += len(x) + 1
|
||||||
}
|
}
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *NS) len() int {
|
func (rr *NS) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += len(rr.Ns) + 1
|
l += domainNameLen(rr.Ns, off+l, compression, true)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *NSAPPTR) len() int {
|
func (rr *NSAPPTR) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += len(rr.Ptr) + 1
|
l += domainNameLen(rr.Ptr, off+l, compression, false)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *NSEC3PARAM) len() int {
|
func (rr *NSEC3PARAM) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l++ // Hash
|
l++ // Hash
|
||||||
l++ // Flags
|
l++ // Flags
|
||||||
l += 2 // Iterations
|
l += 2 // Iterations
|
||||||
|
@ -473,44 +475,49 @@ func (rr *NSEC3PARAM) len() int {
|
||||||
l += len(rr.Salt) / 2
|
l += len(rr.Salt) / 2
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *OPENPGPKEY) len() int {
|
func (rr *NULL) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
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))
|
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *PTR) len() int {
|
func (rr *PTR) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += len(rr.Ptr) + 1
|
l += domainNameLen(rr.Ptr, off+l, compression, true)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *PX) len() int {
|
func (rr *PX) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += 2 // Preference
|
l += 2 // Preference
|
||||||
l += len(rr.Map822) + 1
|
l += domainNameLen(rr.Map822, off+l, compression, false)
|
||||||
l += len(rr.Mapx400) + 1
|
l += domainNameLen(rr.Mapx400, off+l, compression, false)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *RFC3597) len() int {
|
func (rr *RFC3597) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += len(rr.Rdata)/2 + 1
|
l += len(rr.Rdata)/2 + 1
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *RKEY) len() int {
|
func (rr *RKEY) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += 2 // Flags
|
l += 2 // Flags
|
||||||
l++ // Protocol
|
l++ // Protocol
|
||||||
l++ // Algorithm
|
l++ // Algorithm
|
||||||
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
|
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *RP) len() int {
|
func (rr *RP) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += len(rr.Mbox) + 1
|
l += domainNameLen(rr.Mbox, off+l, compression, false)
|
||||||
l += len(rr.Txt) + 1
|
l += domainNameLen(rr.Txt, off+l, compression, false)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *RRSIG) len() int {
|
func (rr *RRSIG) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += 2 // TypeCovered
|
l += 2 // TypeCovered
|
||||||
l++ // Algorithm
|
l++ // Algorithm
|
||||||
l++ // Labels
|
l++ // Labels
|
||||||
|
@ -518,28 +525,28 @@ func (rr *RRSIG) len() int {
|
||||||
l += 4 // Expiration
|
l += 4 // Expiration
|
||||||
l += 4 // Inception
|
l += 4 // Inception
|
||||||
l += 2 // KeyTag
|
l += 2 // KeyTag
|
||||||
l += len(rr.SignerName) + 1
|
l += domainNameLen(rr.SignerName, off+l, compression, false)
|
||||||
l += base64.StdEncoding.DecodedLen(len(rr.Signature))
|
l += base64.StdEncoding.DecodedLen(len(rr.Signature))
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *RT) len() int {
|
func (rr *RT) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += 2 // Preference
|
l += 2 // Preference
|
||||||
l += len(rr.Host) + 1
|
l += domainNameLen(rr.Host, off+l, compression, false)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *SMIMEA) len() int {
|
func (rr *SMIMEA) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l++ // Usage
|
l++ // Usage
|
||||||
l++ // Selector
|
l++ // Selector
|
||||||
l++ // MatchingType
|
l++ // MatchingType
|
||||||
l += len(rr.Certificate)/2 + 1
|
l += len(rr.Certificate)/2 + 1
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *SOA) len() int {
|
func (rr *SOA) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += len(rr.Ns) + 1
|
l += domainNameLen(rr.Ns, off+l, compression, true)
|
||||||
l += len(rr.Mbox) + 1
|
l += domainNameLen(rr.Mbox, off+l, compression, true)
|
||||||
l += 4 // Serial
|
l += 4 // Serial
|
||||||
l += 4 // Refresh
|
l += 4 // Refresh
|
||||||
l += 4 // Retry
|
l += 4 // Retry
|
||||||
|
@ -547,45 +554,45 @@ func (rr *SOA) len() int {
|
||||||
l += 4 // Minttl
|
l += 4 // Minttl
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *SPF) len() int {
|
func (rr *SPF) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
for _, x := range rr.Txt {
|
for _, x := range rr.Txt {
|
||||||
l += len(x) + 1
|
l += len(x) + 1
|
||||||
}
|
}
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *SRV) len() int {
|
func (rr *SRV) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += 2 // Priority
|
l += 2 // Priority
|
||||||
l += 2 // Weight
|
l += 2 // Weight
|
||||||
l += 2 // Port
|
l += 2 // Port
|
||||||
l += len(rr.Target) + 1
|
l += domainNameLen(rr.Target, off+l, compression, false)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *SSHFP) len() int {
|
func (rr *SSHFP) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l++ // Algorithm
|
l++ // Algorithm
|
||||||
l++ // Type
|
l++ // Type
|
||||||
l += len(rr.FingerPrint)/2 + 1
|
l += len(rr.FingerPrint)/2 + 1
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *TA) len() int {
|
func (rr *TA) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += 2 // KeyTag
|
l += 2 // KeyTag
|
||||||
l++ // Algorithm
|
l++ // Algorithm
|
||||||
l++ // DigestType
|
l++ // DigestType
|
||||||
l += len(rr.Digest)/2 + 1
|
l += len(rr.Digest)/2 + 1
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *TALINK) len() int {
|
func (rr *TALINK) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += len(rr.PreviousName) + 1
|
l += domainNameLen(rr.PreviousName, off+l, compression, false)
|
||||||
l += len(rr.NextName) + 1
|
l += domainNameLen(rr.NextName, off+l, compression, false)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *TKEY) len() int {
|
func (rr *TKEY) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += len(rr.Algorithm) + 1
|
l += domainNameLen(rr.Algorithm, off+l, compression, false)
|
||||||
l += 4 // Inception
|
l += 4 // Inception
|
||||||
l += 4 // Expiration
|
l += 4 // Expiration
|
||||||
l += 2 // Mode
|
l += 2 // Mode
|
||||||
|
@ -596,17 +603,17 @@ func (rr *TKEY) len() int {
|
||||||
l += len(rr.OtherData) / 2
|
l += len(rr.OtherData) / 2
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *TLSA) len() int {
|
func (rr *TLSA) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l++ // Usage
|
l++ // Usage
|
||||||
l++ // Selector
|
l++ // Selector
|
||||||
l++ // MatchingType
|
l++ // MatchingType
|
||||||
l += len(rr.Certificate)/2 + 1
|
l += len(rr.Certificate)/2 + 1
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *TSIG) len() int {
|
func (rr *TSIG) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += len(rr.Algorithm) + 1
|
l += domainNameLen(rr.Algorithm, off+l, compression, false)
|
||||||
l += 6 // TimeSigned
|
l += 6 // TimeSigned
|
||||||
l += 2 // Fudge
|
l += 2 // Fudge
|
||||||
l += 2 // MACSize
|
l += 2 // MACSize
|
||||||
|
@ -617,247 +624,252 @@ func (rr *TSIG) len() int {
|
||||||
l += len(rr.OtherData) / 2
|
l += len(rr.OtherData) / 2
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *TXT) len() int {
|
func (rr *TXT) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
for _, x := range rr.Txt {
|
for _, x := range rr.Txt {
|
||||||
l += len(x) + 1
|
l += len(x) + 1
|
||||||
}
|
}
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *UID) len() int {
|
func (rr *UID) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += 4 // Uid
|
l += 4 // Uid
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *UINFO) len() int {
|
func (rr *UINFO) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += len(rr.Uinfo) + 1
|
l += len(rr.Uinfo) + 1
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *URI) len() int {
|
func (rr *URI) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += 2 // Priority
|
l += 2 // Priority
|
||||||
l += 2 // Weight
|
l += 2 // Weight
|
||||||
l += len(rr.Target)
|
l += len(rr.Target)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (rr *X25) len() int {
|
func (rr *X25) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
l += len(rr.PSDNAddress) + 1
|
l += len(rr.PSDNAddress) + 1
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy() functions
|
// copy() functions
|
||||||
func (rr *A) copy() RR {
|
func (rr *A) copy() RR {
|
||||||
return &A{*rr.Hdr.copyHeader(), copyIP(rr.A)}
|
return &A{rr.Hdr, copyIP(rr.A)}
|
||||||
}
|
}
|
||||||
func (rr *AAAA) copy() RR {
|
func (rr *AAAA) copy() RR {
|
||||||
return &AAAA{*rr.Hdr.copyHeader(), copyIP(rr.AAAA)}
|
return &AAAA{rr.Hdr, copyIP(rr.AAAA)}
|
||||||
}
|
}
|
||||||
func (rr *AFSDB) copy() RR {
|
func (rr *AFSDB) copy() RR {
|
||||||
return &AFSDB{*rr.Hdr.copyHeader(), rr.Subtype, rr.Hostname}
|
return &AFSDB{rr.Hdr, rr.Subtype, rr.Hostname}
|
||||||
}
|
}
|
||||||
func (rr *ANY) copy() RR {
|
func (rr *ANY) copy() RR {
|
||||||
return &ANY{*rr.Hdr.copyHeader()}
|
return &ANY{rr.Hdr}
|
||||||
}
|
}
|
||||||
func (rr *AVC) copy() RR {
|
func (rr *AVC) copy() RR {
|
||||||
Txt := make([]string, len(rr.Txt))
|
Txt := make([]string, len(rr.Txt))
|
||||||
copy(Txt, rr.Txt)
|
copy(Txt, rr.Txt)
|
||||||
return &AVC{*rr.Hdr.copyHeader(), Txt}
|
return &AVC{rr.Hdr, Txt}
|
||||||
}
|
}
|
||||||
func (rr *CAA) copy() RR {
|
func (rr *CAA) copy() RR {
|
||||||
return &CAA{*rr.Hdr.copyHeader(), rr.Flag, rr.Tag, rr.Value}
|
return &CAA{rr.Hdr, rr.Flag, rr.Tag, rr.Value}
|
||||||
}
|
}
|
||||||
func (rr *CERT) copy() RR {
|
func (rr *CERT) copy() RR {
|
||||||
return &CERT{*rr.Hdr.copyHeader(), rr.Type, rr.KeyTag, rr.Algorithm, rr.Certificate}
|
return &CERT{rr.Hdr, rr.Type, rr.KeyTag, rr.Algorithm, rr.Certificate}
|
||||||
}
|
}
|
||||||
func (rr *CNAME) copy() RR {
|
func (rr *CNAME) copy() RR {
|
||||||
return &CNAME{*rr.Hdr.copyHeader(), rr.Target}
|
return &CNAME{rr.Hdr, rr.Target}
|
||||||
}
|
}
|
||||||
func (rr *CSYNC) copy() RR {
|
func (rr *CSYNC) copy() RR {
|
||||||
TypeBitMap := make([]uint16, len(rr.TypeBitMap))
|
TypeBitMap := make([]uint16, len(rr.TypeBitMap))
|
||||||
copy(TypeBitMap, rr.TypeBitMap)
|
copy(TypeBitMap, rr.TypeBitMap)
|
||||||
return &CSYNC{*rr.Hdr.copyHeader(), rr.Serial, rr.Flags, TypeBitMap}
|
return &CSYNC{rr.Hdr, rr.Serial, rr.Flags, TypeBitMap}
|
||||||
}
|
}
|
||||||
func (rr *DHCID) copy() RR {
|
func (rr *DHCID) copy() RR {
|
||||||
return &DHCID{*rr.Hdr.copyHeader(), rr.Digest}
|
return &DHCID{rr.Hdr, rr.Digest}
|
||||||
}
|
}
|
||||||
func (rr *DNAME) copy() RR {
|
func (rr *DNAME) copy() RR {
|
||||||
return &DNAME{*rr.Hdr.copyHeader(), rr.Target}
|
return &DNAME{rr.Hdr, rr.Target}
|
||||||
}
|
}
|
||||||
func (rr *DNSKEY) copy() RR {
|
func (rr *DNSKEY) copy() RR {
|
||||||
return &DNSKEY{*rr.Hdr.copyHeader(), rr.Flags, rr.Protocol, rr.Algorithm, rr.PublicKey}
|
return &DNSKEY{rr.Hdr, rr.Flags, rr.Protocol, rr.Algorithm, rr.PublicKey}
|
||||||
}
|
}
|
||||||
func (rr *DS) copy() RR {
|
func (rr *DS) copy() RR {
|
||||||
return &DS{*rr.Hdr.copyHeader(), rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest}
|
return &DS{rr.Hdr, rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest}
|
||||||
}
|
}
|
||||||
func (rr *EID) copy() RR {
|
func (rr *EID) copy() RR {
|
||||||
return &EID{*rr.Hdr.copyHeader(), rr.Endpoint}
|
return &EID{rr.Hdr, rr.Endpoint}
|
||||||
}
|
}
|
||||||
func (rr *EUI48) copy() RR {
|
func (rr *EUI48) copy() RR {
|
||||||
return &EUI48{*rr.Hdr.copyHeader(), rr.Address}
|
return &EUI48{rr.Hdr, rr.Address}
|
||||||
}
|
}
|
||||||
func (rr *EUI64) copy() RR {
|
func (rr *EUI64) copy() RR {
|
||||||
return &EUI64{*rr.Hdr.copyHeader(), rr.Address}
|
return &EUI64{rr.Hdr, rr.Address}
|
||||||
}
|
}
|
||||||
func (rr *GID) copy() RR {
|
func (rr *GID) copy() RR {
|
||||||
return &GID{*rr.Hdr.copyHeader(), rr.Gid}
|
return &GID{rr.Hdr, rr.Gid}
|
||||||
}
|
}
|
||||||
func (rr *GPOS) copy() RR {
|
func (rr *GPOS) copy() RR {
|
||||||
return &GPOS{*rr.Hdr.copyHeader(), rr.Longitude, rr.Latitude, rr.Altitude}
|
return &GPOS{rr.Hdr, rr.Longitude, rr.Latitude, rr.Altitude}
|
||||||
}
|
}
|
||||||
func (rr *HINFO) copy() RR {
|
func (rr *HINFO) copy() RR {
|
||||||
return &HINFO{*rr.Hdr.copyHeader(), rr.Cpu, rr.Os}
|
return &HINFO{rr.Hdr, rr.Cpu, rr.Os}
|
||||||
}
|
}
|
||||||
func (rr *HIP) copy() RR {
|
func (rr *HIP) copy() RR {
|
||||||
RendezvousServers := make([]string, len(rr.RendezvousServers))
|
RendezvousServers := make([]string, len(rr.RendezvousServers))
|
||||||
copy(RendezvousServers, rr.RendezvousServers)
|
copy(RendezvousServers, rr.RendezvousServers)
|
||||||
return &HIP{*rr.Hdr.copyHeader(), rr.HitLength, rr.PublicKeyAlgorithm, rr.PublicKeyLength, rr.Hit, rr.PublicKey, RendezvousServers}
|
return &HIP{rr.Hdr, rr.HitLength, rr.PublicKeyAlgorithm, rr.PublicKeyLength, rr.Hit, rr.PublicKey, RendezvousServers}
|
||||||
}
|
}
|
||||||
func (rr *KX) copy() RR {
|
func (rr *KX) copy() RR {
|
||||||
return &KX{*rr.Hdr.copyHeader(), rr.Preference, rr.Exchanger}
|
return &KX{rr.Hdr, rr.Preference, rr.Exchanger}
|
||||||
}
|
}
|
||||||
func (rr *L32) copy() RR {
|
func (rr *L32) copy() RR {
|
||||||
return &L32{*rr.Hdr.copyHeader(), rr.Preference, copyIP(rr.Locator32)}
|
return &L32{rr.Hdr, rr.Preference, copyIP(rr.Locator32)}
|
||||||
}
|
}
|
||||||
func (rr *L64) copy() RR {
|
func (rr *L64) copy() RR {
|
||||||
return &L64{*rr.Hdr.copyHeader(), rr.Preference, rr.Locator64}
|
return &L64{rr.Hdr, rr.Preference, rr.Locator64}
|
||||||
}
|
}
|
||||||
func (rr *LOC) copy() RR {
|
func (rr *LOC) copy() RR {
|
||||||
return &LOC{*rr.Hdr.copyHeader(), rr.Version, rr.Size, rr.HorizPre, rr.VertPre, rr.Latitude, rr.Longitude, rr.Altitude}
|
return &LOC{rr.Hdr, rr.Version, rr.Size, rr.HorizPre, rr.VertPre, rr.Latitude, rr.Longitude, rr.Altitude}
|
||||||
}
|
}
|
||||||
func (rr *LP) copy() RR {
|
func (rr *LP) copy() RR {
|
||||||
return &LP{*rr.Hdr.copyHeader(), rr.Preference, rr.Fqdn}
|
return &LP{rr.Hdr, rr.Preference, rr.Fqdn}
|
||||||
}
|
}
|
||||||
func (rr *MB) copy() RR {
|
func (rr *MB) copy() RR {
|
||||||
return &MB{*rr.Hdr.copyHeader(), rr.Mb}
|
return &MB{rr.Hdr, rr.Mb}
|
||||||
}
|
}
|
||||||
func (rr *MD) copy() RR {
|
func (rr *MD) copy() RR {
|
||||||
return &MD{*rr.Hdr.copyHeader(), rr.Md}
|
return &MD{rr.Hdr, rr.Md}
|
||||||
}
|
}
|
||||||
func (rr *MF) copy() RR {
|
func (rr *MF) copy() RR {
|
||||||
return &MF{*rr.Hdr.copyHeader(), rr.Mf}
|
return &MF{rr.Hdr, rr.Mf}
|
||||||
}
|
}
|
||||||
func (rr *MG) copy() RR {
|
func (rr *MG) copy() RR {
|
||||||
return &MG{*rr.Hdr.copyHeader(), rr.Mg}
|
return &MG{rr.Hdr, rr.Mg}
|
||||||
}
|
}
|
||||||
func (rr *MINFO) copy() RR {
|
func (rr *MINFO) copy() RR {
|
||||||
return &MINFO{*rr.Hdr.copyHeader(), rr.Rmail, rr.Email}
|
return &MINFO{rr.Hdr, rr.Rmail, rr.Email}
|
||||||
}
|
}
|
||||||
func (rr *MR) copy() RR {
|
func (rr *MR) copy() RR {
|
||||||
return &MR{*rr.Hdr.copyHeader(), rr.Mr}
|
return &MR{rr.Hdr, rr.Mr}
|
||||||
}
|
}
|
||||||
func (rr *MX) copy() RR {
|
func (rr *MX) copy() RR {
|
||||||
return &MX{*rr.Hdr.copyHeader(), rr.Preference, rr.Mx}
|
return &MX{rr.Hdr, rr.Preference, rr.Mx}
|
||||||
}
|
}
|
||||||
func (rr *NAPTR) copy() RR {
|
func (rr *NAPTR) copy() RR {
|
||||||
return &NAPTR{*rr.Hdr.copyHeader(), rr.Order, rr.Preference, rr.Flags, rr.Service, rr.Regexp, rr.Replacement}
|
return &NAPTR{rr.Hdr, rr.Order, rr.Preference, rr.Flags, rr.Service, rr.Regexp, rr.Replacement}
|
||||||
}
|
}
|
||||||
func (rr *NID) copy() RR {
|
func (rr *NID) copy() RR {
|
||||||
return &NID{*rr.Hdr.copyHeader(), rr.Preference, rr.NodeID}
|
return &NID{rr.Hdr, rr.Preference, rr.NodeID}
|
||||||
}
|
}
|
||||||
func (rr *NIMLOC) copy() RR {
|
func (rr *NIMLOC) copy() RR {
|
||||||
return &NIMLOC{*rr.Hdr.copyHeader(), rr.Locator}
|
return &NIMLOC{rr.Hdr, rr.Locator}
|
||||||
}
|
}
|
||||||
func (rr *NINFO) copy() RR {
|
func (rr *NINFO) copy() RR {
|
||||||
ZSData := make([]string, len(rr.ZSData))
|
ZSData := make([]string, len(rr.ZSData))
|
||||||
copy(ZSData, rr.ZSData)
|
copy(ZSData, rr.ZSData)
|
||||||
return &NINFO{*rr.Hdr.copyHeader(), ZSData}
|
return &NINFO{rr.Hdr, ZSData}
|
||||||
}
|
}
|
||||||
func (rr *NS) copy() RR {
|
func (rr *NS) copy() RR {
|
||||||
return &NS{*rr.Hdr.copyHeader(), rr.Ns}
|
return &NS{rr.Hdr, rr.Ns}
|
||||||
}
|
}
|
||||||
func (rr *NSAPPTR) copy() RR {
|
func (rr *NSAPPTR) copy() RR {
|
||||||
return &NSAPPTR{*rr.Hdr.copyHeader(), rr.Ptr}
|
return &NSAPPTR{rr.Hdr, rr.Ptr}
|
||||||
}
|
}
|
||||||
func (rr *NSEC) copy() RR {
|
func (rr *NSEC) copy() RR {
|
||||||
TypeBitMap := make([]uint16, len(rr.TypeBitMap))
|
TypeBitMap := make([]uint16, len(rr.TypeBitMap))
|
||||||
copy(TypeBitMap, rr.TypeBitMap)
|
copy(TypeBitMap, rr.TypeBitMap)
|
||||||
return &NSEC{*rr.Hdr.copyHeader(), rr.NextDomain, TypeBitMap}
|
return &NSEC{rr.Hdr, rr.NextDomain, TypeBitMap}
|
||||||
}
|
}
|
||||||
func (rr *NSEC3) copy() RR {
|
func (rr *NSEC3) copy() RR {
|
||||||
TypeBitMap := make([]uint16, len(rr.TypeBitMap))
|
TypeBitMap := make([]uint16, len(rr.TypeBitMap))
|
||||||
copy(TypeBitMap, rr.TypeBitMap)
|
copy(TypeBitMap, rr.TypeBitMap)
|
||||||
return &NSEC3{*rr.Hdr.copyHeader(), rr.Hash, rr.Flags, rr.Iterations, rr.SaltLength, rr.Salt, rr.HashLength, rr.NextDomain, TypeBitMap}
|
return &NSEC3{rr.Hdr, rr.Hash, rr.Flags, rr.Iterations, rr.SaltLength, rr.Salt, rr.HashLength, rr.NextDomain, TypeBitMap}
|
||||||
}
|
}
|
||||||
func (rr *NSEC3PARAM) copy() RR {
|
func (rr *NSEC3PARAM) copy() RR {
|
||||||
return &NSEC3PARAM{*rr.Hdr.copyHeader(), rr.Hash, rr.Flags, rr.Iterations, rr.SaltLength, rr.Salt}
|
return &NSEC3PARAM{rr.Hdr, rr.Hash, rr.Flags, rr.Iterations, rr.SaltLength, rr.Salt}
|
||||||
|
}
|
||||||
|
func (rr *NULL) copy() RR {
|
||||||
|
return &NULL{rr.Hdr, rr.Data}
|
||||||
}
|
}
|
||||||
func (rr *OPENPGPKEY) copy() RR {
|
func (rr *OPENPGPKEY) copy() RR {
|
||||||
return &OPENPGPKEY{*rr.Hdr.copyHeader(), rr.PublicKey}
|
return &OPENPGPKEY{rr.Hdr, rr.PublicKey}
|
||||||
}
|
}
|
||||||
func (rr *OPT) copy() RR {
|
func (rr *OPT) copy() RR {
|
||||||
Option := make([]EDNS0, len(rr.Option))
|
Option := make([]EDNS0, len(rr.Option))
|
||||||
copy(Option, rr.Option)
|
for i, e := range rr.Option {
|
||||||
return &OPT{*rr.Hdr.copyHeader(), Option}
|
Option[i] = e.copy()
|
||||||
|
}
|
||||||
|
return &OPT{rr.Hdr, Option}
|
||||||
}
|
}
|
||||||
func (rr *PTR) copy() RR {
|
func (rr *PTR) copy() RR {
|
||||||
return &PTR{*rr.Hdr.copyHeader(), rr.Ptr}
|
return &PTR{rr.Hdr, rr.Ptr}
|
||||||
}
|
}
|
||||||
func (rr *PX) copy() RR {
|
func (rr *PX) copy() RR {
|
||||||
return &PX{*rr.Hdr.copyHeader(), rr.Preference, rr.Map822, rr.Mapx400}
|
return &PX{rr.Hdr, rr.Preference, rr.Map822, rr.Mapx400}
|
||||||
}
|
}
|
||||||
func (rr *RFC3597) copy() RR {
|
func (rr *RFC3597) copy() RR {
|
||||||
return &RFC3597{*rr.Hdr.copyHeader(), rr.Rdata}
|
return &RFC3597{rr.Hdr, rr.Rdata}
|
||||||
}
|
}
|
||||||
func (rr *RKEY) copy() RR {
|
func (rr *RKEY) copy() RR {
|
||||||
return &RKEY{*rr.Hdr.copyHeader(), rr.Flags, rr.Protocol, rr.Algorithm, rr.PublicKey}
|
return &RKEY{rr.Hdr, rr.Flags, rr.Protocol, rr.Algorithm, rr.PublicKey}
|
||||||
}
|
}
|
||||||
func (rr *RP) copy() RR {
|
func (rr *RP) copy() RR {
|
||||||
return &RP{*rr.Hdr.copyHeader(), rr.Mbox, rr.Txt}
|
return &RP{rr.Hdr, rr.Mbox, rr.Txt}
|
||||||
}
|
}
|
||||||
func (rr *RRSIG) copy() RR {
|
func (rr *RRSIG) copy() RR {
|
||||||
return &RRSIG{*rr.Hdr.copyHeader(), rr.TypeCovered, rr.Algorithm, rr.Labels, rr.OrigTtl, rr.Expiration, rr.Inception, rr.KeyTag, rr.SignerName, rr.Signature}
|
return &RRSIG{rr.Hdr, rr.TypeCovered, rr.Algorithm, rr.Labels, rr.OrigTtl, rr.Expiration, rr.Inception, rr.KeyTag, rr.SignerName, rr.Signature}
|
||||||
}
|
}
|
||||||
func (rr *RT) copy() RR {
|
func (rr *RT) copy() RR {
|
||||||
return &RT{*rr.Hdr.copyHeader(), rr.Preference, rr.Host}
|
return &RT{rr.Hdr, rr.Preference, rr.Host}
|
||||||
}
|
}
|
||||||
func (rr *SMIMEA) copy() RR {
|
func (rr *SMIMEA) copy() RR {
|
||||||
return &SMIMEA{*rr.Hdr.copyHeader(), rr.Usage, rr.Selector, rr.MatchingType, rr.Certificate}
|
return &SMIMEA{rr.Hdr, rr.Usage, rr.Selector, rr.MatchingType, rr.Certificate}
|
||||||
}
|
}
|
||||||
func (rr *SOA) copy() RR {
|
func (rr *SOA) copy() RR {
|
||||||
return &SOA{*rr.Hdr.copyHeader(), rr.Ns, rr.Mbox, rr.Serial, rr.Refresh, rr.Retry, rr.Expire, rr.Minttl}
|
return &SOA{rr.Hdr, rr.Ns, rr.Mbox, rr.Serial, rr.Refresh, rr.Retry, rr.Expire, rr.Minttl}
|
||||||
}
|
}
|
||||||
func (rr *SPF) copy() RR {
|
func (rr *SPF) copy() RR {
|
||||||
Txt := make([]string, len(rr.Txt))
|
Txt := make([]string, len(rr.Txt))
|
||||||
copy(Txt, rr.Txt)
|
copy(Txt, rr.Txt)
|
||||||
return &SPF{*rr.Hdr.copyHeader(), Txt}
|
return &SPF{rr.Hdr, Txt}
|
||||||
}
|
}
|
||||||
func (rr *SRV) copy() RR {
|
func (rr *SRV) copy() RR {
|
||||||
return &SRV{*rr.Hdr.copyHeader(), rr.Priority, rr.Weight, rr.Port, rr.Target}
|
return &SRV{rr.Hdr, rr.Priority, rr.Weight, rr.Port, rr.Target}
|
||||||
}
|
}
|
||||||
func (rr *SSHFP) copy() RR {
|
func (rr *SSHFP) copy() RR {
|
||||||
return &SSHFP{*rr.Hdr.copyHeader(), rr.Algorithm, rr.Type, rr.FingerPrint}
|
return &SSHFP{rr.Hdr, rr.Algorithm, rr.Type, rr.FingerPrint}
|
||||||
}
|
}
|
||||||
func (rr *TA) copy() RR {
|
func (rr *TA) copy() RR {
|
||||||
return &TA{*rr.Hdr.copyHeader(), rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest}
|
return &TA{rr.Hdr, rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest}
|
||||||
}
|
}
|
||||||
func (rr *TALINK) copy() RR {
|
func (rr *TALINK) copy() RR {
|
||||||
return &TALINK{*rr.Hdr.copyHeader(), rr.PreviousName, rr.NextName}
|
return &TALINK{rr.Hdr, rr.PreviousName, rr.NextName}
|
||||||
}
|
}
|
||||||
func (rr *TKEY) copy() RR {
|
func (rr *TKEY) copy() RR {
|
||||||
return &TKEY{*rr.Hdr.copyHeader(), rr.Algorithm, rr.Inception, rr.Expiration, rr.Mode, rr.Error, rr.KeySize, rr.Key, rr.OtherLen, rr.OtherData}
|
return &TKEY{rr.Hdr, rr.Algorithm, rr.Inception, rr.Expiration, rr.Mode, rr.Error, rr.KeySize, rr.Key, rr.OtherLen, rr.OtherData}
|
||||||
}
|
}
|
||||||
func (rr *TLSA) copy() RR {
|
func (rr *TLSA) copy() RR {
|
||||||
return &TLSA{*rr.Hdr.copyHeader(), rr.Usage, rr.Selector, rr.MatchingType, rr.Certificate}
|
return &TLSA{rr.Hdr, rr.Usage, rr.Selector, rr.MatchingType, rr.Certificate}
|
||||||
}
|
}
|
||||||
func (rr *TSIG) copy() RR {
|
func (rr *TSIG) copy() RR {
|
||||||
return &TSIG{*rr.Hdr.copyHeader(), rr.Algorithm, rr.TimeSigned, rr.Fudge, rr.MACSize, rr.MAC, rr.OrigId, rr.Error, rr.OtherLen, rr.OtherData}
|
return &TSIG{rr.Hdr, rr.Algorithm, rr.TimeSigned, rr.Fudge, rr.MACSize, rr.MAC, rr.OrigId, rr.Error, rr.OtherLen, rr.OtherData}
|
||||||
}
|
}
|
||||||
func (rr *TXT) copy() RR {
|
func (rr *TXT) copy() RR {
|
||||||
Txt := make([]string, len(rr.Txt))
|
Txt := make([]string, len(rr.Txt))
|
||||||
copy(Txt, rr.Txt)
|
copy(Txt, rr.Txt)
|
||||||
return &TXT{*rr.Hdr.copyHeader(), Txt}
|
return &TXT{rr.Hdr, Txt}
|
||||||
}
|
}
|
||||||
func (rr *UID) copy() RR {
|
func (rr *UID) copy() RR {
|
||||||
return &UID{*rr.Hdr.copyHeader(), rr.Uid}
|
return &UID{rr.Hdr, rr.Uid}
|
||||||
}
|
}
|
||||||
func (rr *UINFO) copy() RR {
|
func (rr *UINFO) copy() RR {
|
||||||
return &UINFO{*rr.Hdr.copyHeader(), rr.Uinfo}
|
return &UINFO{rr.Hdr, rr.Uinfo}
|
||||||
}
|
}
|
||||||
func (rr *URI) copy() RR {
|
func (rr *URI) copy() RR {
|
||||||
return &URI{*rr.Hdr.copyHeader(), rr.Priority, rr.Weight, rr.Target}
|
return &URI{rr.Hdr, rr.Priority, rr.Weight, rr.Target}
|
||||||
}
|
}
|
||||||
func (rr *X25) copy() RR {
|
func (rr *X25) copy() RR {
|
||||||
return &X25{*rr.Hdr.copyHeader(), rr.PSDNAddress}
|
return &X25{rr.Hdr, rr.PSDNAddress}
|
||||||
}
|
}
|
||||||
|
|
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
|
@ -191,7 +191,7 @@ github.com/julienschmidt/httprouter
|
||||||
github.com/kr/logfmt
|
github.com/kr/logfmt
|
||||||
# github.com/matttproud/golang_protobuf_extensions v1.0.1
|
# github.com/matttproud/golang_protobuf_extensions v1.0.1
|
||||||
github.com/matttproud/golang_protobuf_extensions/pbutil
|
github.com/matttproud/golang_protobuf_extensions/pbutil
|
||||||
# github.com/miekg/dns v1.0.4
|
# github.com/miekg/dns v1.1.4
|
||||||
github.com/miekg/dns
|
github.com/miekg/dns
|
||||||
# github.com/mitchellh/go-homedir v0.0.0-20180523094522-3864e76763d9
|
# github.com/mitchellh/go-homedir v0.0.0-20180523094522-3864e76763d9
|
||||||
github.com/mitchellh/go-homedir
|
github.com/mitchellh/go-homedir
|
||||||
|
|
Loading…
Reference in a new issue