Merge pull request #97405 from dlorenc/dns

Update github.com/miekg/dns to pick up fix for CVE-2019-19794.
This commit is contained in:
Kubernetes Prow Robot 2021-01-11 05:49:09 -08:00 committed by GitHub
commit 334b426a6b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 2989 additions and 1939 deletions

View File

@ -1,9 +1,5 @@
= vendor/github.com/miekg/dns licensed under: = = vendor/github.com/miekg/dns licensed under: =
Extensions of the original work are copyright (c) 2011 Miek Gieben
As this is fork of the official Go code the same license applies:
Copyright (c) 2009 The Go Authors. All rights reserved. Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@ -32,5 +28,7 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
As this is fork of the official Go code the same license applies.
Extensions of the original work are copyright (c) 2011 Miek Gieben
= vendor/github.com/miekg/dns/LICENSE 147353de6868a20caa562d26eab7b3c5 = vendor/github.com/miekg/dns/LICENSE 567c1ad6c08ca0ee8d7e0a0cf790aff9

4
go.mod
View File

@ -67,7 +67,7 @@ require (
github.com/libopenstorage/openstorage v1.0.0 github.com/libopenstorage/openstorage v1.0.0
github.com/lithammer/dedent v1.1.0 github.com/lithammer/dedent v1.1.0
github.com/lpabon/godbc v0.1.1 // indirect github.com/lpabon/godbc v0.1.1 // indirect
github.com/miekg/dns v1.1.4 github.com/miekg/dns v1.1.35
github.com/moby/ipvs v1.0.1 github.com/moby/ipvs v1.0.1
github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb // indirect github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb // indirect
github.com/mrunalp/fileutils v0.0.0-20200520151820-abd8a0e76976 github.com/mrunalp/fileutils v0.0.0-20200520151820-abd8a0e76976
@ -359,7 +359,7 @@ replace (
github.com/mattn/go-runewidth => github.com/mattn/go-runewidth v0.0.2 github.com/mattn/go-runewidth => github.com/mattn/go-runewidth v0.0.2
github.com/matttproud/golang_protobuf_extensions => github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 github.com/matttproud/golang_protobuf_extensions => github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369
github.com/mholt/certmagic => github.com/mholt/certmagic v0.6.2-0.20190624175158-6a42ef9fe8c2 github.com/mholt/certmagic => github.com/mholt/certmagic v0.6.2-0.20190624175158-6a42ef9fe8c2
github.com/miekg/dns => github.com/miekg/dns v1.1.4 github.com/miekg/dns => github.com/miekg/dns v1.1.35
github.com/mindprince/gonvml => github.com/mindprince/gonvml v0.0.0-20190828220739-9ebdce4bb989 github.com/mindprince/gonvml => github.com/mindprince/gonvml v0.0.0-20190828220739-9ebdce4bb989
github.com/mistifyio/go-zfs => github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible github.com/mistifyio/go-zfs => github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible
github.com/mitchellh/cli => github.com/mitchellh/cli v1.0.0 github.com/mitchellh/cli => github.com/mitchellh/cli v1.0.0

4
go.sum
View File

@ -353,8 +353,8 @@ github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/mholt/certmagic v0.6.2-0.20190624175158-6a42ef9fe8c2/go.mod h1:g4cOPxcjV0oFq3qwpjSA30LReKD8AoIfwAY9VvG35NY= github.com/mholt/certmagic v0.6.2-0.20190624175158-6a42ef9fe8c2/go.mod h1:g4cOPxcjV0oFq3qwpjSA30LReKD8AoIfwAY9VvG35NY=
github.com/miekg/dns v1.1.4 h1:rCMZsU2ScVSYcAsOXgmC6+AKOK+6pmQTOcw03nfwYV0= github.com/miekg/dns v1.1.35 h1:oTfOaDH+mZkdcgdIjH6yBajRGtIwcwcaR+rt23ZSrJs=
github.com/miekg/dns v1.1.4/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/mindprince/gonvml v0.0.0-20190828220739-9ebdce4bb989 h1:PS1dLCGtD8bb9RPKJrc8bS7qHL6JnW1CZvwzH9dPoUs= github.com/mindprince/gonvml v0.0.0-20190828220739-9ebdce4bb989 h1:PS1dLCGtD8bb9RPKJrc8bS7qHL6JnW1CZvwzH9dPoUs=
github.com/mindprince/gonvml v0.0.0-20190828220739-9ebdce4bb989/go.mod h1:2eu9pRWp8mo84xCg6KswZ+USQHjwgRhNp06sozOdsTY= github.com/mindprince/gonvml v0.0.0-20190828220739-9ebdce4bb989/go.mod h1:2eu9pRWp8mo84xCg6KswZ+USQHjwgRhNp06sozOdsTY=
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible h1:aKW/4cBs+yK6gpqU3K/oIwk9Q/XICqd3zOX/UFuvqmk= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible h1:aKW/4cBs+yK6gpqU3K/oIwk9Q/XICqd3zOX/UFuvqmk=

View File

@ -2,16 +2,15 @@ language: go
sudo: false sudo: false
go: go:
- 1.10.x - 1.14.x
- 1.11.x - 1.15.x
- tip - tip
before_install: env:
# don't use the miekg/dns when testing forks - GO111MODULE=on
- mkdir -p $GOPATH/src/github.com/miekg
- ln -s $TRAVIS_BUILD_DIR $GOPATH/src/github.com/miekg/ || true
script: script:
- go generate ./... && test `git ls-files --modified | wc -l` = 0
- go test -race -v -bench=. -coverprofile=coverage.txt -covermode=atomic ./... - go test -race -v -bench=. -coverprofile=coverage.txt -covermode=atomic ./...
after_success: after_success:

2
vendor/github.com/miekg/dns/BUILD generated vendored
View File

@ -23,6 +23,7 @@ go_library(
"listen_go_not111.go", "listen_go_not111.go",
"msg.go", "msg.go",
"msg_helpers.go", "msg_helpers.go",
"msg_truncate.go",
"nsecx.go", "nsecx.go",
"privaterr.go", "privaterr.go",
"reverse.go", "reverse.go",
@ -34,6 +35,7 @@ go_library(
"sig0.go", "sig0.go",
"singleinflight.go", "singleinflight.go",
"smimea.go", "smimea.go",
"svcb.go",
"tlsa.go", "tlsa.go",
"tsig.go", "tsig.go",
"types.go", "types.go",

1
vendor/github.com/miekg/dns/CODEOWNERS generated vendored Normal file
View File

@ -0,0 +1 @@
* @miekg @tmthrgd

View File

@ -1,57 +0,0 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
branch = "master"
digest = "1:6914c49eed986dfb8dffb33516fa129c49929d4d873f41e073c83c11c372b870"
name = "golang.org/x/crypto"
packages = [
"ed25519",
"ed25519/internal/edwards25519",
]
pruneopts = ""
revision = "e3636079e1a4c1f337f212cc5cd2aca108f6c900"
[[projects]]
branch = "master"
digest = "1:08e41d63f8dac84d83797368b56cf0b339e42d0224e5e56668963c28aec95685"
name = "golang.org/x/net"
packages = [
"bpf",
"context",
"internal/iana",
"internal/socket",
"ipv4",
"ipv6",
]
pruneopts = ""
revision = "4dfa2610cdf3b287375bbba5b8f2a14d3b01d8de"
[[projects]]
branch = "master"
digest = "1:b2ea75de0ccb2db2ac79356407f8a4cd8f798fe15d41b381c00abf3ae8e55ed1"
name = "golang.org/x/sync"
packages = ["errgroup"]
pruneopts = ""
revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca"
[[projects]]
branch = "master"
digest = "1:149a432fabebb8221a80f77731b1cd63597197ded4f14af606ebe3a0959004ec"
name = "golang.org/x/sys"
packages = ["unix"]
pruneopts = ""
revision = "e4b3c5e9061176387e7cea65e4dc5853801f3fb7"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
input-imports = [
"golang.org/x/crypto/ed25519",
"golang.org/x/net/ipv4",
"golang.org/x/net/ipv6",
"golang.org/x/sync/errgroup",
"golang.org/x/sys/unix",
]
solver-name = "gps-cdcl"
solver-version = 1

View File

@ -1,38 +0,0 @@
# Gopkg.toml example
#
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
[[constraint]]
branch = "master"
name = "golang.org/x/crypto"
[[constraint]]
branch = "master"
name = "golang.org/x/net"
[[constraint]]
branch = "master"
name = "golang.org/x/sys"
[[constraint]]
branch = "master"
name = "golang.org/x/sync"

View File

@ -1,7 +1,3 @@
Extensions of the original work are copyright (c) 2011 Miek Gieben
As this is fork of the official Go code the same license applies:
Copyright (c) 2009 The Go Authors. All rights reserved. Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@ -30,3 +26,5 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
As this is fork of the official Go code the same license applies.
Extensions of the original work are copyright (c) 2011 Miek Gieben

View File

@ -26,8 +26,8 @@ avoiding breaking changes wherever reasonable. We support the last two versions
A not-so-up-to-date-list-that-may-be-actually-current: A not-so-up-to-date-list-that-may-be-actually-current:
* https://github.com/coredns/coredns * https://github.com/coredns/coredns
* https://cloudflare.com
* https://github.com/abh/geodns * https://github.com/abh/geodns
* https://github.com/baidu/bfe
* http://www.statdns.com/ * http://www.statdns.com/
* http://www.dnsinspect.com/ * http://www.dnsinspect.com/
* https://github.com/chuangbo/jianbing-dictionary-dns * https://github.com/chuangbo/jianbing-dictionary-dns
@ -41,11 +41,9 @@ A not-so-up-to-date-list-that-may-be-actually-current:
* https://github.com/StalkR/dns-reverse-proxy * https://github.com/StalkR/dns-reverse-proxy
* 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://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://github.com/miekg/unbound * https://github.com/miekg/unbound
* https://github.com/miekg/exdns * https://github.com/miekg/exdns
* https://dnslookup.org * https://dnslookup.org
@ -54,20 +52,23 @@ A not-so-up-to-date-list-that-may-be-actually-current:
* https://github.com/mehrdadrad/mylg * https://github.com/mehrdadrad/mylg
* https://github.com/bamarni/dockness * https://github.com/bamarni/dockness
* https://github.com/fffaraz/microdns * https://github.com/fffaraz/microdns
* http://kelda.io
* https://github.com/ipdcode/hades <https://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/
* https://dns.apebits.com
* 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/xor-gate/sshfp
* https://github.com/rs/dnstrace * https://github.com/rs/dnstrace
* https://blitiri.com.ar/p/dnss ([github mirror](https://github.com/albertito/dnss)) * https://blitiri.com.ar/p/dnss ([github mirror](https://github.com/albertito/dnss))
* https://github.com/semihalev/sdns
* https://render.com * https://render.com
* https://github.com/peterzen/goresolver
* https://github.com/folbricht/routedns
* https://domainr.com/
* https://zonedb.org/
* https://router7.org/
* https://github.com/fortio/dnsping
Send pull request if you want to be listed here. Send pull request if you want to be listed here.
@ -92,8 +93,8 @@ DNS Authors 2012-
# Building # Building
Building is done with the `go` tool. If you have setup your GOPATH correctly, the following should This library uses Go modules and uses semantic versioning. Building is done with the `go` tool, so
work: the following should work:
go get github.com/miekg/dns go get github.com/miekg/dns
go build github.com/miekg/dns go build github.com/miekg/dns
@ -125,6 +126,7 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
* 2915 - NAPTR record * 2915 - NAPTR record
* 2929 - DNS IANA Considerations * 2929 - DNS IANA Considerations
* 3110 - RSASHA1 DNS keys * 3110 - RSASHA1 DNS keys
* 3123 - APL record
* 3225 - DO bit (DNSSEC OK) * 3225 - DO bit (DNSSEC OK)
* 340{1,2,3} - NAPTR record * 340{1,2,3} - NAPTR record
* 3445 - Limiting the scope of (DNS)KEY * 3445 - Limiting the scope of (DNS)KEY
@ -151,6 +153,7 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
* 6844 - CAA record * 6844 - CAA record
* 6891 - EDNS0 update * 6891 - EDNS0 update
* 6895 - DNS IANA considerations * 6895 - DNS IANA considerations
* 6944 - DNSSEC DNSKEY Algorithm Status
* 6975 - Algorithm Understanding in DNSSEC * 6975 - Algorithm Understanding in DNSSEC
* 7043 - EUI48/EUI64 records * 7043 - EUI48/EUI64 records
* 7314 - DNS (EDNS) EXPIRE Option * 7314 - DNS (EDNS) EXPIRE Option

View File

@ -6,13 +6,20 @@ type MsgAcceptFunc func(dh Header) MsgAcceptAction
// DefaultMsgAcceptFunc checks the request and will reject if: // DefaultMsgAcceptFunc checks the request and will reject if:
// //
// * isn't a request (don't respond in that case). // * isn't a request (don't respond in that case)
//
// * opcode isn't OpcodeQuery or OpcodeNotify // * opcode isn't OpcodeQuery or OpcodeNotify
//
// * Zero bit isn't zero // * Zero bit isn't zero
//
// * has more than 1 question in the question section // * has more than 1 question in the question section
//
// * has more than 1 RR in the Answer section // * has more than 1 RR in the Answer section
//
// * has more than 0 RRs in the Authority section // * has more than 0 RRs in the Authority section
//
// * has more than 2 RRs in the Additional section // * has more than 2 RRs in the Additional section
//
var DefaultMsgAcceptFunc MsgAcceptFunc = defaultMsgAcceptFunc var DefaultMsgAcceptFunc MsgAcceptFunc = defaultMsgAcceptFunc
// MsgAcceptAction represents the action to be taken. // MsgAcceptAction represents the action to be taken.
@ -22,6 +29,7 @@ const (
MsgAccept MsgAcceptAction = iota // Accept the message MsgAccept MsgAcceptAction = iota // Accept the message
MsgReject // Reject the message with a RcodeFormatError MsgReject // Reject the message with a RcodeFormatError
MsgIgnore // Ignore the error and send nothing back. MsgIgnore // Ignore the error and send nothing back.
MsgRejectNotImplemented // Reject the message with a RcodeNotImplemented
) )
func defaultMsgAcceptFunc(dh Header) MsgAcceptAction { func defaultMsgAcceptFunc(dh Header) MsgAcceptAction {
@ -32,12 +40,9 @@ func defaultMsgAcceptFunc(dh Header) MsgAcceptAction {
// Don't allow dynamic updates, because then the sections can contain a whole bunch of RRs. // Don't allow dynamic updates, because then the sections can contain a whole bunch of RRs.
opcode := int(dh.Bits>>11) & 0xF opcode := int(dh.Bits>>11) & 0xF
if opcode != OpcodeQuery && opcode != OpcodeNotify { if opcode != OpcodeQuery && opcode != OpcodeNotify {
return MsgReject return MsgRejectNotImplemented
} }
if isZero := dh.Bits&_Z != 0; isZero {
return MsgReject
}
if dh.Qdcount != 1 { if dh.Qdcount != 1 {
return MsgReject return MsgReject
} }

199
vendor/github.com/miekg/dns/client.go generated vendored
View File

@ -3,10 +3,10 @@ package dns
// A client implementation. // A client implementation.
import ( import (
"bytes"
"context" "context"
"crypto/tls" "crypto/tls"
"encoding/binary" "encoding/binary"
"fmt"
"io" "io"
"net" "net"
"strings" "strings"
@ -34,7 +34,7 @@ type Client struct {
Dialer *net.Dialer // a net.Dialer used to set local address, timeouts and more Dialer *net.Dialer // a net.Dialer used to set local address, timeouts and more
// Timeout is a cumulative timeout for dial, write and read, defaults to 0 (disabled) - overrides DialTimeout, ReadTimeout, // Timeout is a cumulative timeout for dial, write and read, defaults to 0 (disabled) - overrides DialTimeout, ReadTimeout,
// WriteTimeout when non-zero. Can be overridden with net.Dialer.Timeout (see Client.ExchangeWithDialer and // WriteTimeout when non-zero. Can be overridden with net.Dialer.Timeout (see Client.ExchangeWithDialer and
// Client.Dialer) or context.Context.Deadline (see the deprecated ExchangeContext) // Client.Dialer) or context.Context.Deadline (see ExchangeContext)
Timeout time.Duration Timeout time.Duration
DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds, or net.Dialer.Timeout if expiring earlier - overridden by Timeout when that value is non-zero DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds, or net.Dialer.Timeout if expiring earlier - overridden by Timeout when that value is non-zero
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
@ -106,7 +106,7 @@ func (c *Client) Dial(address string) (conn *Conn, err error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
conn.UDPSize = c.UDPSize
return conn, nil return conn, nil
} }
@ -124,37 +124,47 @@ func (c *Client) Dial(address string) (conn *Conn, err error) {
// of 512 bytes // of 512 bytes
// To specify a local address or a timeout, the caller has to set the `Client.Dialer` // To specify a local address or a timeout, the caller has to set the `Client.Dialer`
// attribute appropriately // attribute appropriately
func (c *Client) Exchange(m *Msg, address string) (r *Msg, rtt time.Duration, err error) { func (c *Client) Exchange(m *Msg, address string) (r *Msg, rtt time.Duration, err error) {
if !c.SingleInflight { co, err := c.Dial(address)
return c.exchange(m, address)
}
t := "nop"
if t1, ok := TypeToString[m.Question[0].Qtype]; ok {
t = t1
}
cl := "nop"
if cl1, ok := ClassToString[m.Question[0].Qclass]; ok {
cl = cl1
}
r, rtt, err, shared := c.group.Do(m.Question[0].Name+t+cl, func() (*Msg, time.Duration, error) {
return c.exchange(m, address)
})
if r != nil && shared {
r = r.Copy()
}
return r, rtt, err
}
func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
var co *Conn
co, err = c.Dial(a)
if err != nil { if err != nil {
return nil, 0, err return nil, 0, err
} }
defer co.Close() defer co.Close()
return c.ExchangeWithConn(m, co)
}
// ExchangeWithConn has the same behavior as Exchange, just with a predetermined connection
// that will be used instead of creating a new one.
// Usage pattern with a *dns.Client:
// c := new(dns.Client)
// // connection management logic goes here
//
// conn := c.Dial(address)
// in, rtt, err := c.ExchangeWithConn(message, conn)
//
// This allows users of the library to implement their own connection management,
// as opposed to Exchange, which will always use new connections and incur the added overhead
// that entails when using "tcp" and especially "tcp-tls" clients.
func (c *Client) ExchangeWithConn(m *Msg, conn *Conn) (r *Msg, rtt time.Duration, err error) {
if !c.SingleInflight {
return c.exchange(m, conn)
}
q := m.Question[0]
key := fmt.Sprintf("%s:%d:%d", q.Name, q.Qtype, q.Qclass)
r, rtt, err, shared := c.group.Do(key, func() (*Msg, time.Duration, error) {
return c.exchange(m, conn)
})
if r != nil && shared {
r = r.Copy()
}
return r, rtt, err
}
func (c *Client) exchange(m *Msg, co *Conn) (r *Msg, rtt time.Duration, err error) {
opt := m.IsEdns0() opt := m.IsEdns0()
// If EDNS0 is used use that for size. // If EDNS0 is used use that for size.
@ -175,10 +185,21 @@ func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro
} }
co.SetReadDeadline(time.Now().Add(c.getTimeoutForRequest(c.readTimeout()))) co.SetReadDeadline(time.Now().Add(c.getTimeoutForRequest(c.readTimeout())))
if _, ok := co.Conn.(net.PacketConn); ok {
for {
r, err = co.ReadMsg()
// Ignore replies with mismatched IDs because they might be
// responses to earlier queries that timed out.
if err != nil || r.Id == m.Id {
break
}
}
} else {
r, err = co.ReadMsg() r, err = co.ReadMsg()
if err == nil && r.Id != m.Id { if err == nil && r.Id != m.Id {
err = ErrId err = ErrId
} }
}
rtt = time.Since(t) rtt = time.Since(t)
return r, rtt, err return r, rtt, err
} }
@ -221,24 +242,21 @@ func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) {
err error err error
) )
switch t := co.Conn.(type) { if _, ok := co.Conn.(net.PacketConn); ok {
case *net.TCPConn, *tls.Conn:
r := t.(io.Reader)
// First two bytes specify the length of the entire message.
l, err := tcpMsgLen(r)
if err != nil {
return nil, err
}
p = make([]byte, l)
n, err = tcpRead(r, p)
default:
if co.UDPSize > MinMsgSize { if co.UDPSize > MinMsgSize {
p = make([]byte, co.UDPSize) p = make([]byte, co.UDPSize)
} else { } else {
p = make([]byte, MinMsgSize) p = make([]byte, MinMsgSize)
} }
n, err = co.Read(p) n, err = co.Read(p)
} else {
var length uint16
if err := binary.Read(co.Conn, binary.BigEndian, &length); err != nil {
return nil, err
}
p = make([]byte, length)
n, err = io.ReadFull(co.Conn, p)
} }
if err != nil { if err != nil {
@ -258,74 +276,26 @@ func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) {
return p, err return p, err
} }
// tcpMsgLen is a helper func to read first two bytes of stream as uint16 packet length.
func tcpMsgLen(t io.Reader) (int, error) {
p := []byte{0, 0}
n, err := t.Read(p)
if err != nil {
return 0, err
}
// As seen with my local router/switch, returns 1 byte on the above read,
// resulting a a ShortRead. Just write it out (instead of loop) and read the
// other byte.
if n == 1 {
n1, err := t.Read(p[1:])
if err != nil {
return 0, err
}
n += n1
}
if n != 2 {
return 0, ErrShortRead
}
l := binary.BigEndian.Uint16(p)
if l == 0 {
return 0, ErrShortRead
}
return int(l), nil
}
// tcpRead calls TCPConn.Read enough times to fill allocated buffer.
func tcpRead(t io.Reader, p []byte) (int, error) {
n, err := t.Read(p)
if err != nil {
return n, err
}
for n < len(p) {
j, err := t.Read(p[n:])
if err != nil {
return n, err
}
n += j
}
return n, err
}
// Read implements the net.Conn read method. // Read implements the net.Conn read method.
func (co *Conn) Read(p []byte) (n int, err error) { func (co *Conn) Read(p []byte) (n int, err error) {
if co.Conn == nil { if co.Conn == nil {
return 0, ErrConnEmpty return 0, ErrConnEmpty
} }
if len(p) < 2 {
return 0, io.ErrShortBuffer
}
switch t := co.Conn.(type) {
case *net.TCPConn, *tls.Conn:
r := t.(io.Reader)
l, err := tcpMsgLen(r) if _, ok := co.Conn.(net.PacketConn); ok {
if err != nil {
return 0, err
}
if l > len(p) {
return l, io.ErrShortBuffer
}
return tcpRead(r, p[:l])
}
// UDP connection // UDP connection
return co.Conn.Read(p) return co.Conn.Read(p)
}
var length uint16
if err := binary.Read(co.Conn, binary.BigEndian, &length); err != nil {
return 0, err
}
if int(length) > len(p) {
return 0, io.ErrShortBuffer
}
return io.ReadFull(co.Conn, p[:length])
} }
// WriteMsg sends a message through the connection co. // WriteMsg sends a message through the connection co.
@ -352,25 +322,20 @@ func (co *Conn) WriteMsg(m *Msg) (err error) {
} }
// Write implements the net.Conn Write method. // Write implements the net.Conn Write method.
func (co *Conn) Write(p []byte) (n int, err error) { func (co *Conn) Write(p []byte) (int, error) {
switch t := co.Conn.(type) { if len(p) > MaxMsgSize {
case *net.TCPConn, *tls.Conn:
w := t.(io.Writer)
lp := len(p)
if lp < 2 {
return 0, io.ErrShortBuffer
}
if lp > MaxMsgSize {
return 0, &Error{err: "message too large"} return 0, &Error{err: "message too large"}
} }
l := make([]byte, 2, lp+2)
binary.BigEndian.PutUint16(l, uint16(lp)) if _, ok := co.Conn.(net.PacketConn); ok {
p = append(l, p...)
n, err := io.Copy(w, bytes.NewReader(p))
return int(n), err
}
return co.Conn.Write(p) return co.Conn.Write(p)
}
l := make([]byte, 2)
binary.BigEndian.PutUint16(l, uint16(len(p)))
n, err := (&net.Buffers{l, p}).WriteTo(co.Conn)
return int(n), err
} }
// Return the appropriate timeout for a specific request // Return the appropriate timeout for a specific request
@ -413,7 +378,7 @@ func ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, err error)
// ExchangeConn performs a synchronous query. It sends the message m via the connection // ExchangeConn performs a synchronous query. It sends the message m via the connection
// c and waits for a reply. The connection c is not closed by ExchangeConn. // c and waits for a reply. The connection c is not closed by ExchangeConn.
// This function is going away, but can easily be mimicked: // Deprecated: This function is going away, but can easily be mimicked:
// //
// co := &dns.Conn{Conn: c} // c is your net.Conn // co := &dns.Conn{Conn: c} // c is your net.Conn
// co.WriteMsg(m) // co.WriteMsg(m)

View File

@ -68,14 +68,10 @@ func ClientConfigFromReader(resolvconf io.Reader) (*ClientConfig, error) {
} }
case "search": // set search path to given servers case "search": // set search path to given servers
c.Search = make([]string, len(f)-1) c.Search = append([]string(nil), f[1:]...)
for i := 0; i < len(c.Search); i++ {
c.Search[i] = f[i+1]
}
case "options": // magic options case "options": // magic options
for i := 1; i < len(f); i++ { for _, s := range f[1:] {
s := f[i]
switch { switch {
case len(s) >= 6 && s[:6] == "ndots:": case len(s) >= 6 && s[:6] == "ndots:":
n, _ := strconv.Atoi(s[6:]) n, _ := strconv.Atoi(s[6:])

View File

@ -105,7 +105,7 @@ func (dns *Msg) SetAxfr(z string) *Msg {
// SetTsig appends a TSIG RR to the message. // SetTsig appends a TSIG RR to the message.
// This is only a skeleton TSIG RR that is added as the last RR in the // This is only a skeleton TSIG RR that is added as the last RR in the
// additional section. The Tsig is calculated when the message is being send. // additional section. The TSIG is calculated when the message is being send.
func (dns *Msg) SetTsig(z, algo string, fudge uint16, timesigned int64) *Msg { func (dns *Msg) SetTsig(z, algo string, fudge uint16, timesigned int64) *Msg {
t := new(TSIG) t := new(TSIG)
t.Hdr = RR_Header{z, TypeTSIG, ClassANY, 0, 0} t.Hdr = RR_Header{z, TypeTSIG, ClassANY, 0, 0}
@ -146,10 +146,9 @@ func (dns *Msg) IsTsig() *TSIG {
// record in the additional section will do. It returns the OPT record // record in the additional section will do. It returns the OPT record
// found or nil. // found or nil.
func (dns *Msg) IsEdns0() *OPT { func (dns *Msg) IsEdns0() *OPT {
// EDNS0 is at the end of the additional section, start there. // RFC 6891, Section 6.1.1 allows the OPT record to appear
// We might want to change this to *only* look at the last two // anywhere in the additional record section, but it's usually at
// records. So we see TSIG and/or OPT - this a slightly bigger // the end so start there.
// change though.
for i := len(dns.Extra) - 1; i >= 0; i-- { for i := len(dns.Extra) - 1; i >= 0; i-- {
if dns.Extra[i].Header().Rrtype == TypeOPT { if dns.Extra[i].Header().Rrtype == TypeOPT {
return dns.Extra[i].(*OPT) return dns.Extra[i].(*OPT)
@ -158,6 +157,21 @@ func (dns *Msg) IsEdns0() *OPT {
return nil return nil
} }
// popEdns0 is like IsEdns0, but it removes the record from the message.
func (dns *Msg) popEdns0() *OPT {
// RFC 6891, Section 6.1.1 allows the OPT record to appear
// anywhere in the additional record section, but it's usually at
// the end so start there.
for i := len(dns.Extra) - 1; i >= 0; i-- {
if dns.Extra[i].Header().Rrtype == TypeOPT {
opt := dns.Extra[i].(*OPT)
dns.Extra = append(dns.Extra[:i], dns.Extra[i+1:]...)
return opt
}
}
return nil
}
// IsDomainName checks if s is a valid domain name, it returns the number of // IsDomainName checks if s is a valid domain name, it returns the number of
// labels and true, when a domain name is valid. Note that non fully qualified // labels and true, when a domain name is valid. Note that non fully qualified
// domain name is considered valid, in this case the last label is counted in // domain name is considered valid, in this case the last label is counted in
@ -303,6 +317,12 @@ func Fqdn(s string) string {
return s + "." return s + "."
} }
// CanonicalName returns the domain name in canonical form. A name in canonical
// form is lowercase and fully qualified. See Section 6.2 in RFC 4034.
func CanonicalName(s string) string {
return strings.ToLower(Fqdn(s))
}
// Copied from the official Go code. // Copied from the official Go code.
// ReverseAddr returns the in-addr.arpa. or ip6.arpa. hostname of the IP // ReverseAddr returns the in-addr.arpa. or ip6.arpa. hostname of the IP
@ -350,7 +370,7 @@ func (t Type) String() string {
// String returns the string representation for the class c. // String returns the string representation for the class c.
func (c Class) String() string { func (c Class) String() string {
if s, ok := ClassToString[uint16(c)]; ok { if s, ok := ClassToString[uint16(c)]; ok {
// Only emit mnemonics when they are unambiguous, specically ANY is in both. // Only emit mnemonics when they are unambiguous, specially ANY is in both.
if _, ok := StringToType[s]; !ok { if _, ok := StringToType[s]; !ok {
return s return s
} }

4
vendor/github.com/miekg/dns/dns.go generated vendored
View File

@ -54,7 +54,7 @@ type RR interface {
// parse parses an RR from zone file format. // 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. // This will only be called on a new and empty RR type with only the header populated.
parse(c *zlexer, origin, file string) *ParseError parse(c *zlexer, origin string) *ParseError
// isDuplicate returns whether the two RRs are duplicates. // isDuplicate returns whether the two RRs are duplicates.
isDuplicate(r2 RR) bool isDuplicate(r2 RR) bool
@ -105,7 +105,7 @@ func (h *RR_Header) unpack(msg []byte, off int) (int, error) {
panic("dns: internal error: unpack should never be called on RR_Header") panic("dns: internal error: unpack should never be called on RR_Header")
} }
func (h *RR_Header) parse(c *zlexer, origin, file string) *ParseError { func (h *RR_Header) parse(c *zlexer, origin string) *ParseError {
panic("dns: internal error: parse should never be called on RR_Header") panic("dns: internal error: parse should never be called on RR_Header")
} }

126
vendor/github.com/miekg/dns/dnssec.go generated vendored
View File

@ -3,10 +3,8 @@ package dns
import ( import (
"bytes" "bytes"
"crypto" "crypto"
"crypto/dsa"
"crypto/ecdsa" "crypto/ecdsa"
"crypto/elliptic" "crypto/elliptic"
_ "crypto/md5"
"crypto/rand" "crypto/rand"
"crypto/rsa" "crypto/rsa"
_ "crypto/sha1" _ "crypto/sha1"
@ -141,8 +139,8 @@ func (k *DNSKEY) KeyTag() uint16 {
switch k.Algorithm { switch k.Algorithm {
case RSAMD5: case RSAMD5:
// Look at the bottom two bytes of the modules, which the last // Look at the bottom two bytes of the modules, which the last
// item in the pubkey. We could do this faster by looking directly // item in the pubkey.
// at the base64 values. But I'm lazy. // This algorithm has been deprecated, but keep this key-tag calculation.
modulus, _ := fromBase64([]byte(k.PublicKey)) modulus, _ := fromBase64([]byte(k.PublicKey))
if len(modulus) > 1 { if len(modulus) > 1 {
x := binary.BigEndian.Uint16(modulus[len(modulus)-2:]) x := binary.BigEndian.Uint16(modulus[len(modulus)-2:])
@ -200,7 +198,7 @@ func (k *DNSKEY) ToDS(h uint8) *DS {
wire = wire[:n] wire = wire[:n]
owner := make([]byte, 255) owner := make([]byte, 255)
off, err1 := PackDomainName(strings.ToLower(k.Hdr.Name), owner, 0, nil, false) off, err1 := PackDomainName(CanonicalName(k.Hdr.Name), owner, 0, nil, false)
if err1 != nil { if err1 != nil {
return nil return nil
} }
@ -285,7 +283,7 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
sigwire.Inception = rr.Inception sigwire.Inception = rr.Inception
sigwire.KeyTag = rr.KeyTag sigwire.KeyTag = rr.KeyTag
// For signing, lowercase this name // For signing, lowercase this name
sigwire.SignerName = strings.ToLower(rr.SignerName) sigwire.SignerName = CanonicalName(rr.SignerName)
// Create the desired binary blob // Create the desired binary blob
signdata := make([]byte, DefaultMsgSize) signdata := make([]byte, DefaultMsgSize)
@ -318,6 +316,10 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
} }
rr.Signature = toBase64(signature) rr.Signature = toBase64(signature)
return nil
case RSAMD5, DSA, DSANSEC3SHA1:
// See RFC 6944.
return ErrAlg
default: default:
h := hash.New() h := hash.New()
h.Write(signdata) h.Write(signdata)
@ -329,9 +331,8 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
} }
rr.Signature = toBase64(signature) rr.Signature = toBase64(signature)
}
return nil return nil
}
} }
func sign(k crypto.Signer, hashed []byte, hash crypto.Hash, alg uint8) ([]byte, error) { func sign(k crypto.Signer, hashed []byte, hash crypto.Hash, alg uint8) ([]byte, error) {
@ -343,7 +344,6 @@ func sign(k crypto.Signer, hashed []byte, hash crypto.Hash, alg uint8) ([]byte,
switch alg { switch alg {
case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512: case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512:
return signature, nil return signature, nil
case ECDSAP256SHA256, ECDSAP384SHA384: case ECDSAP256SHA256, ECDSAP384SHA384:
ecdsaSignature := &struct { ecdsaSignature := &struct {
R, S *big.Int R, S *big.Int
@ -363,20 +363,11 @@ func sign(k crypto.Signer, hashed []byte, hash crypto.Hash, alg uint8) ([]byte,
signature := intToBytes(ecdsaSignature.R, intlen) signature := intToBytes(ecdsaSignature.R, intlen)
signature = append(signature, intToBytes(ecdsaSignature.S, intlen)...) signature = append(signature, intToBytes(ecdsaSignature.S, intlen)...)
return signature, nil return signature, nil
// There is no defined interface for what a DSA backed crypto.Signer returns
case DSA, DSANSEC3SHA1:
// t := divRoundUp(divRoundUp(p.PublicKey.Y.BitLen(), 8)-64, 8)
// signature := []byte{byte(t)}
// signature = append(signature, intToBytes(r1, 20)...)
// signature = append(signature, intToBytes(s1, 20)...)
// rr.Signature = signature
case ED25519: case ED25519:
return signature, nil return signature, nil
} default:
return nil, ErrAlg return nil, ErrAlg
}
} }
// Verify validates an RRSet with the signature and key. This is only the // Verify validates an RRSet with the signature and key. This is only the
@ -420,7 +411,7 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
sigwire.Expiration = rr.Expiration sigwire.Expiration = rr.Expiration
sigwire.Inception = rr.Inception sigwire.Inception = rr.Inception
sigwire.KeyTag = rr.KeyTag sigwire.KeyTag = rr.KeyTag
sigwire.SignerName = strings.ToLower(rr.SignerName) sigwire.SignerName = CanonicalName(rr.SignerName)
// Create the desired binary blob // Create the desired binary blob
signeddata := make([]byte, DefaultMsgSize) signeddata := make([]byte, DefaultMsgSize)
n, err := packSigWire(sigwire, signeddata) n, err := packSigWire(sigwire, signeddata)
@ -445,7 +436,7 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
} }
switch rr.Algorithm { switch rr.Algorithm {
case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512, RSAMD5: case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512:
// TODO(mg): this can be done quicker, ie. cache the pubkey data somewhere?? // TODO(mg): this can be done quicker, ie. cache the pubkey data somewhere??
pubkey := k.publicKeyRSA() // Get the key pubkey := k.publicKeyRSA() // Get the key
if pubkey == nil { if pubkey == nil {
@ -556,19 +547,18 @@ func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey {
pubkey := new(rsa.PublicKey) pubkey := new(rsa.PublicKey)
var expo uint64 var expo uint64
for i := 0; i < int(explen); i++ { // The exponent of length explen is between keyoff and modoff.
for _, v := range keybuf[keyoff:modoff] {
expo <<= 8 expo <<= 8
expo |= uint64(keybuf[keyoff+i]) expo |= uint64(v)
} }
if expo > 1<<31-1 { if expo > 1<<31-1 {
// Larger exponent than supported by the crypto package. // Larger exponent than supported by the crypto package.
return nil return nil
} }
pubkey.E = int(expo) pubkey.E = int(expo)
pubkey.N = new(big.Int).SetBytes(keybuf[modoff:])
pubkey.N = big.NewInt(0)
pubkey.N.SetBytes(keybuf[modoff:])
return pubkey return pubkey
} }
@ -593,34 +583,8 @@ func (k *DNSKEY) publicKeyECDSA() *ecdsa.PublicKey {
return nil return nil
} }
} }
pubkey.X = big.NewInt(0) pubkey.X = new(big.Int).SetBytes(keybuf[:len(keybuf)/2])
pubkey.X.SetBytes(keybuf[:len(keybuf)/2]) pubkey.Y = new(big.Int).SetBytes(keybuf[len(keybuf)/2:])
pubkey.Y = big.NewInt(0)
pubkey.Y.SetBytes(keybuf[len(keybuf)/2:])
return pubkey
}
func (k *DNSKEY) publicKeyDSA() *dsa.PublicKey {
keybuf, err := fromBase64([]byte(k.PublicKey))
if err != nil {
return nil
}
if len(keybuf) < 22 {
return nil
}
t, keybuf := int(keybuf[0]), keybuf[1:]
size := 64 + t*8
q, keybuf := keybuf[:20], keybuf[20:]
if len(keybuf) != 3*size {
return nil
}
p, keybuf := keybuf[:size], keybuf[size:]
g, y := keybuf[:size], keybuf[size:]
pubkey := new(dsa.PublicKey)
pubkey.Parameters.Q = big.NewInt(0).SetBytes(q)
pubkey.Parameters.P = big.NewInt(0).SetBytes(p)
pubkey.Parameters.G = big.NewInt(0).SetBytes(g)
pubkey.Y = big.NewInt(0).SetBytes(y)
return pubkey return pubkey
} }
@ -659,7 +623,7 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
h.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
h.Name = strings.ToLower(h.Name) h.Name = CanonicalName(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,
@ -672,49 +636,49 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
// conversion. // conversion.
switch x := r1.(type) { switch x := r1.(type) {
case *NS: case *NS:
x.Ns = strings.ToLower(x.Ns) x.Ns = CanonicalName(x.Ns)
case *MD: case *MD:
x.Md = strings.ToLower(x.Md) x.Md = CanonicalName(x.Md)
case *MF: case *MF:
x.Mf = strings.ToLower(x.Mf) x.Mf = CanonicalName(x.Mf)
case *CNAME: case *CNAME:
x.Target = strings.ToLower(x.Target) x.Target = CanonicalName(x.Target)
case *SOA: case *SOA:
x.Ns = strings.ToLower(x.Ns) x.Ns = CanonicalName(x.Ns)
x.Mbox = strings.ToLower(x.Mbox) x.Mbox = CanonicalName(x.Mbox)
case *MB: case *MB:
x.Mb = strings.ToLower(x.Mb) x.Mb = CanonicalName(x.Mb)
case *MG: case *MG:
x.Mg = strings.ToLower(x.Mg) x.Mg = CanonicalName(x.Mg)
case *MR: case *MR:
x.Mr = strings.ToLower(x.Mr) x.Mr = CanonicalName(x.Mr)
case *PTR: case *PTR:
x.Ptr = strings.ToLower(x.Ptr) x.Ptr = CanonicalName(x.Ptr)
case *MINFO: case *MINFO:
x.Rmail = strings.ToLower(x.Rmail) x.Rmail = CanonicalName(x.Rmail)
x.Email = strings.ToLower(x.Email) x.Email = CanonicalName(x.Email)
case *MX: case *MX:
x.Mx = strings.ToLower(x.Mx) x.Mx = CanonicalName(x.Mx)
case *RP: case *RP:
x.Mbox = strings.ToLower(x.Mbox) x.Mbox = CanonicalName(x.Mbox)
x.Txt = strings.ToLower(x.Txt) x.Txt = CanonicalName(x.Txt)
case *AFSDB: case *AFSDB:
x.Hostname = strings.ToLower(x.Hostname) x.Hostname = CanonicalName(x.Hostname)
case *RT: case *RT:
x.Host = strings.ToLower(x.Host) x.Host = CanonicalName(x.Host)
case *SIG: case *SIG:
x.SignerName = strings.ToLower(x.SignerName) x.SignerName = CanonicalName(x.SignerName)
case *PX: case *PX:
x.Map822 = strings.ToLower(x.Map822) x.Map822 = CanonicalName(x.Map822)
x.Mapx400 = strings.ToLower(x.Mapx400) x.Mapx400 = CanonicalName(x.Mapx400)
case *NAPTR: case *NAPTR:
x.Replacement = strings.ToLower(x.Replacement) x.Replacement = CanonicalName(x.Replacement)
case *KX: case *KX:
x.Exchanger = strings.ToLower(x.Exchanger) x.Exchanger = CanonicalName(x.Exchanger)
case *SRV: case *SRV:
x.Target = strings.ToLower(x.Target) x.Target = CanonicalName(x.Target)
case *DNAME: case *DNAME:
x.Target = strings.ToLower(x.Target) x.Target = CanonicalName(x.Target)
} }
// 6.2. Canonical RR Form. (5) - origTTL // 6.2. Canonical RR Form. (5) - origTTL
wire := make([]byte, Len(r1)+1) // +1 to be safe(r) wire := make([]byte, Len(r1)+1) // +1 to be safe(r)

View File

@ -2,7 +2,6 @@ package dns
import ( import (
"crypto" "crypto"
"crypto/dsa"
"crypto/ecdsa" "crypto/ecdsa"
"crypto/elliptic" "crypto/elliptic"
"crypto/rand" "crypto/rand"
@ -20,11 +19,7 @@ import (
// bits should be set to the size of the algorithm. // bits should be set to the size of the algorithm.
func (k *DNSKEY) Generate(bits int) (crypto.PrivateKey, error) { func (k *DNSKEY) Generate(bits int) (crypto.PrivateKey, error) {
switch k.Algorithm { switch k.Algorithm {
case DSA, DSANSEC3SHA1: case RSASHA1, RSASHA256, RSASHA1NSEC3SHA1:
if bits != 1024 {
return nil, ErrKeySize
}
case RSAMD5, RSASHA1, RSASHA256, RSASHA1NSEC3SHA1:
if bits < 512 || bits > 4096 { if bits < 512 || bits > 4096 {
return nil, ErrKeySize return nil, ErrKeySize
} }
@ -44,23 +39,12 @@ func (k *DNSKEY) Generate(bits int) (crypto.PrivateKey, error) {
if bits != 256 { if bits != 256 {
return nil, ErrKeySize return nil, ErrKeySize
} }
default:
return nil, ErrAlg
} }
switch k.Algorithm { switch k.Algorithm {
case DSA, DSANSEC3SHA1: case RSASHA1, RSASHA256, RSASHA512, RSASHA1NSEC3SHA1:
params := new(dsa.Parameters)
if err := dsa.GenerateParameters(params, rand.Reader, dsa.L1024N160); err != nil {
return nil, err
}
priv := new(dsa.PrivateKey)
priv.PublicKey.Parameters = *params
err := dsa.GenerateKey(priv, rand.Reader)
if err != nil {
return nil, err
}
k.setPublicKeyDSA(params.Q, params.P, params.G, priv.PublicKey.Y)
return priv, nil
case RSAMD5, RSASHA1, RSASHA256, RSASHA512, RSASHA1NSEC3SHA1:
priv, err := rsa.GenerateKey(rand.Reader, bits) priv, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil { if err != nil {
return nil, err return nil, err
@ -120,16 +104,6 @@ func (k *DNSKEY) setPublicKeyECDSA(_X, _Y *big.Int) bool {
return true return true
} }
// Set the public key for DSA
func (k *DNSKEY) setPublicKeyDSA(_Q, _P, _G, _Y *big.Int) bool {
if _Q == nil || _P == nil || _G == nil || _Y == nil {
return false
}
buf := dsaToBuf(_Q, _P, _G, _Y)
k.PublicKey = toBase64(buf)
return true
}
// Set the public key for Ed25519 // Set the public key for Ed25519
func (k *DNSKEY) setPublicKeyED25519(_K ed25519.PublicKey) bool { func (k *DNSKEY) setPublicKeyED25519(_K ed25519.PublicKey) bool {
if _K == nil { if _K == nil {
@ -164,15 +138,3 @@ func curveToBuf(_X, _Y *big.Int, intlen int) []byte {
buf = append(buf, intToBytes(_Y, intlen)...) buf = append(buf, intToBytes(_Y, intlen)...)
return buf return buf
} }
// Set the public key for X and Y for Curve. The two
// values are just concatenated.
func dsaToBuf(_Q, _P, _G, _Y *big.Int) []byte {
t := divRoundUp(divRoundUp(_G.BitLen(), 8)-64, 8)
buf := []byte{byte(t)}
buf = append(buf, intToBytes(_Q, 20)...)
buf = append(buf, intToBytes(_P, 64+t*8)...)
buf = append(buf, intToBytes(_G, 64+t*8)...)
buf = append(buf, intToBytes(_Y, 64+t*8)...)
return buf
}

View File

@ -3,7 +3,6 @@ package dns
import ( import (
"bufio" "bufio"
"crypto" "crypto"
"crypto/dsa"
"crypto/ecdsa" "crypto/ecdsa"
"crypto/rsa" "crypto/rsa"
"io" "io"
@ -44,26 +43,7 @@ func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, er
return nil, ErrPrivKey return nil, ErrPrivKey
} }
switch uint8(algo) { switch uint8(algo) {
case DSA: case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512:
priv, err := readPrivateKeyDSA(m)
if err != nil {
return nil, err
}
pub := k.publicKeyDSA()
if pub == nil {
return nil, ErrKey
}
priv.PublicKey = *pub
return priv, nil
case RSAMD5:
fallthrough
case RSASHA1:
fallthrough
case RSASHA1NSEC3SHA1:
fallthrough
case RSASHA256:
fallthrough
case RSASHA512:
priv, err := readPrivateKeyRSA(m) priv, err := readPrivateKeyRSA(m)
if err != nil { if err != nil {
return nil, err return nil, err
@ -74,11 +54,7 @@ func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, er
} }
priv.PublicKey = *pub priv.PublicKey = *pub
return priv, nil return priv, nil
case ECCGOST: case ECDSAP256SHA256, ECDSAP384SHA384:
return nil, ErrPrivKey
case ECDSAP256SHA256:
fallthrough
case ECDSAP384SHA384:
priv, err := readPrivateKeyECDSA(m) priv, err := readPrivateKeyECDSA(m)
if err != nil { if err != nil {
return nil, err return nil, err
@ -92,7 +68,7 @@ func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, er
case ED25519: case ED25519:
return readPrivateKeyED25519(m) return readPrivateKeyED25519(m)
default: default:
return nil, ErrPrivKey return nil, ErrAlg
} }
} }
@ -109,21 +85,16 @@ func readPrivateKeyRSA(m map[string]string) (*rsa.PrivateKey, error) {
} }
switch k { switch k {
case "modulus": case "modulus":
p.PublicKey.N = big.NewInt(0) p.PublicKey.N = new(big.Int).SetBytes(v1)
p.PublicKey.N.SetBytes(v1)
case "publicexponent": case "publicexponent":
i := big.NewInt(0) i := new(big.Int).SetBytes(v1)
i.SetBytes(v1)
p.PublicKey.E = int(i.Int64()) // int64 should be large enough p.PublicKey.E = int(i.Int64()) // int64 should be large enough
case "privateexponent": case "privateexponent":
p.D = big.NewInt(0) p.D = new(big.Int).SetBytes(v1)
p.D.SetBytes(v1)
case "prime1": case "prime1":
p.Primes[0] = big.NewInt(0) p.Primes[0] = new(big.Int).SetBytes(v1)
p.Primes[0].SetBytes(v1)
case "prime2": case "prime2":
p.Primes[1] = big.NewInt(0) p.Primes[1] = new(big.Int).SetBytes(v1)
p.Primes[1].SetBytes(v1)
} }
case "exponent1", "exponent2", "coefficient": case "exponent1", "exponent2", "coefficient":
// not used in Go (yet) // not used in Go (yet)
@ -134,27 +105,9 @@ func readPrivateKeyRSA(m map[string]string) (*rsa.PrivateKey, error) {
return p, nil return p, nil
} }
func readPrivateKeyDSA(m map[string]string) (*dsa.PrivateKey, error) {
p := new(dsa.PrivateKey)
p.X = big.NewInt(0)
for k, v := range m {
switch k {
case "private_value(x)":
v1, err := fromBase64([]byte(v))
if err != nil {
return nil, err
}
p.X.SetBytes(v1)
case "created", "publish", "activate":
/* not used in Go (yet) */
}
}
return p, nil
}
func readPrivateKeyECDSA(m map[string]string) (*ecdsa.PrivateKey, error) { func readPrivateKeyECDSA(m map[string]string) (*ecdsa.PrivateKey, error) {
p := new(ecdsa.PrivateKey) p := new(ecdsa.PrivateKey)
p.D = big.NewInt(0) p.D = new(big.Int)
// TODO: validate that the required flags are present // TODO: validate that the required flags are present
for k, v := range m { for k, v := range m {
switch k { switch k {
@ -322,6 +275,11 @@ func (kl *klexer) Next() (lex, bool) {
commt = false commt = false
} }
if kl.key && str.Len() == 0 {
// ignore empty lines
break
}
kl.key = true kl.key = true
l.value = zValue l.value = zValue

View File

@ -2,7 +2,6 @@ package dns
import ( import (
"crypto" "crypto"
"crypto/dsa"
"crypto/ecdsa" "crypto/ecdsa"
"crypto/rsa" "crypto/rsa"
"math/big" "math/big"
@ -13,10 +12,12 @@ import (
const format = "Private-key-format: v1.3\n" const format = "Private-key-format: v1.3\n"
var bigIntOne = big.NewInt(1)
// PrivateKeyString converts a PrivateKey to a string. This string has the same // PrivateKeyString converts a PrivateKey to a string. This string has the same
// format as the private-key-file of BIND9 (Private-key-format: v1.3). // format as the private-key-file of BIND9 (Private-key-format: v1.3).
// It needs some info from the key (the algorithm), so its a method of the DNSKEY // It needs some info from the key (the algorithm), so its a method of the DNSKEY.
// It supports rsa.PrivateKey, ecdsa.PrivateKey and dsa.PrivateKey // It supports *rsa.PrivateKey, *ecdsa.PrivateKey and ed25519.PrivateKey.
func (r *DNSKEY) PrivateKeyString(p crypto.PrivateKey) string { func (r *DNSKEY) PrivateKeyString(p crypto.PrivateKey) string {
algorithm := strconv.Itoa(int(r.Algorithm)) algorithm := strconv.Itoa(int(r.Algorithm))
algorithm += " (" + AlgorithmToString[r.Algorithm] + ")" algorithm += " (" + AlgorithmToString[r.Algorithm] + ")"
@ -31,12 +32,11 @@ func (r *DNSKEY) PrivateKeyString(p crypto.PrivateKey) string {
prime2 := toBase64(p.Primes[1].Bytes()) prime2 := toBase64(p.Primes[1].Bytes())
// Calculate Exponent1/2 and Coefficient as per: http://en.wikipedia.org/wiki/RSA#Using_the_Chinese_remainder_algorithm // Calculate Exponent1/2 and Coefficient as per: http://en.wikipedia.org/wiki/RSA#Using_the_Chinese_remainder_algorithm
// and from: http://code.google.com/p/go/issues/detail?id=987 // and from: http://code.google.com/p/go/issues/detail?id=987
one := big.NewInt(1) p1 := new(big.Int).Sub(p.Primes[0], bigIntOne)
p1 := big.NewInt(0).Sub(p.Primes[0], one) q1 := new(big.Int).Sub(p.Primes[1], bigIntOne)
q1 := big.NewInt(0).Sub(p.Primes[1], one) exp1 := new(big.Int).Mod(p.D, p1)
exp1 := big.NewInt(0).Mod(p.D, p1) exp2 := new(big.Int).Mod(p.D, q1)
exp2 := big.NewInt(0).Mod(p.D, q1) coeff := new(big.Int).ModInverse(p.Primes[1], p.Primes[0])
coeff := big.NewInt(0).ModInverse(p.Primes[1], p.Primes[0])
exponent1 := toBase64(exp1.Bytes()) exponent1 := toBase64(exp1.Bytes())
exponent2 := toBase64(exp2.Bytes()) exponent2 := toBase64(exp2.Bytes())
@ -66,21 +66,6 @@ func (r *DNSKEY) PrivateKeyString(p crypto.PrivateKey) string {
"Algorithm: " + algorithm + "\n" + "Algorithm: " + algorithm + "\n" +
"PrivateKey: " + private + "\n" "PrivateKey: " + private + "\n"
case *dsa.PrivateKey:
T := divRoundUp(divRoundUp(p.PublicKey.Parameters.G.BitLen(), 8)-64, 8)
prime := toBase64(intToBytes(p.PublicKey.Parameters.P, 64+T*8))
subprime := toBase64(intToBytes(p.PublicKey.Parameters.Q, 20))
base := toBase64(intToBytes(p.PublicKey.Parameters.G, 64+T*8))
priv := toBase64(intToBytes(p.X, 20))
pub := toBase64(intToBytes(p.PublicKey.Y, 64+T*8))
return format +
"Algorithm: " + algorithm + "\n" +
"Prime(p): " + prime + "\n" +
"Subprime(q): " + subprime + "\n" +
"Base(g): " + base + "\n" +
"Private_value(x): " + priv + "\n" +
"Public_value(y): " + pub + "\n"
case ed25519.PrivateKey: case ed25519.PrivateKey:
private := toBase64(p.Seed()) private := toBase64(p.Seed())
return format + return format +

13
vendor/github.com/miekg/dns/doc.go generated vendored
View File

@ -83,7 +83,7 @@ with:
in, err := dns.Exchange(m1, "127.0.0.1:53") in, err := dns.Exchange(m1, "127.0.0.1:53")
When this functions returns you will get dns message. A dns message consists When this functions returns you will get DNS message. A DNS message consists
out of four sections. out of four sections.
The question section: in.Question, the answer section: in.Answer, The question section: in.Question, the answer section: in.Answer,
the authority section: in.Ns and the additional section: in.Extra. the authority section: in.Ns and the additional section: in.Extra.
@ -209,7 +209,7 @@ Basic use pattern validating and replying to a message that has TSIG set.
// *Msg r has an TSIG record and it was validated // *Msg r has an TSIG record and it was validated
m.SetTsig("axfr.", dns.HmacMD5, 300, time.Now().Unix()) m.SetTsig("axfr.", dns.HmacMD5, 300, time.Now().Unix())
} else { } else {
// *Msg r has an TSIG records and it was not valided // *Msg r has an TSIG records and it was not validated
} }
} }
w.WriteMsg(m) w.WriteMsg(m)
@ -221,7 +221,7 @@ RFC 6895 sets aside a range of type codes for private use. This range is 65,280
- 65,534 (0xFF00 - 0xFFFE). When experimenting with new Resource Records these - 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 https://miek.nl/2014/September/21/idn-and-private-rr-in-go-dns/ for more See https://miek.nl/2014/september/21/idn-and-private-rr-in-go-dns/ for more
information. information.
EDNS0 EDNS0
@ -238,9 +238,8 @@ Basic use pattern for creating an (empty) OPT RR:
The rdata of an OPT RR consists out of a slice of EDNS0 (RFC 6891) interfaces. The rdata of an OPT RR consists out of a slice of EDNS0 (RFC 6891) interfaces.
Currently only a few have been standardized: EDNS0_NSID (RFC 5001) and Currently only a few have been standardized: EDNS0_NSID (RFC 5001) and
EDNS0_SUBNET (draft-vandergaast-edns-client-subnet-02). Note that these options EDNS0_SUBNET (RFC 7871). Note 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 {
@ -261,7 +260,7 @@ From RFC 2931:
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 It works like TSIG, except that SIG(0) uses public key cryptography, instead of
the shared secret approach in TSIG. Supported algorithms: DSA, ECDSAP256SHA256, the shared secret approach in TSIG. Supported algorithms: ECDSAP256SHA256,
ECDSAP384SHA384, RSASHA1, RSASHA256 and RSASHA512. ECDSAP384SHA384, RSASHA1, RSASHA256 and RSASHA512.
Signing subsequent messages in multi-message sessions is not implemented. Signing subsequent messages in multi-message sessions is not implemented.

View File

@ -3,9 +3,8 @@ package dns
//go:generate go run duplicate_generate.go //go:generate go run duplicate_generate.go
// IsDuplicate checks of r1 and r2 are duplicates of each other, excluding the TTL. // 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 // So this means the header data is equal *and* the RDATA is the same. Returns true
// is so, otherwise false. // if so, otherwise false. It's a protocol violation to have identical RRs in a message.
// It's is a protocol violation to have identical RRs in a message.
func IsDuplicate(r1, r2 RR) bool { func IsDuplicate(r1, r2 RR) bool {
// Check whether the record header is identical. // Check whether the record header is identical.
if !r1.Header().isDuplicate(r2.Header()) { if !r1.Header().isDuplicate(r2.Header()) {
@ -27,12 +26,12 @@ func (r1 *RR_Header) isDuplicate(_r2 RR) bool {
if r1.Rrtype != r2.Rrtype { if r1.Rrtype != r2.Rrtype {
return false return false
} }
if !isDulicateName(r1.Name, r2.Name) { if !isDuplicateName(r1.Name, r2.Name) {
return false return false
} }
// ignore TTL // ignore TTL
return true return true
} }
// isDulicateName checks if the domain names s1 and s2 are equal. // isDuplicateName checks if the domain names s1 and s2 are equal.
func isDulicateName(s1, s2 string) bool { return equal(s1, s2) } func isDuplicateName(s1, s2 string) bool { return equal(s1, s2) }

50
vendor/github.com/miekg/dns/edns.go generated vendored
View File

@ -80,15 +80,15 @@ func (rr *OPT) String() string {
func (rr *OPT) len(off int, compression map[string]struct{}) int { func (rr *OPT) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len(off, compression)
for i := 0; i < len(rr.Option); i++ { for _, o := range rr.Option {
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, _ := o.pack()
l += len(lo) l += len(lo)
} }
return l return l
} }
func (rr *OPT) parse(c *zlexer, origin, file string) *ParseError { func (rr *OPT) parse(c *zlexer, origin string) *ParseError {
panic("dns: internal error: parse should never be called on OPT") panic("dns: internal error: parse should never be called on OPT")
} }
@ -360,7 +360,7 @@ func (e *EDNS0_COOKIE) copy() EDNS0 { return &EDNS0_COOKIE{e.Code, e.C
// The EDNS0_UL (Update Lease) (draft RFC) option is used to tell the server to set // 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
// up after themselves. This is a draft RFC and more information can be found at // up after themselves. This is a draft RFC and more information can be found at
// http://files.dns-sd.org/draft-sekar-dns-ul.txt // https://tools.ietf.org/html/draft-sekar-dns-ul-02
// //
// o := new(dns.OPT) // o := new(dns.OPT)
// o.Hdr.Name = "." // o.Hdr.Name = "."
@ -372,22 +372,34 @@ func (e *EDNS0_COOKIE) copy() EDNS0 { return &EDNS0_COOKIE{e.Code, e.C
type EDNS0_UL struct { type EDNS0_UL struct {
Code uint16 // Always EDNS0UL Code uint16 // Always EDNS0UL
Lease uint32 Lease uint32
KeyLease uint32
} }
// 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 fmt.Sprintf("%d %d", e.Lease, e.KeyLease) }
func (e *EDNS0_UL) copy() EDNS0 { return &EDNS0_UL{e.Code, e.Lease} } func (e *EDNS0_UL) copy() EDNS0 { return &EDNS0_UL{e.Code, e.Lease, e.KeyLease} }
// 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) {
b := make([]byte, 4) var b []byte
if e.KeyLease == 0 {
b = make([]byte, 4)
} else {
b = make([]byte, 8)
binary.BigEndian.PutUint32(b[4:], e.KeyLease)
}
binary.BigEndian.PutUint32(b, e.Lease) binary.BigEndian.PutUint32(b, e.Lease)
return b, nil return b, nil
} }
func (e *EDNS0_UL) unpack(b []byte) error { func (e *EDNS0_UL) unpack(b []byte) error {
if len(b) < 4 { switch len(b) {
case 4:
e.KeyLease = 0
case 8:
e.KeyLease = binary.BigEndian.Uint32(b[4:])
default:
return ErrBuf return ErrBuf
} }
e.Lease = binary.BigEndian.Uint32(b) e.Lease = binary.BigEndian.Uint32(b)
@ -453,11 +465,11 @@ func (e *EDNS0_DAU) unpack(b []byte) error { e.AlgCode = b; return nil }
func (e *EDNS0_DAU) String() string { func (e *EDNS0_DAU) String() string {
s := "" s := ""
for i := 0; i < len(e.AlgCode); i++ { for _, alg := range e.AlgCode {
if a, ok := AlgorithmToString[e.AlgCode[i]]; ok { if a, ok := AlgorithmToString[alg]; ok {
s += " " + a s += " " + a
} else { } else {
s += " " + strconv.Itoa(int(e.AlgCode[i])) s += " " + strconv.Itoa(int(alg))
} }
} }
return s return s
@ -477,11 +489,11 @@ func (e *EDNS0_DHU) unpack(b []byte) error { e.AlgCode = b; return nil }
func (e *EDNS0_DHU) String() string { func (e *EDNS0_DHU) String() string {
s := "" s := ""
for i := 0; i < len(e.AlgCode); i++ { for _, alg := range e.AlgCode {
if a, ok := HashToString[e.AlgCode[i]]; ok { if a, ok := HashToString[alg]; ok {
s += " " + a s += " " + a
} else { } else {
s += " " + strconv.Itoa(int(e.AlgCode[i])) s += " " + strconv.Itoa(int(alg))
} }
} }
return s return s
@ -502,11 +514,11 @@ func (e *EDNS0_N3U) unpack(b []byte) error { e.AlgCode = b; return nil }
func (e *EDNS0_N3U) String() string { func (e *EDNS0_N3U) String() string {
// Re-use the hash map // Re-use the hash map
s := "" s := ""
for i := 0; i < len(e.AlgCode); i++ { for _, alg := range e.AlgCode {
if a, ok := HashToString[e.AlgCode[i]]; ok { if a, ok := HashToString[alg]; ok {
s += " " + a s += " " + a
} else { } else {
s += " " + strconv.Itoa(int(e.AlgCode[i])) s += " " + strconv.Itoa(int(alg))
} }
} }
return s return s
@ -531,6 +543,10 @@ func (e *EDNS0_EXPIRE) pack() ([]byte, error) {
} }
func (e *EDNS0_EXPIRE) unpack(b []byte) error { func (e *EDNS0_EXPIRE) unpack(b []byte) error {
if len(b) == 0 {
// zero-length EXPIRE query, see RFC 7314 Section 2
return nil
}
if len(b) < 4 { if len(b) < 4 {
return ErrBuf return ErrBuf
} }

View File

@ -31,6 +31,9 @@ func Field(r RR, i int) string {
switch reflect.ValueOf(r).Elem().Type().Field(i).Tag { switch reflect.ValueOf(r).Elem().Type().Field(i).Tag {
case `dns:"a"`: case `dns:"a"`:
// TODO(miek): Hmm store this as 16 bytes // TODO(miek): Hmm store this as 16 bytes
if d.Len() < net.IPv4len {
return ""
}
if d.Len() < net.IPv6len { if d.Len() < net.IPv6len {
return net.IPv4(byte(d.Index(0).Uint()), return net.IPv4(byte(d.Index(0).Uint()),
byte(d.Index(1).Uint()), byte(d.Index(1).Uint()),
@ -42,6 +45,9 @@ func Field(r RR, i int) string {
byte(d.Index(14).Uint()), byte(d.Index(14).Uint()),
byte(d.Index(15).Uint())).String() byte(d.Index(15).Uint())).String()
case `dns:"aaaa"`: case `dns:"aaaa"`:
if d.Len() < net.IPv6len {
return ""
}
return net.IP{ return net.IP{
byte(d.Index(0).Uint()), byte(d.Index(0).Uint()),
byte(d.Index(1).Uint()), byte(d.Index(1).Uint()),

11
vendor/github.com/miekg/dns/fuzz.go generated vendored
View File

@ -2,6 +2,8 @@
package dns package dns
import "strings"
func Fuzz(data []byte) int { func Fuzz(data []byte) int {
msg := new(Msg) msg := new(Msg)
@ -16,7 +18,14 @@ func Fuzz(data []byte) int {
} }
func FuzzNewRR(data []byte) int { func FuzzNewRR(data []byte) int {
if _, err := NewRR(string(data)); err != nil { str := string(data)
// Do not fuzz lines that include the $INCLUDE keyword and hint the fuzzer
// at avoiding them.
// See GH#1025 for context.
if strings.Contains(strings.ToUpper(str), "$INCLUDE") {
return -1
}
if _, err := NewRR(str); err != nil {
return 0 return 0
} }
return 1 return 1

View File

@ -20,13 +20,13 @@ import (
// of $ after that are interpreted. // of $ after that are interpreted.
func (zp *ZoneParser) generate(l lex) (RR, bool) { func (zp *ZoneParser) generate(l lex) (RR, bool) {
token := l.token token := l.token
step := 1 step := int64(1)
if i := strings.IndexByte(token, '/'); i >= 0 { if i := strings.IndexByte(token, '/'); i >= 0 {
if i+1 == len(token) { if i+1 == len(token) {
return zp.setParseError("bad step in $GENERATE range", l) return zp.setParseError("bad step in $GENERATE range", l)
} }
s, err := strconv.Atoi(token[i+1:]) s, err := strconv.ParseInt(token[i+1:], 10, 64)
if err != nil || s <= 0 { if err != nil || s <= 0 {
return zp.setParseError("bad step in $GENERATE range", l) return zp.setParseError("bad step in $GENERATE range", l)
} }
@ -40,20 +40,24 @@ func (zp *ZoneParser) generate(l lex) (RR, bool) {
return zp.setParseError("bad start-stop in $GENERATE range", l) return zp.setParseError("bad start-stop in $GENERATE range", l)
} }
start, err := strconv.Atoi(sx[0]) start, err := strconv.ParseInt(sx[0], 10, 64)
if err != nil { if err != nil {
return zp.setParseError("bad start in $GENERATE range", l) return zp.setParseError("bad start in $GENERATE range", l)
} }
end, err := strconv.Atoi(sx[1]) end, err := strconv.ParseInt(sx[1], 10, 64)
if err != nil { if err != nil {
return zp.setParseError("bad stop in $GENERATE range", l) return zp.setParseError("bad stop in $GENERATE range", l)
} }
if end < 0 || start < 0 || end < start { if end < 0 || start < 0 || end < start || (end-start)/step > 65535 {
return zp.setParseError("bad range in $GENERATE range", l) return zp.setParseError("bad range in $GENERATE range", l)
} }
zp.c.Next() // _BLANK // _BLANK
l, ok := zp.c.Next()
if !ok || l.value != zBlank {
return zp.setParseError("garbage after $GENERATE range", l)
}
// Create a complete new string, which we then parse again. // Create a complete new string, which we then parse again.
var s string var s string
@ -71,16 +75,17 @@ func (zp *ZoneParser) generate(l lex) (RR, bool) {
r := &generateReader{ r := &generateReader{
s: s, s: s,
cur: start, cur: int(start),
start: start, start: int(start),
end: end, end: int(end),
step: step, step: int(step),
file: zp.file, file: zp.file,
lex: &l, lex: &l,
} }
zp.sub = NewZoneParser(r, zp.origin, zp.file) zp.sub = NewZoneParser(r, zp.origin, zp.file)
zp.sub.includeDepth, zp.sub.includeAllowed = zp.includeDepth, zp.includeAllowed zp.sub.includeDepth, zp.sub.includeAllowed = zp.includeDepth, zp.includeAllowed
zp.sub.generateDisallowed = true
zp.sub.SetDefaultTTL(defaultTtl) zp.sub.SetDefaultTTL(defaultTtl)
return zp.subNext() return zp.subNext()
} }
@ -183,7 +188,7 @@ func (r *generateReader) ReadByte() (byte, error) {
if errMsg != "" { if errMsg != "" {
return 0, r.parseError(errMsg, si+3+sep) return 0, r.parseError(errMsg, si+3+sep)
} }
if r.start+offset < 0 || r.end+offset > 1<<31-1 { if r.start+offset < 0 || int64(r.end) + int64(offset) > 1<<31-1 {
return 0, r.parseError("bad offset in $GENERATE", si+3+sep) return 0, r.parseError("bad offset in $GENERATE", si+3+sep)
} }
@ -224,19 +229,19 @@ func modToPrintf(s string) (string, int, string) {
return "", 0, "bad base in $GENERATE" return "", 0, "bad base in $GENERATE"
} }
offset, err := strconv.Atoi(offStr) offset, err := strconv.ParseInt(offStr, 10, 64)
if err != nil { if err != nil {
return "", 0, "bad offset in $GENERATE" return "", 0, "bad offset in $GENERATE"
} }
width, err := strconv.Atoi(widthStr) width, err := strconv.ParseInt(widthStr, 10, 64)
if err != nil || width < 0 || width > 255 { if err != nil || width < 0 || width > 255 {
return "", 0, "bad width in $GENERATE" return "", 0, "bad width in $GENERATE"
} }
if width == 0 { if width == 0 {
return "%" + base, offset, "" return "%" + base, int(offset), ""
} }
return "%0" + widthStr + base, offset, "" return "%0" + widthStr + base, int(offset), ""
} }

11
vendor/github.com/miekg/dns/go.mod generated vendored Normal file
View File

@ -0,0 +1,11 @@
module github.com/miekg/dns
go 1.12
require (
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550
golang.org/x/net v0.0.0-20190923162816-aa69164e4478
golang.org/x/sync v0.0.0-20190423024810-112230192c58
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425 // indirect
)

39
vendor/github.com/miekg/dns/go.sum generated vendored Normal file
View File

@ -0,0 +1,39 @@
golang.org/x/crypto v0.0.0-20181001203147-e3636079e1a4 h1:Vk3wNqEZwyGyei9yq5ekj7frek2u7HUfffJ1/opblzc=
golang.org/x/crypto v0.0.0-20181001203147-e3636079e1a4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 h1:Gv7RPwsi3eZ2Fgewe3CBsuOebPwO27PoXzRpJPsvSSM=
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392 h1:ACG4HJsFiNMf47Y4PeRoebLNy/2lXT9EtprMuTFWt1M=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20180926154720-4dfa2610cdf3 h1:dgd4x4kJt7G4k4m93AYLzM8Ni6h2qLTfh9n9vXJT3/0=
golang.org/x/net v0.0.0-20180926154720-4dfa2610cdf3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180928133829-e4b3c5e90611 h1:O33LKL7WyJgjN9CvxfTIomjIClbd/Kq86/iipowHQU0=
golang.org/x/sys v0.0.0-20180928133829-e4b3c5e90611/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd h1:DBH9mDw0zluJT/R+nGuV3jWFWLFaHyYZWD4tOT+cjn0=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe h1:6fAMxZRR6sl1Uq8U61gxU+kPTs2tR8uOySCbBP7BN/M=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425 h1:VvQyQJN0tSuecqgcIxMWnnfG5kSmgy9KZR9sW3W5QeA=
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@ -28,9 +28,7 @@ func SplitDomainName(s string) (labels []string) {
case 1: case 1:
// no-op // no-op
default: default:
end := 0 for _, end := range idx[1:] {
for i := 1; i < len(idx); i++ {
end = idx[i]
labels = append(labels, s[begin:end-1]) labels = append(labels, s[begin:end-1])
begin = end begin = end
} }
@ -85,7 +83,7 @@ func CompareDomainName(s1, s2 string) (n int) {
return return
} }
// CountLabel counts the the number of labels in the string s. // CountLabel counts the number of labels in the string s.
// s must be a syntactically valid domain name. // s must be a syntactically valid domain name.
func CountLabel(s string) (labels int) { func CountLabel(s string) (labels int) {
if s == "." { if s == "." {
@ -128,20 +126,23 @@ func Split(s string) []int {
// The bool end is true when the end of the string has been reached. // The bool end is true when the end of the string has been reached.
// Also see PrevLabel. // Also see PrevLabel.
func NextLabel(s string, offset int) (i int, end bool) { func NextLabel(s string, offset int) (i int, end bool) {
quote := false if s == "" {
return 0, true
}
for i = offset; i < len(s)-1; i++ { for i = offset; i < len(s)-1; i++ {
switch s[i] { if s[i] != '.' {
case '\\':
quote = !quote
default:
quote = false
case '.':
if quote {
quote = !quote
continue continue
} }
return i + 1, false j := i - 1
for j >= 0 && s[j] == '\\' {
j--
} }
if (j-i)%2 == 0 {
continue
}
return i + 1, false
} }
return i + 1, true return i + 1, true
} }
@ -151,17 +152,38 @@ func NextLabel(s string, offset int) (i int, end bool) {
// The bool start is true when the start of the string has been overshot. // The bool start is true when the start of the string has been overshot.
// Also see NextLabel. // Also see NextLabel.
func PrevLabel(s string, n int) (i int, start bool) { func PrevLabel(s string, n int) (i int, start bool) {
if s == "" {
return 0, true
}
if n == 0 { if n == 0 {
return len(s), false return len(s), false
} }
lab := Split(s)
if lab == nil { l := len(s) - 1
return 0, true if s[l] == '.' {
l--
} }
if n > len(lab) {
return 0, true for ; l >= 0 && n > 0; l-- {
if s[l] != '.' {
continue
} }
return lab[len(lab)-n], false j := l - 1
for j >= 0 && s[j] == '\\' {
j--
}
if (j-l)%2 == 0 {
continue
}
n--
if n == 0 {
return l + 1, false
}
}
return 0, n > 1
} }
// equal compares a and b while ignoring case. It returns true when equal otherwise false. // equal compares a and b while ignoring case. It returns true when equal otherwise false.

123
vendor/github.com/miekg/dns/msg.go generated vendored
View File

@ -11,14 +11,12 @@ package dns
//go:generate go run msg_generate.go //go:generate go run msg_generate.go
import ( import (
crand "crypto/rand" "crypto/rand"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"math/big" "math/big"
"math/rand"
"strconv" "strconv"
"strings" "strings"
"sync"
) )
const ( const (
@ -73,53 +71,23 @@ var (
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.
) )
// Id by default, returns a 16 bits random number to be used as a // Id by default returns a 16-bit random number to be used as a message id. The
// message id. The random provided should be good enough. This being a // number is drawn from a cryptographically secure random number generator.
// variable the function can be reassigned to a custom function. // This being a variable the function can be reassigned to a custom function.
// For instance, to make it return a static value: // For instance, to make it return a static value for testing:
// //
// dns.Id = func() uint16 { return 3 } // dns.Id = func() uint16 { return 3 }
var Id = id var Id = id
var (
idLock sync.Mutex
idRand *rand.Rand
)
// id returns a 16 bits random number to be used as a // id returns a 16 bits random number to be used as a
// message id. The random provided should be good enough. // message id. The random provided should be good enough.
func id() uint16 { func id() uint16 {
idLock.Lock() var output uint16
err := binary.Read(rand.Reader, binary.BigEndian, &output)
if idRand == nil { if err != nil {
// This (partially) works around panic("dns: reading random id failed: " + err.Error())
// https://github.com/golang/go/issues/11833 by only
// seeding idRand upon the first call to id.
var seed int64
var buf [8]byte
if _, err := crand.Read(buf[:]); err == nil {
seed = int64(binary.LittleEndian.Uint64(buf[:]))
} else {
seed = rand.Int63()
} }
return output
idRand = rand.New(rand.NewSource(seed))
}
// The call to idRand.Uint32 must be within the
// mutex lock because *rand.Rand is not safe for
// concurrent use.
//
// There is no added performance overhead to calling
// idRand.Uint32 inside a mutex lock over just
// calling rand.Uint32 as the global math/rand rng
// is internally protected by a sync.Mutex.
id := uint16(idRand.Uint32())
idLock.Unlock()
return id
} }
// MsgHdr is a a manually-unpacked version of (id, bits). // MsgHdr is a a manually-unpacked version of (id, bits).
@ -429,20 +397,15 @@ Loop:
if budget <= 0 { if budget <= 0 {
return "", lenmsg, ErrLongDomain return "", lenmsg, ErrLongDomain
} }
for j := off; j < off+c; j++ { for _, b := range msg[off : off+c] {
switch b := msg[j]; b { if isDomainNameLabelSpecial(b) {
case '.', '(', ')', ';', ' ', '@':
fallthrough
case '"', '\\':
s = append(s, '\\', b) s = append(s, '\\', b)
default: } else if b < ' ' || b > '~' {
if b < ' ' || b > '~' { // unprintable, use \DDD
s = append(s, escapeByte(b)...) s = append(s, escapeByte(b)...)
} else { } else {
s = append(s, b) s = append(s, b)
} }
} }
}
s = append(s, '.') s = append(s, '.')
off += c off += c
case 0xC0: case 0xC0:
@ -489,11 +452,11 @@ func packTxt(txt []string, msg []byte, offset int, tmp []byte) (int, error) {
return offset, nil return offset, nil
} }
var err error var err error
for i := range txt { for _, s := range txt {
if len(txt[i]) > len(tmp) { if len(s) > len(tmp) {
return offset, ErrBuf return offset, ErrBuf
} }
offset, err = packTxtString(txt[i], msg, offset, tmp) offset, err = packTxtString(s, msg, offset, tmp)
if err != nil { if err != nil {
return offset, err return offset, err
} }
@ -693,7 +656,6 @@ func unpackRRslice(l int, msg []byte, off int) (dst1 []RR, off1 int, err error)
} }
// If offset does not increase anymore, l is a lie // If offset does not increase anymore, l is a lie
if off1 == off { if off1 == off {
l = i
break break
} }
dst = append(dst, r) dst = append(dst, r)
@ -934,31 +896,31 @@ func (dns *Msg) String() string {
s += "ADDITIONAL: " + strconv.Itoa(len(dns.Extra)) + "\n" s += "ADDITIONAL: " + strconv.Itoa(len(dns.Extra)) + "\n"
if len(dns.Question) > 0 { if len(dns.Question) > 0 {
s += "\n;; QUESTION SECTION:\n" s += "\n;; QUESTION SECTION:\n"
for i := 0; i < len(dns.Question); i++ { for _, r := range dns.Question {
s += dns.Question[i].String() + "\n" s += r.String() + "\n"
} }
} }
if len(dns.Answer) > 0 { if len(dns.Answer) > 0 {
s += "\n;; ANSWER SECTION:\n" s += "\n;; ANSWER SECTION:\n"
for i := 0; i < len(dns.Answer); i++ { for _, r := range dns.Answer {
if dns.Answer[i] != nil { if r != nil {
s += dns.Answer[i].String() + "\n" s += r.String() + "\n"
} }
} }
} }
if len(dns.Ns) > 0 { if len(dns.Ns) > 0 {
s += "\n;; AUTHORITY SECTION:\n" s += "\n;; AUTHORITY SECTION:\n"
for i := 0; i < len(dns.Ns); i++ { for _, r := range dns.Ns {
if dns.Ns[i] != nil { if r != nil {
s += dns.Ns[i].String() + "\n" s += r.String() + "\n"
} }
} }
} }
if len(dns.Extra) > 0 { if len(dns.Extra) > 0 {
s += "\n;; ADDITIONAL SECTION:\n" s += "\n;; ADDITIONAL SECTION:\n"
for i := 0; i < len(dns.Extra); i++ { for _, r := range dns.Extra {
if dns.Extra[i] != nil { if r != nil {
s += dns.Extra[i].String() + "\n" s += r.String() + "\n"
} }
} }
} }
@ -1091,33 +1053,20 @@ func (dns *Msg) CopyTo(r1 *Msg) *Msg {
} }
rrArr := make([]RR, len(dns.Answer)+len(dns.Ns)+len(dns.Extra)) rrArr := make([]RR, len(dns.Answer)+len(dns.Ns)+len(dns.Extra))
var rri int r1.Answer, rrArr = rrArr[:0:len(dns.Answer)], rrArr[len(dns.Answer):]
r1.Ns, rrArr = rrArr[:0:len(dns.Ns)], rrArr[len(dns.Ns):]
r1.Extra = rrArr[:0:len(dns.Extra)]
if len(dns.Answer) > 0 { for _, r := range dns.Answer {
rrbegin := rri r1.Answer = append(r1.Answer, r.copy())
for i := 0; i < len(dns.Answer); i++ {
rrArr[rri] = dns.Answer[i].copy()
rri++
}
r1.Answer = rrArr[rrbegin:rri:rri]
} }
if len(dns.Ns) > 0 { for _, r := range dns.Ns {
rrbegin := rri r1.Ns = append(r1.Ns, r.copy())
for i := 0; i < len(dns.Ns); i++ {
rrArr[rri] = dns.Ns[i].copy()
rri++
}
r1.Ns = rrArr[rrbegin:rri:rri]
} }
if len(dns.Extra) > 0 { for _, r := range dns.Extra {
rrbegin := rri r1.Extra = append(r1.Extra, r.copy())
for i := 0; i < len(dns.Extra); i++ {
rrArr[rri] = dns.Extra[i].copy()
rri++
}
r1.Extra = rrArr[rrbegin:rri:rri]
} }
return r1 return r1

View File

@ -6,6 +6,7 @@ import (
"encoding/binary" "encoding/binary"
"encoding/hex" "encoding/hex"
"net" "net"
"sort"
"strings" "strings"
) )
@ -25,12 +26,13 @@ func unpackDataA(msg []byte, off int) (net.IP, int, error) {
} }
func packDataA(a net.IP, msg []byte, off int) (int, error) { func packDataA(a net.IP, msg []byte, off int) (int, error) {
switch len(a) {
case net.IPv4len, net.IPv6len:
// It must be a slice of 4, even if it is 16, we encode only the first 4 // It must be a slice of 4, even if it is 16, we encode only the first 4
if off+net.IPv4len > len(msg) { if off+net.IPv4len > len(msg) {
return len(msg), &Error{err: "overflow packing a"} return len(msg), &Error{err: "overflow packing a"}
} }
switch len(a) {
case net.IPv4len, net.IPv6len:
copy(msg[off:], a.To4()) copy(msg[off:], a.To4())
off += net.IPv4len off += net.IPv4len
case 0: case 0:
@ -51,12 +53,12 @@ func unpackDataAAAA(msg []byte, off int) (net.IP, int, error) {
} }
func packDataAAAA(aaaa net.IP, msg []byte, off int) (int, error) { func packDataAAAA(aaaa net.IP, msg []byte, off int) (int, error) {
switch len(aaaa) {
case net.IPv6len:
if off+net.IPv6len > len(msg) { if off+net.IPv6len > len(msg) {
return len(msg), &Error{err: "overflow packing aaaa"} return len(msg), &Error{err: "overflow packing aaaa"}
} }
switch len(aaaa) {
case net.IPv6len:
copy(msg[off:], aaaa) copy(msg[off:], aaaa)
off += net.IPv6len off += net.IPv6len
case 0: case 0:
@ -264,24 +266,36 @@ func unpackString(msg []byte, off int) (string, int, error) {
return "", off, &Error{err: "overflow unpacking txt"} return "", off, &Error{err: "overflow unpacking txt"}
} }
l := int(msg[off]) l := int(msg[off])
if off+l+1 > len(msg) { off++
if off+l > len(msg) {
return "", off, &Error{err: "overflow unpacking txt"} return "", off, &Error{err: "overflow unpacking txt"}
} }
var s strings.Builder var s strings.Builder
s.Grow(l) consumed := 0
for _, b := range msg[off+1 : off+1+l] { for i, b := range msg[off : off+l] {
switch { switch {
case b == '"' || b == '\\': case b == '"' || b == '\\':
if consumed == 0 {
s.Grow(l * 2)
}
s.Write(msg[off+consumed : off+i])
s.WriteByte('\\') s.WriteByte('\\')
s.WriteByte(b) s.WriteByte(b)
consumed = i + 1
case b < ' ' || b > '~': // unprintable case b < ' ' || b > '~': // unprintable
if consumed == 0 {
s.Grow(l * 2)
}
s.Write(msg[off+consumed : off+i])
s.WriteString(escapeByte(b)) s.WriteString(escapeByte(b))
default: consumed = i + 1
s.WriteByte(b)
} }
} }
off += 1 + l if consumed == 0 { // no escaping needed
return s.String(), off, nil return string(msg[off : off+l]), off + l, nil
}
s.Write(msg[off+consumed : off+l])
return s.String(), off + l, nil
} }
func packString(s string, msg []byte, off int) (int, error) { func packString(s string, msg []byte, off int) (int, error) {
@ -410,79 +424,12 @@ Option:
if off+int(optlen) > len(msg) { if off+int(optlen) > len(msg) {
return nil, len(msg), &Error{err: "overflow unpacking opt"} return nil, len(msg), &Error{err: "overflow unpacking opt"}
} }
switch code { e := makeDataOpt(code)
case EDNS0NSID:
e := new(EDNS0_NSID)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil { if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err return nil, len(msg), err
} }
edns = append(edns, e) edns = append(edns, e)
off += int(optlen) off += int(optlen)
case EDNS0SUBNET:
e := new(EDNS0_SUBNET)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
case EDNS0COOKIE:
e := new(EDNS0_COOKIE)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
case EDNS0UL:
e := new(EDNS0_UL)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
case EDNS0LLQ:
e := new(EDNS0_LLQ)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
case EDNS0DAU:
e := new(EDNS0_DAU)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
case EDNS0DHU:
e := new(EDNS0_DHU)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
case EDNS0N3U:
e := new(EDNS0_N3U)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
case EDNS0PADDING:
e := new(EDNS0_PADDING)
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
default:
e := new(EDNS0_LOCAL)
e.Code = code
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
return nil, len(msg), err
}
edns = append(edns, e)
off += int(optlen)
}
if off < len(msg) { if off < len(msg) {
goto Option goto Option
@ -491,19 +438,46 @@ Option:
return edns, off, nil return edns, off, nil
} }
func makeDataOpt(code uint16) EDNS0 {
switch code {
case EDNS0NSID:
return new(EDNS0_NSID)
case EDNS0SUBNET:
return new(EDNS0_SUBNET)
case EDNS0COOKIE:
return new(EDNS0_COOKIE)
case EDNS0EXPIRE:
return new(EDNS0_EXPIRE)
case EDNS0UL:
return new(EDNS0_UL)
case EDNS0LLQ:
return new(EDNS0_LLQ)
case EDNS0DAU:
return new(EDNS0_DAU)
case EDNS0DHU:
return new(EDNS0_DHU)
case EDNS0N3U:
return new(EDNS0_N3U)
case EDNS0PADDING:
return new(EDNS0_PADDING)
default:
e := new(EDNS0_LOCAL)
e.Code = code
return e
}
}
func packDataOpt(options []EDNS0, msg []byte, off int) (int, error) { func packDataOpt(options []EDNS0, msg []byte, off int) (int, error) {
for _, el := range options { for _, el := range options {
b, err := el.pack() b, err := el.pack()
if err != nil || off+3 > len(msg) { if err != nil || off+4 > len(msg) {
return len(msg), &Error{err: "overflow packing opt"} return len(msg), &Error{err: "overflow packing opt"}
} }
binary.BigEndian.PutUint16(msg[off:], el.Option()) // Option code binary.BigEndian.PutUint16(msg[off:], el.Option()) // Option code
binary.BigEndian.PutUint16(msg[off+2:], uint16(len(b))) // Length binary.BigEndian.PutUint16(msg[off+2:], uint16(len(b))) // Length
off += 4 off += 4
if off+len(b) > len(msg) { if off+len(b) > len(msg) {
copy(msg[off:], b) return len(msg), &Error{err: "overflow packing opt"}
off = len(msg)
continue
} }
// Actual data // Actual data
copy(msg[off:off+len(b)], b) copy(msg[off:off+len(b)], b)
@ -553,8 +527,7 @@ func unpackDataNsec(msg []byte, off int) ([]uint16, int, error) {
} }
// Walk the bytes in the window and extract the type bits // Walk the bytes in the window and extract the type bits
for j := 0; j < length; j++ { for j, b := range msg[off : off+length] {
b := msg[off+j]
// Check the bits one by one, and set the type // Check the bits one by one, and set the type
if b&0x80 == 0x80 { if b&0x80 == 0x80 {
nsec = append(nsec, uint16(window*256+j*8+0)) nsec = append(nsec, uint16(window*256+j*8+0))
@ -587,13 +560,35 @@ func unpackDataNsec(msg []byte, off int) ([]uint16, int, error) {
return nsec, off, nil return nsec, off, nil
} }
// typeBitMapLen is a helper function which computes the "maximum" length of
// a the NSEC Type BitMap field.
func typeBitMapLen(bitmap []uint16) int {
var l int
var lastwindow, lastlength uint16
for _, t := range bitmap {
window := t / 256
length := (t-window*256)/8 + 1
if window > lastwindow && lastlength != 0 { // New window, jump to the new offset
l += int(lastlength) + 2
lastlength = 0
}
if window < lastwindow || length < lastlength {
// packDataNsec would return Error{err: "nsec bits out of order"} here, but
// when computing the length, we want do be liberal.
continue
}
lastwindow, lastlength = window, length
}
l += int(lastlength) + 2
return l
}
func packDataNsec(bitmap []uint16, msg []byte, off int) (int, error) { func packDataNsec(bitmap []uint16, msg []byte, off int) (int, error) {
if len(bitmap) == 0 { if len(bitmap) == 0 {
return off, nil return off, nil
} }
var lastwindow, lastlength uint16 var lastwindow, lastlength uint16
for j := 0; j < len(bitmap); j++ { for _, t := range bitmap {
t := bitmap[j]
window := t / 256 window := t / 256
length := (t-window*256)/8 + 1 length := (t-window*256)/8 + 1
if window > lastwindow && lastlength != 0 { // New window, jump to the new offset if window > lastwindow && lastlength != 0 { // New window, jump to the new offset
@ -618,6 +613,65 @@ func packDataNsec(bitmap []uint16, msg []byte, off int) (int, error) {
return off, nil return off, nil
} }
func unpackDataSVCB(msg []byte, off int) ([]SVCBKeyValue, int, error) {
var xs []SVCBKeyValue
var code uint16
var length uint16
var err error
for off < len(msg) {
code, off, err = unpackUint16(msg, off)
if err != nil {
return nil, len(msg), &Error{err: "overflow unpacking SVCB"}
}
length, off, err = unpackUint16(msg, off)
if err != nil || off+int(length) > len(msg) {
return nil, len(msg), &Error{err: "overflow unpacking SVCB"}
}
e := makeSVCBKeyValue(SVCBKey(code))
if e == nil {
return nil, len(msg), &Error{err: "bad SVCB key"}
}
if err := e.unpack(msg[off : off+int(length)]); err != nil {
return nil, len(msg), err
}
if len(xs) > 0 && e.Key() <= xs[len(xs)-1].Key() {
return nil, len(msg), &Error{err: "SVCB keys not in strictly increasing order"}
}
xs = append(xs, e)
off += int(length)
}
return xs, off, nil
}
func packDataSVCB(pairs []SVCBKeyValue, msg []byte, off int) (int, error) {
pairs = append([]SVCBKeyValue(nil), pairs...)
sort.Slice(pairs, func(i, j int) bool {
return pairs[i].Key() < pairs[j].Key()
})
prev := svcb_RESERVED
for _, el := range pairs {
if el.Key() == prev {
return len(msg), &Error{err: "repeated SVCB keys are not allowed"}
}
prev = el.Key()
packed, err := el.pack()
if err != nil {
return len(msg), err
}
off, err = packUint16(uint16(el.Key()), msg, off)
if err != nil {
return len(msg), &Error{err: "overflow packing SVCB"}
}
off, err = packUint16(uint16(len(packed)), msg, off)
if err != nil || off+len(packed) > len(msg) {
return len(msg), &Error{err: "overflow packing SVCB"}
}
copy(msg[off:off+len(packed)], packed)
off += len(packed)
}
return off, nil
}
func unpackDataDomainNames(msg []byte, off, end int) ([]string, int, error) { func unpackDataDomainNames(msg []byte, off, end int) ([]string, int, error) {
var ( var (
servers []string servers []string
@ -639,11 +693,141 @@ func unpackDataDomainNames(msg []byte, off, end int) ([]string, int, error) {
func packDataDomainNames(names []string, msg []byte, off int, compression compressionMap, 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 _, name := range names {
off, err = packDomainName(names[j], msg, off, compression, compress) off, err = packDomainName(name, msg, off, compression, compress)
if err != nil { if err != nil {
return len(msg), err return len(msg), err
} }
} }
return off, nil return off, nil
} }
func packDataApl(data []APLPrefix, msg []byte, off int) (int, error) {
var err error
for i := range data {
off, err = packDataAplPrefix(&data[i], msg, off)
if err != nil {
return len(msg), err
}
}
return off, nil
}
func packDataAplPrefix(p *APLPrefix, msg []byte, off int) (int, error) {
if len(p.Network.IP) != len(p.Network.Mask) {
return len(msg), &Error{err: "address and mask lengths don't match"}
}
var err error
prefix, _ := p.Network.Mask.Size()
addr := p.Network.IP.Mask(p.Network.Mask)[:(prefix+7)/8]
switch len(p.Network.IP) {
case net.IPv4len:
off, err = packUint16(1, msg, off)
case net.IPv6len:
off, err = packUint16(2, msg, off)
default:
err = &Error{err: "unrecognized address family"}
}
if err != nil {
return len(msg), err
}
off, err = packUint8(uint8(prefix), msg, off)
if err != nil {
return len(msg), err
}
var n uint8
if p.Negation {
n = 0x80
}
// trim trailing zero bytes as specified in RFC3123 Sections 4.1 and 4.2.
i := len(addr) - 1
for ; i >= 0 && addr[i] == 0; i-- {
}
addr = addr[:i+1]
adflen := uint8(len(addr)) & 0x7f
off, err = packUint8(n|adflen, msg, off)
if err != nil {
return len(msg), err
}
if off+len(addr) > len(msg) {
return len(msg), &Error{err: "overflow packing APL prefix"}
}
off += copy(msg[off:], addr)
return off, nil
}
func unpackDataApl(msg []byte, off int) ([]APLPrefix, int, error) {
var result []APLPrefix
for off < len(msg) {
prefix, end, err := unpackDataAplPrefix(msg, off)
if err != nil {
return nil, len(msg), err
}
off = end
result = append(result, prefix)
}
return result, off, nil
}
func unpackDataAplPrefix(msg []byte, off int) (APLPrefix, int, error) {
family, off, err := unpackUint16(msg, off)
if err != nil {
return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL prefix"}
}
prefix, off, err := unpackUint8(msg, off)
if err != nil {
return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL prefix"}
}
nlen, off, err := unpackUint8(msg, off)
if err != nil {
return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL prefix"}
}
var ip []byte
switch family {
case 1:
ip = make([]byte, net.IPv4len)
case 2:
ip = make([]byte, net.IPv6len)
default:
return APLPrefix{}, len(msg), &Error{err: "unrecognized APL address family"}
}
if int(prefix) > 8*len(ip) {
return APLPrefix{}, len(msg), &Error{err: "APL prefix too long"}
}
afdlen := int(nlen & 0x7f)
if afdlen > len(ip) {
return APLPrefix{}, len(msg), &Error{err: "APL length too long"}
}
if off+afdlen > len(msg) {
return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL address"}
}
off += copy(ip, msg[off:off+afdlen])
if afdlen > 0 {
last := ip[afdlen-1]
if last == 0 {
return APLPrefix{}, len(msg), &Error{err: "extra APL address bits"}
}
}
ipnet := net.IPNet{
IP: ip,
Mask: net.CIDRMask(int(prefix), 8*len(ip)),
}
network := ipnet.IP.Mask(ipnet.Mask)
if !network.Equal(ipnet.IP) {
return APLPrefix{}, len(msg), &Error{err: "invalid APL address length"}
}
return APLPrefix{
Negation: (nlen & 0x80) != 0,
Network: ipnet,
}, off, nil
}

112
vendor/github.com/miekg/dns/msg_truncate.go generated vendored Normal file
View File

@ -0,0 +1,112 @@
package dns
// Truncate ensures the reply message will fit into the requested buffer
// size by removing records that exceed the requested size.
//
// It will first check if the reply fits without compression and then with
// compression. If it won't fit with compression, Truncate then walks the
// record adding as many records as possible without exceeding the
// requested buffer size.
//
// The TC bit will be set if any records were excluded from the message.
// If the TC bit is already set on the message it will be retained.
// TC indicates that the client should retry over TCP.
//
// According to RFC 2181, the TC bit should only be set if not all of the
// "required" RRs can be included in the response. Unfortunately, we have
// no way of knowing which RRs are required so we set the TC bit if any RR
// had to be omitted from the response.
//
// The appropriate buffer size can be retrieved from the requests OPT
// record, if present, and is transport specific otherwise. dns.MinMsgSize
// should be used for UDP requests without an OPT record, and
// dns.MaxMsgSize for TCP requests without an OPT record.
func (dns *Msg) Truncate(size int) {
if dns.IsTsig() != nil {
// To simplify this implementation, we don't perform
// truncation on responses with a TSIG record.
return
}
// RFC 6891 mandates that the payload size in an OPT record
// less than 512 (MinMsgSize) bytes must be treated as equal to 512 bytes.
//
// For ease of use, we impose that restriction here.
if size < MinMsgSize {
size = MinMsgSize
}
l := msgLenWithCompressionMap(dns, nil) // uncompressed length
if l <= size {
// Don't waste effort compressing this message.
dns.Compress = false
return
}
dns.Compress = true
edns0 := dns.popEdns0()
if edns0 != nil {
// Account for the OPT record that gets added at the end,
// by subtracting that length from our budget.
//
// The EDNS(0) OPT record must have the root domain and
// it's length is thus unaffected by compression.
size -= Len(edns0)
}
compression := make(map[string]struct{})
l = headerSize
for _, r := range dns.Question {
l += r.len(l, compression)
}
var numAnswer int
if l < size {
l, numAnswer = truncateLoop(dns.Answer, size, l, compression)
}
var numNS int
if l < size {
l, numNS = truncateLoop(dns.Ns, size, l, compression)
}
var numExtra int
if l < size {
_, numExtra = truncateLoop(dns.Extra, size, l, compression)
}
// See the function documentation for when we set this.
dns.Truncated = dns.Truncated || len(dns.Answer) > numAnswer ||
len(dns.Ns) > numNS || len(dns.Extra) > numExtra
dns.Answer = dns.Answer[:numAnswer]
dns.Ns = dns.Ns[:numNS]
dns.Extra = dns.Extra[:numExtra]
if edns0 != nil {
// Add the OPT record back onto the additional section.
dns.Extra = append(dns.Extra, edns0)
}
}
func truncateLoop(rrs []RR, size, l int, compression map[string]struct{}) (int, int) {
for i, r := range rrs {
if r == nil {
continue
}
l += r.len(l, compression)
if l > size {
// Return size, rather than l prior to this record,
// to prevent any further records being added.
return size, i
}
if l == size {
return l, i + 1
}
}
return l, len(rrs)
}

View File

@ -43,7 +43,7 @@ func HashName(label string, ha uint8, iter uint16, salt string) string {
return toBase32(nsec3) return toBase32(nsec3)
} }
// Cover returns true if a name is covered by the NSEC3 record // Cover returns true if a name is covered by the NSEC3 record.
func (rr *NSEC3) Cover(name string) bool { func (rr *NSEC3) Cover(name string) bool {
nameHash := HashName(name, rr.Hash, rr.Iterations, rr.Salt) nameHash := HashName(name, rr.Hash, rr.Iterations, rr.Salt)
owner := strings.ToUpper(rr.Hdr.Name) owner := strings.ToUpper(rr.Hdr.Name)

View File

@ -1,9 +1,6 @@
package dns package dns
import ( import "strings"
"fmt"
"strings"
)
// PrivateRdata is an interface used for implementing "Private Use" RR types, see // PrivateRdata is an interface used for implementing "Private Use" RR types, see
// RFC 6895. This allows one to experiment with new RR types, without requesting an // RFC 6895. This allows one to experiment with new RR types, without requesting an
@ -16,9 +13,8 @@ type PrivateRdata interface {
// Pack is used when packing a private RR into a buffer. // Pack is used when packing a private RR into a buffer.
Pack([]byte) (int, error) Pack([]byte) (int, error)
// Unpack is used when unpacking a private RR from a buffer. // Unpack is used when unpacking a private RR from a buffer.
// TODO(miek): diff. signature than Pack, see edns0.go for instance.
Unpack([]byte) (int, error) Unpack([]byte) (int, error)
// Copy copies the Rdata. // Copy copies the Rdata into the PrivateRdata argument.
Copy(PrivateRdata) error Copy(PrivateRdata) error
// Len returns the length in octets of the Rdata. // Len returns the length in octets of the Rdata.
Len() int Len() int
@ -29,22 +25,8 @@ type PrivateRdata interface {
type PrivateRR struct { type PrivateRR struct {
Hdr RR_Header Hdr RR_Header
Data PrivateRdata Data PrivateRdata
}
func mkPrivateRR(rrtype uint16) *PrivateRR { generator func() PrivateRdata // for copy
// Panics if RR is not an instance of PrivateRR.
rrfunc, ok := TypeToRR[rrtype]
if !ok {
panic(fmt.Sprintf("dns: invalid operation with Private RR type %d", rrtype))
}
anyrr := rrfunc()
rr, ok := anyrr.(*PrivateRR)
if !ok {
panic(fmt.Sprintf("dns: RR is not a PrivateRR, TypeToRR[%d] generator returned %T", rrtype, anyrr))
}
return rr
} }
// Header return the RR header of r. // Header return the RR header of r.
@ -61,13 +43,12 @@ func (r *PrivateRR) len(off int, compression map[string]struct{}) int {
func (r *PrivateRR) copy() RR { func (r *PrivateRR) copy() RR {
// make new RR like this: // make new RR like this:
rr := mkPrivateRR(r.Hdr.Rrtype) rr := &PrivateRR{r.Hdr, r.generator(), r.generator}
rr.Hdr = r.Hdr
err := r.Data.Copy(rr.Data) if err := r.Data.Copy(rr.Data); err != nil {
if err != nil { panic("dns: got value that could not be used to copy Private rdata: " + err.Error())
panic("dns: got value that could not be used to copy Private rdata")
} }
return rr return rr
} }
@ -86,7 +67,7 @@ func (r *PrivateRR) unpack(msg []byte, off int) (int, error) {
return off, err return off, err
} }
func (r *PrivateRR) parse(c *zlexer, origin, file string) *ParseError { func (r *PrivateRR) parse(c *zlexer, origin string) *ParseError {
var l lex var l lex
text := make([]string, 0, 2) // could be 0..N elements, median is probably 1 text := make([]string, 0, 2) // could be 0..N elements, median is probably 1
Fetch: Fetch:
@ -103,7 +84,7 @@ Fetch:
err := r.Data.Parse(text) err := r.Data.Parse(text)
if err != nil { if err != nil {
return &ParseError{file, err.Error(), l} return &ParseError{"", err.Error(), l}
} }
return nil return nil
@ -116,7 +97,7 @@ func (r1 *PrivateRR) isDuplicate(r2 RR) bool { return false }
func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata) { func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata) {
rtypestr = strings.ToUpper(rtypestr) rtypestr = strings.ToUpper(rtypestr)
TypeToRR[rtype] = func() RR { return &PrivateRR{RR_Header{}, generator()} } TypeToRR[rtype] = func() RR { return &PrivateRR{RR_Header{}, generator(), generator} }
TypeToString[rtype] = rtypestr TypeToString[rtype] = rtypestr
StringToType[rtypestr] = rtype StringToType[rtypestr] = rtype
} }

227
vendor/github.com/miekg/dns/scan.go generated vendored
View File

@ -87,31 +87,18 @@ type lex struct {
column int // column in the file column int // column in the file
} }
// Token holds the token that are returned when a zone file is parsed.
type Token struct {
// The scanned resource record when error is not nil.
RR
// When an error occurred, this has the error specifics.
Error *ParseError
// A potential comment positioned after the RR and on the same line.
Comment string
}
// ttlState describes the state necessary to fill in an omitted RR TTL // ttlState describes the state necessary to fill in an omitted RR TTL
type ttlState struct { type ttlState struct {
ttl uint32 // ttl is the current default TTL ttl uint32 // ttl is the current default TTL
isByDirective bool // isByDirective indicates whether ttl was set by a $TTL directive isByDirective bool // isByDirective indicates whether ttl was set by a $TTL directive
} }
// NewRR reads the RR contained in the string s. Only the first RR is // NewRR reads the RR contained in the string s. Only the first RR is returned.
// returned. If s contains no records, NewRR will return nil with no // If s contains no records, NewRR will return nil with no error.
// error.
// //
// The class defaults to IN and TTL defaults to 3600. The full zone // The class defaults to IN and TTL defaults to 3600. The full zone file syntax
// file syntax like $TTL, $ORIGIN, etc. is supported. // like $TTL, $ORIGIN, etc. is supported. All fields of the returned RR are
// // set, except RR.Header().Rdlength which is set to 0.
// All fields of the returned RR are set, except RR.Header().Rdlength
// which is set to 0.
func NewRR(s string) (RR, error) { func NewRR(s string) (RR, error) {
if len(s) > 0 && s[len(s)-1] != '\n' { // We need a closing newline if len(s) > 0 && s[len(s)-1] != '\n' { // We need a closing newline
return ReadRR(strings.NewReader(s+"\n"), "") return ReadRR(strings.NewReader(s+"\n"), "")
@ -133,69 +120,6 @@ func ReadRR(r io.Reader, file string) (RR, error) {
return rr, zp.Err() return rr, zp.Err()
} }
// ParseZone reads a RFC 1035 style zonefile from r. It returns
// *Tokens on the returned channel, each consisting of either a
// parsed RR and optional comment or a nil RR and an error. The
// channel is closed by ParseZone when the end of r is reached.
//
// The string file is used in error reporting and to resolve relative
// $INCLUDE directives. The string origin is used as the initial
// origin, as if the file would start with an $ORIGIN directive.
//
// The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are all
// supported.
//
// Basic usage pattern when reading from a string (z) containing the
// zone data:
//
// for x := range dns.ParseZone(strings.NewReader(z), "", "") {
// if x.Error != nil {
// // log.Println(x.Error)
// } else {
// // Do something with x.RR
// }
// }
//
// Comments specified after an RR (and on the same line!) are
// returned too:
//
// foo. IN A 10.0.0.1 ; this is a comment
//
// The text "; this is comment" is returned in Token.Comment.
// Comments inside the RR are returned concatenated along with the
// RR. Comments on a line by themselves are discarded.
//
// To prevent memory leaks it is important to always fully drain the
// returned channel. If an error occurs, it will always be the last
// Token sent on the channel.
//
// Deprecated: New users should prefer the ZoneParser API.
func ParseZone(r io.Reader, origin, file string) chan *Token {
t := make(chan *Token, 10000)
go parseZone(r, origin, file, t)
return t
}
func parseZone(r io.Reader, origin, file string, t chan *Token) {
defer close(t)
zp := NewZoneParser(r, origin, file)
zp.SetIncludeAllowed(true)
for rr, ok := zp.Next(); ok; rr, ok = zp.Next() {
t <- &Token{RR: rr, Comment: zp.Comment()}
}
if err := zp.Err(); err != nil {
pe, ok := err.(*ParseError)
if !ok {
pe = &ParseError{file: file, err: err.Error()}
}
t <- &Token{Error: pe}
}
}
// ZoneParser is a parser for an RFC 1035 style zonefile. // ZoneParser is a parser for an RFC 1035 style zonefile.
// //
// Each parsed RR in the zone is returned sequentially from Next. An // Each parsed RR in the zone is returned sequentially from Next. An
@ -203,6 +127,7 @@ func parseZone(r io.Reader, origin, file string, t chan *Token) {
// //
// The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are all // The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are all
// supported. Although $INCLUDE is disabled by default. // supported. Although $INCLUDE is disabled by default.
// Note that $GENERATE's range support up to a maximum of 65535 steps.
// //
// Basic usage pattern when reading from a string (z) containing the // Basic usage pattern when reading from a string (z) containing the
// zone data: // zone data:
@ -246,6 +171,7 @@ type ZoneParser struct {
includeDepth uint8 includeDepth uint8
includeAllowed bool includeAllowed bool
generateDisallowed bool
} }
// NewZoneParser returns an RFC 1035 style zonefile parser that reads // NewZoneParser returns an RFC 1035 style zonefile parser that reads
@ -503,9 +429,8 @@ func (zp *ZoneParser) Next() (RR, bool) {
return zp.setParseError("expecting $TTL value, not this...", l) return zp.setParseError("expecting $TTL value, not this...", l)
} }
if e := slurpRemainder(zp.c, zp.file); e != nil { if err := slurpRemainder(zp.c); err != nil {
zp.parseErr = e return zp.setParseError(err.err, err.lex)
return nil, false
} }
ttl, ok := stringToTTL(l.token) ttl, ok := stringToTTL(l.token)
@ -527,9 +452,8 @@ func (zp *ZoneParser) Next() (RR, bool) {
return zp.setParseError("expecting $ORIGIN value, not this...", l) return zp.setParseError("expecting $ORIGIN value, not this...", l)
} }
if e := slurpRemainder(zp.c, zp.file); e != nil { if err := slurpRemainder(zp.c); err != nil {
zp.parseErr = e return zp.setParseError(err.err, err.lex)
return nil, false
} }
name, ok := toAbsoluteName(l.token, zp.origin) name, ok := toAbsoluteName(l.token, zp.origin)
@ -547,6 +471,9 @@ func (zp *ZoneParser) Next() (RR, bool) {
st = zExpectDirGenerate st = zExpectDirGenerate
case zExpectDirGenerate: case zExpectDirGenerate:
if zp.generateDisallowed {
return zp.setParseError("nested $GENERATE directive not allowed", l)
}
if l.value != zString { if l.value != zString {
return zp.setParseError("expecting $GENERATE value, not this...", l) return zp.setParseError("expecting $GENERATE value, not this...", l)
} }
@ -650,19 +577,44 @@ func (zp *ZoneParser) Next() (RR, bool) {
st = zExpectRdata st = zExpectRdata
case zExpectRdata: case zExpectRdata:
r, e := setRR(*h, zp.c, zp.origin, zp.file) var rr RR
if e != nil { if newFn, ok := TypeToRR[h.Rrtype]; ok && canParseAsRR(h.Rrtype) {
// If e.lex is nil than we have encounter a unknown RR type rr = newFn()
// in that case we substitute our current lex token *rr.Header() = *h
if e.lex.token == "" && e.lex.value == 0 { } else {
e.lex = l // Uh, dirty rr = &RFC3597{Hdr: *h}
} }
zp.parseErr = e _, isPrivate := rr.(*PrivateRR)
return nil, false if !isPrivate && zp.c.Peek().token == "" {
// This is a dynamic update rr.
// TODO(tmthrgd): Previously slurpRemainder was only called
// for certain RR types, which may have been important.
if err := slurpRemainder(zp.c); err != nil {
return zp.setParseError(err.err, err.lex)
} }
return r, true return rr, true
} else if l.value == zNewline {
return zp.setParseError("unexpected newline", l)
}
if err := rr.parse(zp.c, zp.origin); err != nil {
// err is a concrete *ParseError without the file field set.
// The setParseError call below will construct a new
// *ParseError with file set to zp.file.
// If err.lex is nil than we have encounter an unknown RR type
// in that case we substitute our current lex token.
if err.lex == (lex{}) {
return zp.setParseError(err.err, l)
}
return zp.setParseError(err.err, err.lex)
}
return rr, true
} }
} }
@ -671,6 +623,18 @@ func (zp *ZoneParser) Next() (RR, bool) {
return nil, false return nil, false
} }
// canParseAsRR returns true if the record type can be parsed as a
// concrete RR. It blacklists certain record types that must be parsed
// according to RFC 3597 because they lack a presentation format.
func canParseAsRR(rrtype uint16) bool {
switch rrtype {
case TypeANY, TypeNULL, TypeOPT, TypeTSIG:
return false
default:
return true
}
}
type zlexer struct { type zlexer struct {
br io.ByteReader br io.ByteReader
@ -683,6 +647,7 @@ type zlexer struct {
comment string comment string
l lex l lex
cachedL *lex
brace int brace int
quote bool quote bool
@ -748,13 +713,37 @@ func (zl *zlexer) readByte() (byte, bool) {
return c, true return c, true
} }
func (zl *zlexer) Peek() lex {
if zl.nextL {
return zl.l
}
l, ok := zl.Next()
if !ok {
return l
}
if zl.nextL {
// Cache l. Next returns zl.cachedL then zl.l.
zl.cachedL = &l
} else {
// In this case l == zl.l, so we just tell Next to return zl.l.
zl.nextL = true
}
return l
}
func (zl *zlexer) Next() (lex, bool) { func (zl *zlexer) Next() (lex, bool) {
l := &zl.l l := &zl.l
if zl.nextL { switch {
case zl.cachedL != nil:
l, zl.cachedL = zl.cachedL, nil
return *l, true
case zl.nextL:
zl.nextL = false zl.nextL = false
return *l, true return *l, true
} case l.err:
if l.err {
// Parsing errors should be sticky. // Parsing errors should be sticky.
return lex{value: zEOF}, false return lex{value: zEOF}, false
} }
@ -908,6 +897,11 @@ func (zl *zlexer) Next() (lex, bool) {
// was inside braces and we delayed adding it until now. // was inside braces and we delayed adding it until now.
com[comi] = ' ' // convert newline to space com[comi] = ' ' // convert newline to space
comi++ comi++
if comi >= len(com) {
l.token = "comment length insufficient for parsing"
l.err = true
return *l, true
}
} }
com[comi] = ';' com[comi] = ';'
@ -1216,11 +1210,29 @@ func stringToCm(token string) (e, m uint8, ok bool) {
if cmeters, err = strconv.Atoi(s[1]); err != nil { if cmeters, err = strconv.Atoi(s[1]); err != nil {
return return
} }
// There's no point in having more than 2 digits in this part, and would rather make the implementation complicated ('123' should be treated as '12').
// So we simply reject it.
// We also make sure the first character is a digit to reject '+-' signs.
if len(s[1]) > 2 || s[1][0] < '0' || s[1][0] > '9' {
return
}
if len(s[1]) == 1 {
// 'nn.1' must be treated as 'nn-meters and 10cm, not 1cm.
cmeters *= 10
}
if len(s[0]) == 0 {
// This will allow omitting the 'meter' part, like .01 (meaning 0.01m = 1cm).
break
}
fallthrough fallthrough
case 1: case 1:
if meters, err = strconv.Atoi(s[0]); err != nil { if meters, err = strconv.Atoi(s[0]); err != nil {
return return
} }
// RFC1876 states the max value is 90000000.00. The latter two conditions enforce it.
if s[0][0] < '0' || s[0][0] > '9' || meters > 90000000 || (meters == 90000000 && cmeters != 0) {
return
}
case 0: case 0:
// huh? // huh?
return 0, 0, false return 0, 0, false
@ -1233,13 +1245,10 @@ func stringToCm(token string) (e, m uint8, ok bool) {
e = 0 e = 0
val = cmeters val = cmeters
} }
for val > 10 { for val >= 10 {
e++ e++
val /= 10 val /= 10
} }
if e > 9 {
ok = false
}
m = uint8(val) m = uint8(val)
return return
} }
@ -1281,6 +1290,9 @@ func appendOrigin(name, origin string) string {
// LOC record helper function // LOC record helper function
func locCheckNorth(token string, latitude uint32) (uint32, bool) { func locCheckNorth(token string, latitude uint32) (uint32, bool) {
if latitude > 90 * 1000 * 60 * 60 {
return latitude, false
}
switch token { switch token {
case "n", "N": case "n", "N":
return LOC_EQUATOR + latitude, true return LOC_EQUATOR + latitude, true
@ -1292,6 +1304,9 @@ func locCheckNorth(token string, latitude uint32) (uint32, bool) {
// LOC record helper function // LOC record helper function
func locCheckEast(token string, longitude uint32) (uint32, bool) { func locCheckEast(token string, longitude uint32) (uint32, bool) {
if longitude > 180 * 1000 * 60 * 60 {
return longitude, false
}
switch token { switch token {
case "e", "E": case "e", "E":
return LOC_EQUATOR + longitude, true return LOC_EQUATOR + longitude, true
@ -1302,18 +1317,18 @@ func locCheckEast(token string, longitude uint32) (uint32, bool) {
} }
// "Eat" the rest of the "line" // "Eat" the rest of the "line"
func slurpRemainder(c *zlexer, f string) *ParseError { func slurpRemainder(c *zlexer) *ParseError {
l, _ := c.Next() l, _ := c.Next()
switch l.value { switch l.value {
case zBlank: case zBlank:
l, _ = c.Next() l, _ = c.Next()
if l.value != zNewline && l.value != zEOF { if l.value != zNewline && l.value != zEOF {
return &ParseError{f, "garbage after rdata", l} return &ParseError{"", "garbage after rdata", l}
} }
case zNewline: case zNewline:
case zEOF: case zEOF:
default: default:
return &ParseError{f, "garbage after rdata", l} return &ParseError{"", "garbage after rdata", l}
} }
return nil return nil
} }

1143
vendor/github.com/miekg/dns/scan_rr.go generated vendored

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,6 @@
package dns package dns
import ( import (
"strings"
"sync" "sync"
) )
@ -36,33 +35,9 @@ func (mux *ServeMux) match(q string, t uint16) Handler {
return nil return nil
} }
q = CanonicalName(q)
var handler Handler 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) { for off, end := 0, false; !end; off, end = NextLabel(q, off) {
if h, ok := mux.z[q[off:]]; ok { if h, ok := mux.z[q[off:]]; ok {
if t != TypeDS { if t != TypeDS {
@ -90,7 +65,7 @@ func (mux *ServeMux) Handle(pattern string, handler Handler) {
if mux.z == nil { if mux.z == nil {
mux.z = make(map[string]Handler) mux.z = make(map[string]Handler)
} }
mux.z[Fqdn(pattern)] = handler mux.z[CanonicalName(pattern)] = handler
mux.m.Unlock() mux.m.Unlock()
} }
@ -105,7 +80,7 @@ func (mux *ServeMux) HandleRemove(pattern string) {
panic("dns: invalid pattern " + pattern) panic("dns: invalid pattern " + pattern)
} }
mux.m.Lock() mux.m.Lock()
delete(mux.z, Fqdn(pattern)) delete(mux.z, CanonicalName(pattern))
mux.m.Unlock() mux.m.Unlock()
} }
@ -116,7 +91,7 @@ func (mux *ServeMux) HandleRemove(pattern string) {
// are redirected to the parent zone (if that is also registered), // are redirected to the parent zone (if that is also registered),
// otherwise the child gets the query. // otherwise the child gets the query.
// //
// If no handler is found, or there is no question, a standard SERVFAIL // If no handler is found, or there is no question, a standard REFUSED
// message is returned // message is returned
func (mux *ServeMux) ServeDNS(w ResponseWriter, req *Msg) { func (mux *ServeMux) ServeDNS(w ResponseWriter, req *Msg) {
var h Handler var h Handler
@ -127,7 +102,7 @@ func (mux *ServeMux) ServeDNS(w ResponseWriter, req *Msg) {
if h != nil { if h != nil {
h.ServeDNS(w, req) h.ServeDNS(w, req)
} else { } else {
HandleFailed(w, req) handleRefused(w, req)
} }
} }

340
vendor/github.com/miekg/dns/server.go generated vendored
View File

@ -3,7 +3,6 @@
package dns package dns
import ( import (
"bytes"
"context" "context"
"crypto/tls" "crypto/tls"
"encoding/binary" "encoding/binary"
@ -12,26 +11,12 @@ import (
"net" "net"
"strings" "strings"
"sync" "sync"
"sync/atomic"
"time" "time"
) )
// Default 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 // aLongTimeAgo is a non-zero time, far in the past, used for
// immediate cancelation of network operations. // immediate cancelation of network operations.
var aLongTimeAgo = time.Unix(1, 0) var aLongTimeAgo = time.Unix(1, 0)
@ -81,21 +66,28 @@ type ConnectionStater interface {
} }
type response struct { type response struct {
msg []byte
closed bool // connection has been closed closed bool // connection has been closed
hijacked bool // connection has been hijacked by handler hijacked bool // connection has been hijacked by handler
tsigTimersOnly bool tsigTimersOnly bool
tsigStatus error 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.PacketConn // 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
pcSession net.Addr // address to use when writing to a generic net.PacketConn
writer Writer // writer to output the raw DNS bits writer Writer // writer to output the raw DNS bits
wg *sync.WaitGroup // for gracefull shutdown }
// handleRefused returns a HandlerFunc that returns REFUSED for every request it gets.
func handleRefused(w ResponseWriter, r *Msg) {
m := new(Msg)
m.SetRcode(r, RcodeRefused)
w.WriteMsg(m)
} }
// HandleFailed returns a HandlerFunc that returns SERVFAIL for every request it gets. // HandleFailed returns a HandlerFunc that returns SERVFAIL for every request it gets.
// Deprecated: This function is going away.
func HandleFailed(w ResponseWriter, r *Msg) { func HandleFailed(w ResponseWriter, r *Msg) {
m := new(Msg) m := new(Msg)
m.SetRcode(r, RcodeServerFailure) m.SetRcode(r, RcodeServerFailure)
@ -156,12 +148,24 @@ type Reader interface {
ReadUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error) ReadUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error)
} }
// defaultReader is an adapter for the Server struct that implements the Reader interface // PacketConnReader is an optional interface that Readers can implement to support using generic net.PacketConns.
// using the readTCP and readUDP func of the embedded Server. type PacketConnReader interface {
Reader
// ReadPacketConn reads a raw message from a generic net.PacketConn UDP connection. Implementations may
// alter connection properties, for example the read-deadline.
ReadPacketConn(conn net.PacketConn, timeout time.Duration) ([]byte, net.Addr, error)
}
// defaultReader is an adapter for the Server struct that implements the Reader and
// PacketConnReader interfaces using the readTCP, readUDP and readPacketConn funcs
// of the embedded Server.
type defaultReader struct { type defaultReader struct {
*Server *Server
} }
var _ PacketConnReader = defaultReader{}
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)
} }
@ -170,8 +174,14 @@ func (dr defaultReader) ReadUDP(conn *net.UDPConn, timeout time.Duration) ([]byt
return dr.readUDP(conn, timeout) return dr.readUDP(conn, timeout)
} }
func (dr defaultReader) ReadPacketConn(conn net.PacketConn, timeout time.Duration) ([]byte, net.Addr, error) {
return dr.readPacketConn(conn, timeout)
}
// DecorateReader is a decorator hook for extending or supplanting the functionality of a Reader. // DecorateReader is a decorator hook for extending or supplanting the functionality of a Reader.
// Implementations should never return a nil Reader. // Implementations should never return a nil Reader.
// Readers should also implement the optional PacketConnReader interface.
// PacketConnReader is required to use a generic net.PacketConn.
type DecorateReader func(Reader) Reader type DecorateReader func(Reader) Reader
// DecorateWriter is a decorator hook for extending or supplanting the functionality of a Writer. // DecorateWriter is a decorator hook for extending or supplanting the functionality of a Writer.
@ -218,11 +228,6 @@ type Server struct {
// By default DefaultMsgAcceptFunc will be used. // By default DefaultMsgAcceptFunc will be used.
MsgAcceptFunc MsgAcceptFunc 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
@ -240,51 +245,6 @@ func (srv *Server) isStarted() bool {
return started 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{} { func makeUDPBuffer(size int) func() interface{} {
return func() interface{} { return func() interface{} {
return make([]byte, size) return make([]byte, size)
@ -292,8 +252,6 @@ func makeUDPBuffer(size int) func() interface{} {
} }
func (srv *Server) init() { func (srv *Server) init() {
srv.queue = make(chan *response)
srv.shutdown = make(chan struct{}) srv.shutdown = make(chan struct{})
srv.conns = make(map[net.Conn]struct{}) srv.conns = make(map[net.Conn]struct{})
@ -301,7 +259,10 @@ func (srv *Server) init() {
srv.UDPSize = MinMsgSize srv.UDPSize = MinMsgSize
} }
if srv.MsgAcceptFunc == nil { if srv.MsgAcceptFunc == nil {
srv.MsgAcceptFunc = defaultMsgAcceptFunc srv.MsgAcceptFunc = DefaultMsgAcceptFunc
}
if srv.Handler == nil {
srv.Handler = DefaultServeMux
} }
srv.udpPool.New = makeUDPBuffer(srv.UDPSize) srv.udpPool.New = makeUDPBuffer(srv.UDPSize)
@ -328,7 +289,6 @@ func (srv *Server) ListenAndServe() error {
} }
srv.init() srv.init()
defer close(srv.queue)
switch srv.Net { switch srv.Net {
case "tcp", "tcp4", "tcp6": case "tcp", "tcp4", "tcp6":
@ -383,26 +343,23 @@ func (srv *Server) ActivateAndServe() error {
} }
srv.init() srv.init()
defer close(srv.queue)
pConn := srv.PacketConn if srv.PacketConn != nil {
l := srv.Listener
if pConn != nil {
// 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 := srv.PacketConn.(*net.UDPConn); ok && t != nil {
if e := setUDPSocketOptions(t); e != nil { if e := setUDPSocketOptions(t); e != nil {
return e return e
} }
}
srv.started = true srv.started = true
unlock() unlock()
return srv.serveUDP(t) return srv.serveUDP(srv.PacketConn)
} }
} if srv.Listener != nil {
if l != nil {
srv.started = true srv.started = true
unlock() unlock()
return srv.serveTCP(l) return srv.serveTCP(srv.Listener)
} }
return &Error{err: "bad listeners"} return &Error{err: "bad listeners"}
} }
@ -499,29 +456,31 @@ func (srv *Server) serveTCP(l net.Listener) error {
srv.conns[rw] = struct{}{} srv.conns[rw] = struct{}{}
srv.lock.Unlock() srv.lock.Unlock()
wg.Add(1) wg.Add(1)
srv.spawnWorker(&response{ go srv.serveTCPConn(&wg, rw)
tsigSecret: srv.TsigSecret,
tcp: rw,
wg: &wg,
})
} }
return nil return nil
} }
// serveUDP starts a UDP listener for the server. // serveUDP starts a UDP listener for the server.
func (srv *Server) serveUDP(l *net.UDPConn) error { func (srv *Server) serveUDP(l net.PacketConn) error {
defer l.Close() defer l.Close()
if srv.NotifyStartedFunc != nil {
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)
} }
lUDP, isUDP := l.(*net.UDPConn)
readerPC, canPacketConn := reader.(PacketConnReader)
if !isUDP && !canPacketConn {
return &Error{err: "PacketConnReader was not implemented on Reader returned from DecorateReader but is required for net.PacketConn"}
}
if srv.NotifyStartedFunc != nil {
srv.NotifyStartedFunc()
}
var wg sync.WaitGroup var wg sync.WaitGroup
defer func() { defer func() {
wg.Wait() wg.Wait()
@ -531,7 +490,17 @@ func (srv *Server) serveUDP(l *net.UDPConn) error {
rtimeout := srv.getReadTimeout() rtimeout := srv.getReadTimeout()
// deadline is not used here // deadline is not used here
for srv.isStarted() { for srv.isStarted() {
m, s, err := reader.ReadUDP(l, rtimeout) var (
m []byte
sPC net.Addr
sUDP *SessionUDP
err error
)
if isUDP {
m, sUDP, err = reader.ReadUDP(lUDP, rtimeout)
} else {
m, sPC, err = readerPC.ReadPacketConn(l, rtimeout)
}
if err != nil { if err != nil {
if !srv.isStarted() { if !srv.isStarted() {
return nil return nil
@ -548,45 +517,21 @@ func (srv *Server) serveUDP(l *net.UDPConn) error {
continue continue
} }
wg.Add(1) wg.Add(1)
srv.spawnWorker(&response{ go srv.serveUDPPacket(&wg, m, l, sUDP, sPC)
msg: m,
tsigSecret: srv.TsigSecret,
udp: l,
udpSession: s,
wg: &wg,
})
} }
return nil return nil
} }
func (srv *Server) serve(w *response) { // Serve a new TCP connection.
func (srv *Server) serveTCPConn(wg *sync.WaitGroup, rw net.Conn) {
w := &response{tsigSecret: srv.TsigSecret, tcp: rw}
if srv.DecorateWriter != nil { if srv.DecorateWriter != nil {
w.writer = srv.DecorateWriter(w) w.writer = srv.DecorateWriter(w)
} else { } else {
w.writer = w w.writer = w
} }
if w.udp != nil {
// serve UDP
srv.serveDNS(w)
w.wg.Done()
return
}
defer func() {
if !w.hijacked {
w.Close()
}
srv.lock.Lock()
delete(srv.conns, w.tcp)
srv.lock.Unlock()
w.wg.Done()
}()
reader := Reader(defaultReader{srv}) reader := Reader(defaultReader{srv})
if srv.DecorateReader != nil { if srv.DecorateReader != nil {
reader = srv.DecorateReader(reader) reader = srv.DecorateReader(reader)
@ -605,14 +550,13 @@ func (srv *Server) serve(w *response) {
} }
for q := 0; (q < limit || limit == -1) && srv.isStarted(); q++ { for q := 0; (q < limit || limit == -1) && srv.isStarted(); q++ {
var err error m, err := reader.ReadTCP(w.tcp, timeout)
w.msg, err = reader.ReadTCP(w.tcp, timeout)
if err != nil { if err != nil {
// TODO(tmthrgd): handle error // TODO(tmthrgd): handle error
break break
} }
srv.serveDNS(w) srv.serveDNS(m, w)
if w.tcp == nil { if w.closed {
break // Close() was called break // Close() was called
} }
if w.hijacked { if w.hijacked {
@ -622,17 +566,33 @@ func (srv *Server) serve(w *response) {
// idle timeout. // idle timeout.
timeout = idleTimeout timeout = idleTimeout
} }
}
func (srv *Server) disposeBuffer(w *response) { if !w.hijacked {
if w.udp != nil && cap(w.msg) == srv.UDPSize { w.Close()
srv.udpPool.Put(w.msg[:srv.UDPSize])
} }
w.msg = nil
srv.lock.Lock()
delete(srv.conns, w.tcp)
srv.lock.Unlock()
wg.Done()
} }
func (srv *Server) serveDNS(w *response) { // Serve a new UDP request.
dh, off, err := unpackMsgHdr(w.msg, 0) func (srv *Server) serveUDPPacket(wg *sync.WaitGroup, m []byte, u net.PacketConn, udpSession *SessionUDP, pcSession net.Addr) {
w := &response{tsigSecret: srv.TsigSecret, udp: u, udpSession: udpSession, pcSession: pcSession}
if srv.DecorateWriter != nil {
w.writer = srv.DecorateWriter(w)
} else {
w.writer = w
}
srv.serveDNS(m, w)
wg.Done()
}
func (srv *Server) serveDNS(m []byte, w *response) {
dh, off, err := unpackMsgHdr(m, 0)
if err != nil { if err != nil {
// Let client hang, they are sending crap; any reply can be used to amplify. // Let client hang, they are sending crap; any reply can be used to amplify.
return return
@ -641,26 +601,32 @@ func (srv *Server) serveDNS(w *response) {
req := new(Msg) req := new(Msg)
req.setHdr(dh) req.setHdr(dh)
switch srv.MsgAcceptFunc(dh) { switch action := srv.MsgAcceptFunc(dh); action {
case MsgAccept: case MsgAccept:
case MsgIgnore: if req.unpack(dh, m, off) == nil {
return break
case MsgReject: }
fallthrough
case MsgReject, MsgRejectNotImplemented:
opcode := req.Opcode
req.SetRcodeFormatError(req) req.SetRcodeFormatError(req)
req.Zero = false
if action == MsgRejectNotImplemented {
req.Opcode = opcode
req.Rcode = RcodeNotImplemented
}
// Are we allowed to delete any OPT records here? // Are we allowed to delete any OPT records here?
req.Ns, req.Answer, req.Extra = nil, nil, nil req.Ns, req.Answer, req.Extra = nil, nil, nil
w.WriteMsg(req) w.WriteMsg(req)
srv.disposeBuffer(w) fallthrough
return case MsgIgnore:
if w.udp != nil && cap(m) == srv.UDPSize {
srv.udpPool.Put(m[:srv.UDPSize])
} }
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 return
} }
@ -668,7 +634,7 @@ func (srv *Server) serveDNS(w *response) {
if w.tsigSecret != nil { if w.tsigSecret != nil {
if t := req.IsTsig(); t != nil { if t := req.IsTsig(); t != nil {
if secret, ok := w.tsigSecret[t.Hdr.Name]; ok { if secret, ok := w.tsigSecret[t.Hdr.Name]; ok {
w.tsigStatus = TsigVerify(w.msg, secret, "", false) w.tsigStatus = TsigVerify(m, secret, "", false)
} else { } else {
w.tsigStatus = ErrSecret w.tsigStatus = ErrSecret
} }
@ -677,14 +643,11 @@ func (srv *Server) serveDNS(w *response) {
} }
} }
srv.disposeBuffer(w) if w.udp != nil && cap(m) == srv.UDPSize {
srv.udpPool.Put(m[:srv.UDPSize])
handler := srv.Handler
if handler == nil {
handler = DefaultServeMux
} }
handler.ServeDNS(w, req) // Writes back to the client srv.Handler.ServeDNS(w, req) // Writes back to the client
} }
func (srv *Server) readTCP(conn net.Conn, timeout time.Duration) ([]byte, error) { func (srv *Server) readTCP(conn net.Conn, timeout time.Duration) ([]byte, error) {
@ -698,36 +661,16 @@ func (srv *Server) readTCP(conn net.Conn, timeout time.Duration) ([]byte, error)
} }
srv.lock.RUnlock() srv.lock.RUnlock()
l := make([]byte, 2) var length uint16
n, err := conn.Read(l) if err := binary.Read(conn, binary.BigEndian, &length); err != nil {
if err != nil || n != 2 {
if err != nil {
return nil, err return nil, err
} }
return nil, ErrShortRead
} m := make([]byte, length)
length := binary.BigEndian.Uint16(l) if _, err := io.ReadFull(conn, m); err != nil {
if length == 0 {
return nil, ErrShortRead
}
m := make([]byte, int(length))
n, err = conn.Read(m[:int(length)])
if err != nil || n == 0 {
if err != nil {
return nil, err return nil, err
} }
return nil, ErrShortRead
}
i := n
for i < int(length) {
j, err := conn.Read(m[i:int(length)])
if err != nil {
return nil, err
}
i += j
}
n = i
m = m[:n]
return m, nil return m, nil
} }
@ -749,6 +692,24 @@ func (srv *Server) readUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *S
return m, s, nil return m, s, nil
} }
func (srv *Server) readPacketConn(conn net.PacketConn, timeout time.Duration) ([]byte, net.Addr, error) {
srv.lock.RLock()
if srv.started {
// See the comment in readTCP above.
conn.SetReadDeadline(time.Now().Add(timeout))
}
srv.lock.RUnlock()
m := srv.udpPool.Get().([]byte)
n, addr, err := conn.ReadFrom(m)
if err != nil {
srv.udpPool.Put(m)
return nil, nil, err
}
m = m[:n]
return m, addr, nil
}
// WriteMsg implements the ResponseWriter.WriteMsg method. // 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 { if w.closed {
@ -782,20 +743,19 @@ func (w *response) Write(m []byte) (int, error) {
switch { switch {
case w.udp != nil: case w.udp != nil:
return WriteToSessionUDP(w.udp, m, w.udpSession) if u, ok := w.udp.(*net.UDPConn); ok {
case w.tcp != nil: return WriteToSessionUDP(u, m, w.udpSession)
lm := len(m)
if lm < 2 {
return 0, io.ErrShortBuffer
} }
if lm > MaxMsgSize { return w.udp.WriteTo(m, w.pcSession)
case w.tcp != nil:
if len(m) > MaxMsgSize {
return 0, &Error{err: "message too large"} return 0, &Error{err: "message too large"}
} }
l := make([]byte, 2, 2+lm)
binary.BigEndian.PutUint16(l, uint16(lm))
m = append(l, m...)
n, err := io.Copy(w.tcp, bytes.NewReader(m)) l := make([]byte, 2)
binary.BigEndian.PutUint16(l, uint16(len(m)))
n, err := (&net.Buffers{l, m}).WriteTo(w.tcp)
return int(n), err return int(n), err
default: default:
panic("dns: internal error: udp and tcp both nil") panic("dns: internal error: udp and tcp both nil")
@ -819,10 +779,12 @@ func (w *response) RemoteAddr() net.Addr {
switch { switch {
case w.udpSession != nil: case w.udpSession != nil:
return w.udpSession.RemoteAddr() return w.udpSession.RemoteAddr()
case w.pcSession != nil:
return w.pcSession
case w.tcp != nil: case w.tcp != nil:
return w.tcp.RemoteAddr() return w.tcp.RemoteAddr()
default: default:
panic("dns: internal error: udpSession and tcp both nil") panic("dns: internal error: udpSession, pcSession and tcp are all nil")
} }
} }

22
vendor/github.com/miekg/dns/sig0.go generated vendored
View File

@ -2,7 +2,6 @@ package dns
import ( import (
"crypto" "crypto"
"crypto/dsa"
"crypto/ecdsa" "crypto/ecdsa"
"crypto/rsa" "crypto/rsa"
"encoding/binary" "encoding/binary"
@ -85,7 +84,7 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
var hash crypto.Hash var hash crypto.Hash
switch rr.Algorithm { switch rr.Algorithm {
case DSA, RSASHA1: case RSASHA1:
hash = crypto.SHA1 hash = crypto.SHA1
case RSASHA256, ECDSAP256SHA256: case RSASHA256, ECDSAP256SHA256:
hash = crypto.SHA256 hash = crypto.SHA256
@ -178,19 +177,6 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
hashed := hasher.Sum(nil) hashed := hasher.Sum(nil)
sig := buf[sigend:] sig := buf[sigend:]
switch k.Algorithm { switch k.Algorithm {
case DSA:
pk := k.publicKeyDSA()
sig = sig[1:]
r := big.NewInt(0)
r.SetBytes(sig[:len(sig)/2])
s := big.NewInt(0)
s.SetBytes(sig[len(sig)/2:])
if pk != nil {
if dsa.Verify(pk, hashed, r, s) {
return nil
}
return ErrSig
}
case RSASHA1, RSASHA256, RSASHA512: case RSASHA1, RSASHA256, RSASHA512:
pk := k.publicKeyRSA() pk := k.publicKeyRSA()
if pk != nil { if pk != nil {
@ -198,10 +184,8 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
} }
case ECDSAP256SHA256, ECDSAP384SHA384: case ECDSAP256SHA256, ECDSAP384SHA384:
pk := k.publicKeyECDSA() pk := k.publicKeyECDSA()
r := big.NewInt(0) r := new(big.Int).SetBytes(sig[:len(sig)/2])
r.SetBytes(sig[:len(sig)/2]) s := new(big.Int).SetBytes(sig[len(sig)/2:])
s := big.NewInt(0)
s.SetBytes(sig[len(sig)/2:])
if pk != nil { if pk != nil {
if ecdsa.Verify(pk, hashed, r, s) { if ecdsa.Verify(pk, hashed, r, s) {
return nil return nil

744
vendor/github.com/miekg/dns/svcb.go generated vendored Normal file
View File

@ -0,0 +1,744 @@
package dns
import (
"bytes"
"encoding/binary"
"errors"
"net"
"sort"
"strconv"
"strings"
)
type SVCBKey uint16
// Keys defined in draft-ietf-dnsop-svcb-https-01 Section 12.3.2.
const (
SVCB_MANDATORY SVCBKey = 0
SVCB_ALPN SVCBKey = 1
SVCB_NO_DEFAULT_ALPN SVCBKey = 2
SVCB_PORT SVCBKey = 3
SVCB_IPV4HINT SVCBKey = 4
SVCB_ECHCONFIG SVCBKey = 5
SVCB_IPV6HINT SVCBKey = 6
svcb_RESERVED SVCBKey = 65535
)
var svcbKeyToStringMap = map[SVCBKey]string{
SVCB_MANDATORY: "mandatory",
SVCB_ALPN: "alpn",
SVCB_NO_DEFAULT_ALPN: "no-default-alpn",
SVCB_PORT: "port",
SVCB_IPV4HINT: "ipv4hint",
SVCB_ECHCONFIG: "echconfig",
SVCB_IPV6HINT: "ipv6hint",
}
var svcbStringToKeyMap = reverseSVCBKeyMap(svcbKeyToStringMap)
func reverseSVCBKeyMap(m map[SVCBKey]string) map[string]SVCBKey {
n := make(map[string]SVCBKey, len(m))
for u, s := range m {
n[s] = u
}
return n
}
// String takes the numerical code of an SVCB key and returns its name.
// Returns an empty string for reserved keys.
// Accepts unassigned keys as well as experimental/private keys.
func (key SVCBKey) String() string {
if x := svcbKeyToStringMap[key]; x != "" {
return x
}
if key == svcb_RESERVED {
return ""
}
return "key" + strconv.FormatUint(uint64(key), 10)
}
// svcbStringToKey returns the numerical code of an SVCB key.
// Returns svcb_RESERVED for reserved/invalid keys.
// Accepts unassigned keys as well as experimental/private keys.
func svcbStringToKey(s string) SVCBKey {
if strings.HasPrefix(s, "key") {
a, err := strconv.ParseUint(s[3:], 10, 16)
// no leading zeros
// key shouldn't be registered
if err != nil || a == 65535 || s[3] == '0' || svcbKeyToStringMap[SVCBKey(a)] != "" {
return svcb_RESERVED
}
return SVCBKey(a)
}
if key, ok := svcbStringToKeyMap[s]; ok {
return key
}
return svcb_RESERVED
}
func (rr *SVCB) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return &ParseError{l.token, "bad SVCB priority", l}
}
rr.Priority = uint16(i)
c.Next() // zBlank
l, _ = c.Next() // zString
rr.Target = l.token
name, nameOk := toAbsoluteName(l.token, o)
if l.err || !nameOk {
return &ParseError{l.token, "bad SVCB Target", l}
}
rr.Target = name
// Values (if any)
l, _ = c.Next()
var xs []SVCBKeyValue
// Helps require whitespace between pairs.
// Prevents key1000="a"key1001=...
canHaveNextKey := true
for l.value != zNewline && l.value != zEOF {
switch l.value {
case zString:
if !canHaveNextKey {
// The key we can now read was probably meant to be
// a part of the last value.
return &ParseError{l.token, "bad SVCB value quotation", l}
}
// In key=value pairs, value does not have to be quoted unless value
// contains whitespace. And keys don't need to have values.
// Similarly, keys with an equality signs after them don't need values.
// l.token includes at least up to the first equality sign.
idx := strings.IndexByte(l.token, '=')
var key, value string
if idx < 0 {
// Key with no value and no equality sign
key = l.token
} else if idx == 0 {
return &ParseError{l.token, "bad SVCB key", l}
} else {
key, value = l.token[:idx], l.token[idx+1:]
if value == "" {
// We have a key and an equality sign. Maybe we have nothing
// after "=" or we have a double quote.
l, _ = c.Next()
if l.value == zQuote {
// Only needed when value ends with double quotes.
// Any value starting with zQuote ends with it.
canHaveNextKey = false
l, _ = c.Next()
switch l.value {
case zString:
// We have a value in double quotes.
value = l.token
l, _ = c.Next()
if l.value != zQuote {
return &ParseError{l.token, "SVCB unterminated value", l}
}
case zQuote:
// There's nothing in double quotes.
default:
return &ParseError{l.token, "bad SVCB value", l}
}
}
}
}
kv := makeSVCBKeyValue(svcbStringToKey(key))
if kv == nil {
return &ParseError{l.token, "bad SVCB key", l}
}
if err := kv.parse(value); err != nil {
return &ParseError{l.token, err.Error(), l}
}
xs = append(xs, kv)
case zQuote:
return &ParseError{l.token, "SVCB key can't contain double quotes", l}
case zBlank:
canHaveNextKey = true
default:
return &ParseError{l.token, "bad SVCB values", l}
}
l, _ = c.Next()
}
rr.Value = xs
if rr.Priority == 0 && len(xs) > 0 {
return &ParseError{l.token, "SVCB aliasform can't have values", l}
}
return nil
}
// makeSVCBKeyValue returns an SVCBKeyValue struct with the key or nil for reserved keys.
func makeSVCBKeyValue(key SVCBKey) SVCBKeyValue {
switch key {
case SVCB_MANDATORY:
return new(SVCBMandatory)
case SVCB_ALPN:
return new(SVCBAlpn)
case SVCB_NO_DEFAULT_ALPN:
return new(SVCBNoDefaultAlpn)
case SVCB_PORT:
return new(SVCBPort)
case SVCB_IPV4HINT:
return new(SVCBIPv4Hint)
case SVCB_ECHCONFIG:
return new(SVCBECHConfig)
case SVCB_IPV6HINT:
return new(SVCBIPv6Hint)
case svcb_RESERVED:
return nil
default:
e := new(SVCBLocal)
e.KeyCode = key
return e
}
}
// SVCB RR. See RFC xxxx (https://tools.ietf.org/html/draft-ietf-dnsop-svcb-https-01).
type SVCB struct {
Hdr RR_Header
Priority uint16
Target string `dns:"domain-name"`
Value []SVCBKeyValue `dns:"pairs"` // Value must be empty if Priority is non-zero.
}
// HTTPS RR. Everything valid for SVCB applies to HTTPS as well.
// Except that the HTTPS record is intended for use with the HTTP and HTTPS protocols.
type HTTPS struct {
SVCB
}
func (rr *HTTPS) String() string {
return rr.SVCB.String()
}
func (rr *HTTPS) parse(c *zlexer, o string) *ParseError {
return rr.SVCB.parse(c, o)
}
// SVCBKeyValue defines a key=value pair for the SVCB RR type.
// An SVCB RR can have multiple SVCBKeyValues appended to it.
type SVCBKeyValue interface {
Key() SVCBKey // Key returns the numerical key code.
pack() ([]byte, error) // pack returns the encoded value.
unpack([]byte) error // unpack sets the value.
String() string // String returns the string representation of the value.
parse(string) error // parse sets the value to the given string representation of the value.
copy() SVCBKeyValue // copy returns a deep-copy of the pair.
len() int // len returns the length of value in the wire format.
}
// SVCBMandatory pair adds to required keys that must be interpreted for the RR
// to be functional.
// Basic use pattern for creating a mandatory option:
//
// s := &dns.SVCB{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeSVCB, Class: dns.ClassINET}}
// e := new(dns.SVCBMandatory)
// e.Code = []uint16{65403}
// s.Value = append(s.Value, e)
type SVCBMandatory struct {
Code []SVCBKey // Must not include mandatory
}
func (*SVCBMandatory) Key() SVCBKey { return SVCB_MANDATORY }
func (s *SVCBMandatory) String() string {
str := make([]string, len(s.Code))
for i, e := range s.Code {
str[i] = e.String()
}
return strings.Join(str, ",")
}
func (s *SVCBMandatory) pack() ([]byte, error) {
codes := append([]SVCBKey(nil), s.Code...)
sort.Slice(codes, func(i, j int) bool {
return codes[i] < codes[j]
})
b := make([]byte, 2*len(codes))
for i, e := range codes {
binary.BigEndian.PutUint16(b[2*i:], uint16(e))
}
return b, nil
}
func (s *SVCBMandatory) unpack(b []byte) error {
if len(b)%2 != 0 {
return errors.New("dns: svcbmandatory: value length is not a multiple of 2")
}
codes := make([]SVCBKey, 0, len(b)/2)
for i := 0; i < len(b); i += 2 {
// We assume strictly increasing order.
codes = append(codes, SVCBKey(binary.BigEndian.Uint16(b[i:])))
}
s.Code = codes
return nil
}
func (s *SVCBMandatory) parse(b string) error {
str := strings.Split(b, ",")
codes := make([]SVCBKey, 0, len(str))
for _, e := range str {
codes = append(codes, svcbStringToKey(e))
}
s.Code = codes
return nil
}
func (s *SVCBMandatory) len() int {
return 2 * len(s.Code)
}
func (s *SVCBMandatory) copy() SVCBKeyValue {
return &SVCBMandatory{
append([]SVCBKey(nil), s.Code...),
}
}
// SVCBAlpn pair is used to list supported connection protocols.
// Protocol ids can be found at:
// https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids
// Basic use pattern for creating an alpn option:
//
// h := new(dns.HTTPS)
// h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}
// e := new(dns.SVCBAlpn)
// e.Alpn = []string{"h2", "http/1.1"}
// h.Value = append(o.Value, e)
type SVCBAlpn struct {
Alpn []string
}
func (*SVCBAlpn) Key() SVCBKey { return SVCB_ALPN }
func (s *SVCBAlpn) String() string { return strings.Join(s.Alpn, ",") }
func (s *SVCBAlpn) pack() ([]byte, error) {
// Liberally estimate the size of an alpn as 10 octets
b := make([]byte, 0, 10*len(s.Alpn))
for _, e := range s.Alpn {
if len(e) == 0 {
return nil, errors.New("dns: svcbalpn: empty alpn-id")
}
if len(e) > 255 {
return nil, errors.New("dns: svcbalpn: alpn-id too long")
}
b = append(b, byte(len(e)))
b = append(b, e...)
}
return b, nil
}
func (s *SVCBAlpn) unpack(b []byte) error {
// Estimate the size of the smallest alpn as 4 bytes
alpn := make([]string, 0, len(b)/4)
for i := 0; i < len(b); {
length := int(b[i])
i++
if i+length > len(b) {
return errors.New("dns: svcbalpn: alpn array overflowing")
}
alpn = append(alpn, string(b[i:i+length]))
i += length
}
s.Alpn = alpn
return nil
}
func (s *SVCBAlpn) parse(b string) error {
s.Alpn = strings.Split(b, ",")
return nil
}
func (s *SVCBAlpn) len() int {
var l int
for _, e := range s.Alpn {
l += 1 + len(e)
}
return l
}
func (s *SVCBAlpn) copy() SVCBKeyValue {
return &SVCBAlpn{
append([]string(nil), s.Alpn...),
}
}
// SVCBNoDefaultAlpn pair signifies no support for default connection protocols.
// Basic use pattern for creating a no-default-alpn option:
//
// s := &dns.SVCB{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeSVCB, Class: dns.ClassINET}}
// e := new(dns.SVCBNoDefaultAlpn)
// s.Value = append(s.Value, e)
type SVCBNoDefaultAlpn struct{}
func (*SVCBNoDefaultAlpn) Key() SVCBKey { return SVCB_NO_DEFAULT_ALPN }
func (*SVCBNoDefaultAlpn) copy() SVCBKeyValue { return &SVCBNoDefaultAlpn{} }
func (*SVCBNoDefaultAlpn) pack() ([]byte, error) { return []byte{}, nil }
func (*SVCBNoDefaultAlpn) String() string { return "" }
func (*SVCBNoDefaultAlpn) len() int { return 0 }
func (*SVCBNoDefaultAlpn) unpack(b []byte) error {
if len(b) != 0 {
return errors.New("dns: svcbnodefaultalpn: no_default_alpn must have no value")
}
return nil
}
func (*SVCBNoDefaultAlpn) parse(b string) error {
if len(b) != 0 {
return errors.New("dns: svcbnodefaultalpn: no_default_alpn must have no value")
}
return nil
}
// SVCBPort pair defines the port for connection.
// Basic use pattern for creating a port option:
//
// s := &dns.SVCB{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeSVCB, Class: dns.ClassINET}}
// e := new(dns.SVCBPort)
// e.Port = 80
// s.Value = append(s.Value, e)
type SVCBPort struct {
Port uint16
}
func (*SVCBPort) Key() SVCBKey { return SVCB_PORT }
func (*SVCBPort) len() int { return 2 }
func (s *SVCBPort) String() string { return strconv.FormatUint(uint64(s.Port), 10) }
func (s *SVCBPort) copy() SVCBKeyValue { return &SVCBPort{s.Port} }
func (s *SVCBPort) unpack(b []byte) error {
if len(b) != 2 {
return errors.New("dns: svcbport: port length is not exactly 2 octets")
}
s.Port = binary.BigEndian.Uint16(b)
return nil
}
func (s *SVCBPort) pack() ([]byte, error) {
b := make([]byte, 2)
binary.BigEndian.PutUint16(b, s.Port)
return b, nil
}
func (s *SVCBPort) parse(b string) error {
port, err := strconv.ParseUint(b, 10, 16)
if err != nil {
return errors.New("dns: svcbport: port out of range")
}
s.Port = uint16(port)
return nil
}
// SVCBIPv4Hint pair suggests an IPv4 address which may be used to open connections
// if A and AAAA record responses for SVCB's Target domain haven't been received.
// In that case, optionally, A and AAAA requests can be made, after which the connection
// to the hinted IP address may be terminated and a new connection may be opened.
// Basic use pattern for creating an ipv4hint option:
//
// h := new(dns.HTTPS)
// h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}
// e := new(dns.SVCBIPv4Hint)
// e.Hint = []net.IP{net.IPv4(1,1,1,1).To4()}
//
// Or
//
// e.Hint = []net.IP{net.ParseIP("1.1.1.1").To4()}
// h.Value = append(h.Value, e)
type SVCBIPv4Hint struct {
Hint []net.IP
}
func (*SVCBIPv4Hint) Key() SVCBKey { return SVCB_IPV4HINT }
func (s *SVCBIPv4Hint) len() int { return 4 * len(s.Hint) }
func (s *SVCBIPv4Hint) pack() ([]byte, error) {
b := make([]byte, 0, 4*len(s.Hint))
for _, e := range s.Hint {
x := e.To4()
if x == nil {
return nil, errors.New("dns: svcbipv4hint: expected ipv4, hint is ipv6")
}
b = append(b, x...)
}
return b, nil
}
func (s *SVCBIPv4Hint) unpack(b []byte) error {
if len(b) == 0 || len(b)%4 != 0 {
return errors.New("dns: svcbipv4hint: ipv4 address byte array length is not a multiple of 4")
}
x := make([]net.IP, 0, len(b)/4)
for i := 0; i < len(b); i += 4 {
x = append(x, net.IP(b[i:i+4]))
}
s.Hint = x
return nil
}
func (s *SVCBIPv4Hint) String() string {
str := make([]string, len(s.Hint))
for i, e := range s.Hint {
x := e.To4()
if x == nil {
return "<nil>"
}
str[i] = x.String()
}
return strings.Join(str, ",")
}
func (s *SVCBIPv4Hint) parse(b string) error {
if strings.Contains(b, ":") {
return errors.New("dns: svcbipv4hint: expected ipv4, got ipv6")
}
str := strings.Split(b, ",")
dst := make([]net.IP, len(str))
for i, e := range str {
ip := net.ParseIP(e).To4()
if ip == nil {
return errors.New("dns: svcbipv4hint: bad ip")
}
dst[i] = ip
}
s.Hint = dst
return nil
}
func (s *SVCBIPv4Hint) copy() SVCBKeyValue {
return &SVCBIPv4Hint{
append([]net.IP(nil), s.Hint...),
}
}
// SVCBECHConfig pair contains the ECHConfig structure defined in draft-ietf-tls-esni [RFC xxxx].
// Basic use pattern for creating an echconfig option:
//
// h := new(dns.HTTPS)
// h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}
// e := new(dns.SVCBECHConfig)
// e.ECH = []byte{0xfe, 0x08, ...}
// h.Value = append(h.Value, e)
type SVCBECHConfig struct {
ECH []byte
}
func (*SVCBECHConfig) Key() SVCBKey { return SVCB_ECHCONFIG }
func (s *SVCBECHConfig) String() string { return toBase64(s.ECH) }
func (s *SVCBECHConfig) len() int { return len(s.ECH) }
func (s *SVCBECHConfig) pack() ([]byte, error) {
return append([]byte(nil), s.ECH...), nil
}
func (s *SVCBECHConfig) copy() SVCBKeyValue {
return &SVCBECHConfig{
append([]byte(nil), s.ECH...),
}
}
func (s *SVCBECHConfig) unpack(b []byte) error {
s.ECH = append([]byte(nil), b...)
return nil
}
func (s *SVCBECHConfig) parse(b string) error {
x, err := fromBase64([]byte(b))
if err != nil {
return errors.New("dns: svcbechconfig: bad base64 echconfig")
}
s.ECH = x
return nil
}
// SVCBIPv6Hint pair suggests an IPv6 address which may be used to open connections
// if A and AAAA record responses for SVCB's Target domain haven't been received.
// In that case, optionally, A and AAAA requests can be made, after which the
// connection to the hinted IP address may be terminated and a new connection may be opened.
// Basic use pattern for creating an ipv6hint option:
//
// h := new(dns.HTTPS)
// h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}
// e := new(dns.SVCBIPv6Hint)
// e.Hint = []net.IP{net.ParseIP("2001:db8::1")}
// h.Value = append(h.Value, e)
type SVCBIPv6Hint struct {
Hint []net.IP
}
func (*SVCBIPv6Hint) Key() SVCBKey { return SVCB_IPV6HINT }
func (s *SVCBIPv6Hint) len() int { return 16 * len(s.Hint) }
func (s *SVCBIPv6Hint) pack() ([]byte, error) {
b := make([]byte, 0, 16*len(s.Hint))
for _, e := range s.Hint {
if len(e) != net.IPv6len || e.To4() != nil {
return nil, errors.New("dns: svcbipv6hint: expected ipv6, hint is ipv4")
}
b = append(b, e...)
}
return b, nil
}
func (s *SVCBIPv6Hint) unpack(b []byte) error {
if len(b) == 0 || len(b)%16 != 0 {
return errors.New("dns: svcbipv6hint: ipv6 address byte array length not a multiple of 16")
}
x := make([]net.IP, 0, len(b)/16)
for i := 0; i < len(b); i += 16 {
ip := net.IP(b[i : i+16])
if ip.To4() != nil {
return errors.New("dns: svcbipv6hint: expected ipv6, got ipv4")
}
x = append(x, ip)
}
s.Hint = x
return nil
}
func (s *SVCBIPv6Hint) String() string {
str := make([]string, len(s.Hint))
for i, e := range s.Hint {
if x := e.To4(); x != nil {
return "<nil>"
}
str[i] = e.String()
}
return strings.Join(str, ",")
}
func (s *SVCBIPv6Hint) parse(b string) error {
if strings.Contains(b, ".") {
return errors.New("dns: svcbipv6hint: expected ipv6, got ipv4")
}
str := strings.Split(b, ",")
dst := make([]net.IP, len(str))
for i, e := range str {
ip := net.ParseIP(e)
if ip == nil {
return errors.New("dns: svcbipv6hint: bad ip")
}
dst[i] = ip
}
s.Hint = dst
return nil
}
func (s *SVCBIPv6Hint) copy() SVCBKeyValue {
return &SVCBIPv6Hint{
append([]net.IP(nil), s.Hint...),
}
}
// SVCBLocal pair is intended for experimental/private use. The key is recommended
// to be in the range [SVCB_PRIVATE_LOWER, SVCB_PRIVATE_UPPER].
// Basic use pattern for creating a keyNNNNN option:
//
// h := new(dns.HTTPS)
// h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET}
// e := new(dns.SVCBLocal)
// e.KeyCode = 65400
// e.Data = []byte("abc")
// h.Value = append(h.Value, e)
type SVCBLocal struct {
KeyCode SVCBKey // Never 65535 or any assigned keys.
Data []byte // All byte sequences are allowed.
}
func (s *SVCBLocal) Key() SVCBKey { return s.KeyCode }
func (s *SVCBLocal) pack() ([]byte, error) { return append([]byte(nil), s.Data...), nil }
func (s *SVCBLocal) len() int { return len(s.Data) }
func (s *SVCBLocal) unpack(b []byte) error {
s.Data = append([]byte(nil), b...)
return nil
}
func (s *SVCBLocal) String() string {
var str strings.Builder
str.Grow(4 * len(s.Data))
for _, e := range s.Data {
if ' ' <= e && e <= '~' {
switch e {
case '"', ';', ' ', '\\':
str.WriteByte('\\')
str.WriteByte(e)
default:
str.WriteByte(e)
}
} else {
str.WriteString(escapeByte(e))
}
}
return str.String()
}
func (s *SVCBLocal) parse(b string) error {
data := make([]byte, 0, len(b))
for i := 0; i < len(b); {
if b[i] != '\\' {
data = append(data, b[i])
i++
continue
}
if i+1 == len(b) {
return errors.New("dns: svcblocal: svcb private/experimental key escape unterminated")
}
if isDigit(b[i+1]) {
if i+3 < len(b) && isDigit(b[i+2]) && isDigit(b[i+3]) {
a, err := strconv.ParseUint(b[i+1:i+4], 10, 8)
if err == nil {
i += 4
data = append(data, byte(a))
continue
}
}
return errors.New("dns: svcblocal: svcb private/experimental key bad escaped octet")
} else {
data = append(data, b[i+1])
i += 2
}
}
s.Data = data
return nil
}
func (s *SVCBLocal) copy() SVCBKeyValue {
return &SVCBLocal{s.KeyCode,
append([]byte(nil), s.Data...),
}
}
func (rr *SVCB) String() string {
s := rr.Hdr.String() +
strconv.Itoa(int(rr.Priority)) + " " +
sprintName(rr.Target)
for _, e := range rr.Value {
s += " " + e.Key().String() + "=\"" + e.String() + "\""
}
return s
}
// areSVCBPairArraysEqual checks if SVCBKeyValue arrays are equal after sorting their
// copies. arrA and arrB have equal lengths, otherwise zduplicate.go wouldn't call this function.
func areSVCBPairArraysEqual(a []SVCBKeyValue, b []SVCBKeyValue) bool {
a = append([]SVCBKeyValue(nil), a...)
b = append([]SVCBKeyValue(nil), b...)
sort.Slice(a, func(i, j int) bool { return a[i].Key() < a[j].Key() })
sort.Slice(b, func(i, j int) bool { return b[i].Key() < b[j].Key() })
for i, e := range a {
if e.Key() != b[i].Key() {
return false
}
b1, err1 := e.pack()
b2, err2 := b[i].pack()
if err1 != nil || err2 != nil || !bytes.Equal(b1, b2) {
return false
}
}
return true
}

94
vendor/github.com/miekg/dns/tsig.go generated vendored
View File

@ -2,7 +2,6 @@ package dns
import ( import (
"crypto/hmac" "crypto/hmac"
"crypto/md5"
"crypto/sha1" "crypto/sha1"
"crypto/sha256" "crypto/sha256"
"crypto/sha512" "crypto/sha512"
@ -16,10 +15,13 @@ import (
// HMAC hashing codes. These are transmitted as domain names. // HMAC hashing codes. These are transmitted as domain names.
const ( const (
HmacMD5 = "hmac-md5.sig-alg.reg.int."
HmacSHA1 = "hmac-sha1." HmacSHA1 = "hmac-sha1."
HmacSHA224 = "hmac-sha224."
HmacSHA256 = "hmac-sha256." HmacSHA256 = "hmac-sha256."
HmacSHA384 = "hmac-sha384."
HmacSHA512 = "hmac-sha512." HmacSHA512 = "hmac-sha512."
HmacMD5 = "hmac-md5.sig-alg.reg.int." // Deprecated: HmacMD5 is no longer supported.
) )
// TSIG is the RR the holds the transaction signature of a message. // TSIG is the RR the holds the transaction signature of a message.
@ -40,7 +42,7 @@ type TSIG struct {
// TSIG has no official presentation format, but this will suffice. // TSIG has no official presentation format, but this will suffice.
func (rr *TSIG) String() string { func (rr *TSIG) String() string {
s := "\n;; TSIG PSEUDOSECTION:\n" s := "\n;; TSIG PSEUDOSECTION:\n; " // add another semi-colon to signify TSIG does not have a presentation format
s += rr.Hdr.String() + s += rr.Hdr.String() +
" " + rr.Algorithm + " " + rr.Algorithm +
" " + tsigTimeToString(rr.TimeSigned) + " " + tsigTimeToString(rr.TimeSigned) +
@ -54,7 +56,7 @@ func (rr *TSIG) String() string {
return s return s
} }
func (rr *TSIG) parse(c *zlexer, origin, file string) *ParseError { func (rr *TSIG) parse(c *zlexer, origin string) *ParseError {
panic("dns: internal error: parse should never be called on TSIG") panic("dns: internal error: parse should never be called on TSIG")
} }
@ -111,32 +113,33 @@ func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, s
if err != nil { if err != nil {
return nil, "", err return nil, "", err
} }
buf := tsigBuffer(mbuf, rr, requestMAC, timersOnly) buf, err := tsigBuffer(mbuf, rr, requestMAC, timersOnly)
if err != nil {
return nil, "", err
}
t := new(TSIG) t := new(TSIG)
var h hash.Hash var h hash.Hash
switch strings.ToLower(rr.Algorithm) { switch CanonicalName(rr.Algorithm) {
case HmacMD5:
h = hmac.New(md5.New, rawsecret)
case HmacSHA1: case HmacSHA1:
h = hmac.New(sha1.New, rawsecret) h = hmac.New(sha1.New, rawsecret)
case HmacSHA224:
h = hmac.New(sha256.New224, rawsecret)
case HmacSHA256: case HmacSHA256:
h = hmac.New(sha256.New, rawsecret) h = hmac.New(sha256.New, rawsecret)
case HmacSHA384:
h = hmac.New(sha512.New384, rawsecret)
case HmacSHA512: case HmacSHA512:
h = hmac.New(sha512.New, rawsecret) h = hmac.New(sha512.New, rawsecret)
default: default:
return nil, "", ErrKeyAlg return nil, "", ErrKeyAlg
} }
h.Write(buf) h.Write(buf)
// Copy all TSIG fields except MAC and its size, which are filled using the computed digest.
*t = *rr
t.MAC = hex.EncodeToString(h.Sum(nil)) t.MAC = hex.EncodeToString(h.Sum(nil))
t.MACSize = uint16(len(t.MAC) / 2) // Size is half! t.MACSize = uint16(len(t.MAC) / 2) // Size is half!
t.Hdr = RR_Header{Name: rr.Hdr.Name, Rrtype: TypeTSIG, Class: ClassANY, Ttl: 0}
t.Fudge = rr.Fudge
t.TimeSigned = rr.TimeSigned
t.Algorithm = rr.Algorithm
t.OrigId = m.Id
tbuf := make([]byte, Len(t)) tbuf := make([]byte, Len(t))
off, err := PackRR(t, tbuf, 0, nil, false) off, err := PackRR(t, tbuf, 0, nil, false)
if err != nil { if err != nil {
@ -153,6 +156,11 @@ func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, s
// If the signature does not validate err contains the // If the signature does not validate err contains the
// error, otherwise it is nil. // error, otherwise it is nil.
func TsigVerify(msg []byte, secret, requestMAC string, timersOnly bool) error { func TsigVerify(msg []byte, secret, requestMAC string, timersOnly bool) error {
return tsigVerify(msg, secret, requestMAC, timersOnly, uint64(time.Now().Unix()))
}
// actual implementation of TsigVerify, taking the current time ('now') as a parameter for the convenience of tests.
func tsigVerify(msg []byte, secret, requestMAC string, timersOnly bool, now uint64) error {
rawsecret, err := fromBase64([]byte(secret)) rawsecret, err := fromBase64([]byte(secret))
if err != nil { if err != nil {
return err return err
@ -168,27 +176,21 @@ func TsigVerify(msg []byte, secret, requestMAC string, timersOnly bool) error {
return err return err
} }
buf := tsigBuffer(stripped, tsig, requestMAC, timersOnly) buf, err := tsigBuffer(stripped, tsig, requestMAC, timersOnly)
if err != nil {
// Fudge factor works both ways. A message can arrive before it was signed because return err
// of clock skew.
now := uint64(time.Now().Unix())
ti := now - tsig.TimeSigned
if now < tsig.TimeSigned {
ti = tsig.TimeSigned - now
}
if uint64(tsig.Fudge) < ti {
return ErrTime
} }
var h hash.Hash var h hash.Hash
switch strings.ToLower(tsig.Algorithm) { switch CanonicalName(tsig.Algorithm) {
case HmacMD5:
h = hmac.New(md5.New, rawsecret)
case HmacSHA1: case HmacSHA1:
h = hmac.New(sha1.New, rawsecret) h = hmac.New(sha1.New, rawsecret)
case HmacSHA224:
h = hmac.New(sha256.New224, rawsecret)
case HmacSHA256: case HmacSHA256:
h = hmac.New(sha256.New, rawsecret) h = hmac.New(sha256.New, rawsecret)
case HmacSHA384:
h = hmac.New(sha512.New384, rawsecret)
case HmacSHA512: case HmacSHA512:
h = hmac.New(sha512.New, rawsecret) h = hmac.New(sha512.New, rawsecret)
default: default:
@ -198,11 +200,24 @@ func TsigVerify(msg []byte, secret, requestMAC string, timersOnly bool) error {
if !hmac.Equal(h.Sum(nil), msgMAC) { if !hmac.Equal(h.Sum(nil), msgMAC) {
return ErrSig return ErrSig
} }
// Fudge factor works both ways. A message can arrive before it was signed because
// of clock skew.
// We check this after verifying the signature, following draft-ietf-dnsop-rfc2845bis
// instead of RFC2845, in order to prevent a security vulnerability as reported in CVE-2017-3142/3143.
ti := now - tsig.TimeSigned
if now < tsig.TimeSigned {
ti = tsig.TimeSigned - now
}
if uint64(tsig.Fudge) < ti {
return ErrTime
}
return nil return nil
} }
// Create a wiredata buffer for the MAC calculation. // Create a wiredata buffer for the MAC calculation.
func tsigBuffer(msgbuf []byte, rr *TSIG, requestMAC string, timersOnly bool) []byte { func tsigBuffer(msgbuf []byte, rr *TSIG, requestMAC string, timersOnly bool) ([]byte, error) {
var buf []byte var buf []byte
if rr.TimeSigned == 0 { if rr.TimeSigned == 0 {
rr.TimeSigned = uint64(time.Now().Unix()) rr.TimeSigned = uint64(time.Now().Unix())
@ -219,7 +234,10 @@ func tsigBuffer(msgbuf []byte, rr *TSIG, requestMAC string, timersOnly bool) []b
m.MACSize = uint16(len(requestMAC) / 2) m.MACSize = uint16(len(requestMAC) / 2)
m.MAC = requestMAC m.MAC = requestMAC
buf = make([]byte, len(requestMAC)) // long enough buf = make([]byte, len(requestMAC)) // long enough
n, _ := packMacWire(m, buf) n, err := packMacWire(m, buf)
if err != nil {
return nil, err
}
buf = buf[:n] buf = buf[:n]
} }
@ -228,20 +246,26 @@ func tsigBuffer(msgbuf []byte, rr *TSIG, requestMAC string, timersOnly bool) []b
tsig := new(timerWireFmt) tsig := new(timerWireFmt)
tsig.TimeSigned = rr.TimeSigned tsig.TimeSigned = rr.TimeSigned
tsig.Fudge = rr.Fudge tsig.Fudge = rr.Fudge
n, _ := packTimerWire(tsig, tsigvar) n, err := packTimerWire(tsig, tsigvar)
if err != nil {
return nil, err
}
tsigvar = tsigvar[:n] tsigvar = tsigvar[:n]
} else { } else {
tsig := new(tsigWireFmt) tsig := new(tsigWireFmt)
tsig.Name = strings.ToLower(rr.Hdr.Name) tsig.Name = CanonicalName(rr.Hdr.Name)
tsig.Class = ClassANY tsig.Class = ClassANY
tsig.Ttl = rr.Hdr.Ttl tsig.Ttl = rr.Hdr.Ttl
tsig.Algorithm = strings.ToLower(rr.Algorithm) tsig.Algorithm = CanonicalName(rr.Algorithm)
tsig.TimeSigned = rr.TimeSigned tsig.TimeSigned = rr.TimeSigned
tsig.Fudge = rr.Fudge tsig.Fudge = rr.Fudge
tsig.Error = rr.Error tsig.Error = rr.Error
tsig.OtherLen = rr.OtherLen tsig.OtherLen = rr.OtherLen
tsig.OtherData = rr.OtherData tsig.OtherData = rr.OtherData
n, _ := packTsigWire(tsig, tsigvar) n, err := packTsigWire(tsig, tsigvar)
if err != nil {
return nil, err
}
tsigvar = tsigvar[:n] tsigvar = tsigvar[:n]
} }
@ -251,7 +275,7 @@ func tsigBuffer(msgbuf []byte, rr *TSIG, requestMAC string, timersOnly bool) []b
} else { } else {
buf = append(msgbuf, tsigvar...) buf = append(msgbuf, tsigvar...)
} }
return buf return buf, nil
} }
// Strip the TSIG from the raw message. // Strip the TSIG from the raw message.

237
vendor/github.com/miekg/dns/types.go generated vendored
View File

@ -1,6 +1,7 @@
package dns package dns
import ( import (
"bytes"
"fmt" "fmt"
"net" "net"
"strconv" "strconv"
@ -61,6 +62,7 @@ const (
TypeCERT uint16 = 37 TypeCERT uint16 = 37
TypeDNAME uint16 = 39 TypeDNAME uint16 = 39
TypeOPT uint16 = 41 // EDNS TypeOPT uint16 = 41 // EDNS
TypeAPL uint16 = 42
TypeDS uint16 = 43 TypeDS uint16 = 43
TypeSSHFP uint16 = 44 TypeSSHFP uint16 = 44
TypeRRSIG uint16 = 46 TypeRRSIG uint16 = 46
@ -79,6 +81,8 @@ const (
TypeCDNSKEY uint16 = 60 TypeCDNSKEY uint16 = 60
TypeOPENPGPKEY uint16 = 61 TypeOPENPGPKEY uint16 = 61
TypeCSYNC uint16 = 62 TypeCSYNC uint16 = 62
TypeSVCB uint16 = 64
TypeHTTPS uint16 = 65
TypeSPF uint16 = 99 TypeSPF uint16 = 99
TypeUINFO uint16 = 100 TypeUINFO uint16 = 100
TypeUID uint16 = 101 TypeUID uint16 = 101
@ -163,11 +167,11 @@ const (
_RD = 1 << 8 // recursion desired _RD = 1 << 8 // recursion desired
_RA = 1 << 7 // recursion available _RA = 1 << 7 // recursion available
_Z = 1 << 6 // Z _Z = 1 << 6 // Z
_AD = 1 << 5 // authticated data _AD = 1 << 5 // authenticated data
_CD = 1 << 4 // checking disabled _CD = 1 << 4 // checking disabled
) )
// Various constants used in the LOC RR, See RFC 1887. // Various constants used in the LOC RR. See RFC 1887.
const ( const (
LOC_EQUATOR = 1 << 31 // RFC 1876, Section 2. LOC_EQUATOR = 1 << 31 // RFC 1876, Section 2.
LOC_PRIMEMERIDIAN = 1 << 31 // RFC 1876, Section 2. LOC_PRIMEMERIDIAN = 1 << 31 // RFC 1876, Section 2.
@ -207,8 +211,11 @@ var CertTypeToString = map[uint16]string{
//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. Usually there is just one. While the
// question section of a message. Usually there is just one. // original DNS RFCs allow multiple questions in the question section of a
// message, in practice it never works. Because most DNS servers see multiple
// questions as an error, it is recommended to only have one question per
// message.
type Question struct { type Question struct {
Name string `dns:"cdomain-name"` // "cdomain-name" specifies encoding (and may be compressed) Name string `dns:"cdomain-name"` // "cdomain-name" specifies encoding (and may be compressed)
Qtype uint16 Qtype uint16
@ -229,7 +236,7 @@ func (q *Question) String() (s string) {
return s return s
} }
// ANY is a wildcard record. See RFC 1035, Section 3.2.3. ANY // ANY is a wild card record. See RFC 1035, Section 3.2.3. ANY
// is named "*" there. // is named "*" there.
type ANY struct { type ANY struct {
Hdr RR_Header Hdr RR_Header
@ -238,7 +245,7 @@ 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 { func (rr *ANY) parse(c *zlexer, origin string) *ParseError {
panic("dns: internal error: parse should never be called on ANY") panic("dns: internal error: parse should never be called on ANY")
} }
@ -253,7 +260,7 @@ func (rr *NULL) String() string {
return ";" + rr.Hdr.String() + rr.Data return ";" + rr.Hdr.String() + rr.Data
} }
func (rr *NULL) parse(c *zlexer, origin, file string) *ParseError { func (rr *NULL) parse(c *zlexer, origin string) *ParseError {
panic("dns: internal error: parse should never be called on NULL") panic("dns: internal error: parse should never be called on NULL")
} }
@ -404,7 +411,7 @@ type RP struct {
} }
func (rr *RP) String() string { func (rr *RP) String() string {
return rr.Hdr.String() + rr.Mbox + " " + sprintTxt([]string{rr.Txt}) return rr.Hdr.String() + sprintName(rr.Mbox) + " " + sprintName(rr.Txt)
} }
// SOA RR. See RFC 1035. // SOA RR. See RFC 1035.
@ -438,25 +445,47 @@ func (rr *TXT) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
func sprintName(s string) string { func sprintName(s string) string {
var dst strings.Builder var dst strings.Builder
dst.Grow(len(s))
for i := 0; i < len(s); { for i := 0; i < len(s); {
if i+1 < len(s) && s[i] == '\\' && s[i+1] == '.' { if s[i] == '.' {
dst.WriteString(s[i : i+2]) if dst.Len() != 0 {
i += 2 dst.WriteByte('.')
}
i++
continue continue
} }
b, n := nextByte(s, i) b, n := nextByte(s, i)
switch { if n == 0 {
case n == 0: // Drop "dangling" incomplete escapes.
i++ // dangling back slash if dst.Len() == 0 {
case b == '.': return s[:i]
dst.WriteByte('.') }
default: break
writeDomainNameByte(&dst, b) }
if isDomainNameLabelSpecial(b) {
if dst.Len() == 0 {
dst.Grow(len(s) * 2)
dst.WriteString(s[:i])
}
dst.WriteByte('\\')
dst.WriteByte(b)
} else if b < ' ' || b > '~' { // unprintable, use \DDD
if dst.Len() == 0 {
dst.Grow(len(s) * 2)
dst.WriteString(s[:i])
}
dst.WriteString(escapeByte(b))
} else {
if dst.Len() != 0 {
dst.WriteByte(b)
}
} }
i += n i += n
} }
if dst.Len() == 0 {
return s
}
return dst.String() return dst.String()
} }
@ -472,15 +501,10 @@ func sprintTxtOctet(s string) string {
} }
b, n := nextByte(s, i) b, n := nextByte(s, i)
switch { if n == 0 {
case n == 0:
i++ // dangling back slash i++ // dangling back slash
case b == '.': } else {
dst.WriteByte('.') writeTXTStringByte(&dst, b)
case b < ' ' || b > '~':
dst.WriteString(escapeByte(b))
default:
dst.WriteByte(b)
} }
i += n i += n
} }
@ -510,16 +534,6 @@ func sprintTxt(txt []string) string {
return out.String() return out.String()
} }
func writeDomainNameByte(s *strings.Builder, b byte) {
switch b {
case '.', ' ', '\'', '@', ';', '(', ')': // additional chars to escape
s.WriteByte('\\')
s.WriteByte(b)
default:
writeTXTStringByte(s, b)
}
}
func writeTXTStringByte(s *strings.Builder, b byte) { func writeTXTStringByte(s *strings.Builder, b byte) {
switch { switch {
case b == '"' || b == '\\': case b == '"' || b == '\\':
@ -566,6 +580,17 @@ func escapeByte(b byte) string {
return escapedByteLarge[int(b)*4 : int(b)*4+4] return escapedByteLarge[int(b)*4 : int(b)*4+4]
} }
// isDomainNameLabelSpecial returns true if
// a domain name label byte should be prefixed
// with an escaping backslash.
func isDomainNameLabelSpecial(b byte) bool {
switch b {
case '.', ' ', '\'', '@', ';', '(', ')', '"', '\\':
return true
}
return false
}
func nextByte(s string, offset int) (byte, int) { func nextByte(s string, offset int) (byte, int) {
if offset >= len(s) { if offset >= len(s) {
return 0, 0 return 0, 0
@ -738,8 +763,8 @@ type LOC struct {
Altitude uint32 Altitude uint32
} }
// cmToM takes a cm value expressed in RFC1876 SIZE mantissa/exponent // cmToM takes a cm value expressed in RFC 1876 SIZE mantissa/exponent
// format and returns a string in m (two decimals for the cm) // format and returns a string in m (two decimals for the cm).
func cmToM(m, e uint8) string { func cmToM(m, e uint8) string {
if e < 2 { if e < 2 {
if e == 1 { if e == 1 {
@ -845,8 +870,8 @@ type NSEC struct {
func (rr *NSEC) String() string { func (rr *NSEC) String() string {
s := rr.Hdr.String() + sprintName(rr.NextDomain) s := rr.Hdr.String() + sprintName(rr.NextDomain)
for i := 0; i < len(rr.TypeBitMap); i++ { for _, t := range rr.TypeBitMap {
s += " " + Type(rr.TypeBitMap[i]).String() s += " " + Type(t).String()
} }
return s return s
} }
@ -854,14 +879,7 @@ func (rr *NSEC) String() string {
func (rr *NSEC) len(off int, compression map[string]struct{}) int { func (rr *NSEC) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len(off, compression)
l += domainNameLen(rr.NextDomain, off+l, compression, false) l += domainNameLen(rr.NextDomain, off+l, compression, false)
lastwindow := uint32(2 ^ 32 + 1) l += typeBitMapLen(rr.TypeBitMap)
for _, t := range rr.TypeBitMap {
window := t / 256
if uint32(window) != lastwindow {
l += 1 + 32
}
lastwindow = uint32(window)
}
return l return l
} }
@ -1011,8 +1029,8 @@ func (rr *NSEC3) String() string {
" " + strconv.Itoa(int(rr.Iterations)) + " " + strconv.Itoa(int(rr.Iterations)) +
" " + saltToString(rr.Salt) + " " + saltToString(rr.Salt) +
" " + rr.NextDomain " " + rr.NextDomain
for i := 0; i < len(rr.TypeBitMap); i++ { for _, t := range rr.TypeBitMap {
s += " " + Type(rr.TypeBitMap[i]).String() s += " " + Type(t).String()
} }
return s return s
} }
@ -1020,14 +1038,7 @@ func (rr *NSEC3) String() string {
func (rr *NSEC3) len(off int, compression map[string]struct{}) int { func (rr *NSEC3) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len(off, compression)
l += 6 + len(rr.Salt)/2 + 1 + len(rr.NextDomain) + 1 l += 6 + len(rr.Salt)/2 + 1 + len(rr.NextDomain) + 1
lastwindow := uint32(2 ^ 32 + 1) l += typeBitMapLen(rr.TypeBitMap)
for _, t := range rr.TypeBitMap {
window := t / 256
if uint32(window) != lastwindow {
l += 1 + 32
}
lastwindow = uint32(window)
}
return l return l
} }
@ -1111,6 +1122,7 @@ type URI struct {
Target string `dns:"octet"` Target string `dns:"octet"`
} }
// rr.Target to be parsed as a sequence of character encoded octets according to RFC 3986
func (rr *URI) String() string { func (rr *URI) String() string {
return rr.Hdr.String() + strconv.Itoa(int(rr.Priority)) + return rr.Hdr.String() + strconv.Itoa(int(rr.Priority)) +
" " + strconv.Itoa(int(rr.Weight)) + " " + sprintTxtOctet(rr.Target) " " + strconv.Itoa(int(rr.Weight)) + " " + sprintTxtOctet(rr.Target)
@ -1272,6 +1284,7 @@ type CAA struct {
Value string `dns:"octet"` Value string `dns:"octet"`
} }
// rr.Value Is the character-string encoding of the value field as specified in RFC 1035, Section 5.1.
func (rr *CAA) String() string { func (rr *CAA) String() string {
return rr.Hdr.String() + strconv.Itoa(int(rr.Flag)) + " " + rr.Tag + " " + sprintTxtOctet(rr.Value) return rr.Hdr.String() + strconv.Itoa(int(rr.Flag)) + " " + rr.Tag + " " + sprintTxtOctet(rr.Value)
} }
@ -1335,8 +1348,8 @@ type CSYNC struct {
func (rr *CSYNC) String() string { func (rr *CSYNC) String() string {
s := rr.Hdr.String() + strconv.FormatInt(int64(rr.Serial), 10) + " " + strconv.Itoa(int(rr.Flags)) s := rr.Hdr.String() + strconv.FormatInt(int64(rr.Serial), 10) + " " + strconv.Itoa(int(rr.Flags))
for i := 0; i < len(rr.TypeBitMap); i++ { for _, t := range rr.TypeBitMap {
s += " " + Type(rr.TypeBitMap[i]).String() s += " " + Type(t).String()
} }
return s return s
} }
@ -1344,17 +1357,92 @@ func (rr *CSYNC) String() string {
func (rr *CSYNC) len(off int, compression map[string]struct{}) int { func (rr *CSYNC) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len(off, compression)
l += 4 + 2 l += 4 + 2
lastwindow := uint32(2 ^ 32 + 1) l += typeBitMapLen(rr.TypeBitMap)
for _, t := range rr.TypeBitMap {
window := t / 256
if uint32(window) != lastwindow {
l += 1 + 32
}
lastwindow = uint32(window)
}
return l return l
} }
// APL RR. See RFC 3123.
type APL struct {
Hdr RR_Header
Prefixes []APLPrefix `dns:"apl"`
}
// APLPrefix is an address prefix hold by an APL record.
type APLPrefix struct {
Negation bool
Network net.IPNet
}
// String returns presentation form of the APL record.
func (rr *APL) String() string {
var sb strings.Builder
sb.WriteString(rr.Hdr.String())
for i, p := range rr.Prefixes {
if i > 0 {
sb.WriteByte(' ')
}
sb.WriteString(p.str())
}
return sb.String()
}
// str returns presentation form of the APL prefix.
func (p *APLPrefix) str() string {
var sb strings.Builder
if p.Negation {
sb.WriteByte('!')
}
switch len(p.Network.IP) {
case net.IPv4len:
sb.WriteByte('1')
case net.IPv6len:
sb.WriteByte('2')
}
sb.WriteByte(':')
switch len(p.Network.IP) {
case net.IPv4len:
sb.WriteString(p.Network.IP.String())
case net.IPv6len:
// add prefix for IPv4-mapped IPv6
if v4 := p.Network.IP.To4(); v4 != nil {
sb.WriteString("::ffff:")
}
sb.WriteString(p.Network.IP.String())
}
sb.WriteByte('/')
prefix, _ := p.Network.Mask.Size()
sb.WriteString(strconv.Itoa(prefix))
return sb.String()
}
// equals reports whether two APL prefixes are identical.
func (a *APLPrefix) equals(b *APLPrefix) bool {
return a.Negation == b.Negation &&
bytes.Equal(a.Network.IP, b.Network.IP) &&
bytes.Equal(a.Network.Mask, b.Network.Mask)
}
// copy returns a copy of the APL prefix.
func (p *APLPrefix) copy() APLPrefix {
return APLPrefix{
Negation: p.Negation,
Network: copyNet(p.Network),
}
}
// len returns size of the prefix in wire format.
func (p *APLPrefix) len() int {
// 4-byte header and the network address prefix (see Section 4 of RFC 3123)
prefix, _ := p.Network.Mask.Size()
return 4 + (prefix+7)/8
}
// TimeToString translates the RRSIG's incep. and expir. times to the // TimeToString translates the RRSIG's incep. and expir. times to the
// 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.
@ -1411,6 +1499,17 @@ func copyIP(ip net.IP) net.IP {
return p return p
} }
// copyNet returns a copy of a subnet.
func copyNet(n net.IPNet) net.IPNet {
m := make(net.IPMask, len(n.Mask))
copy(m, n.Mask)
return net.IPNet{
IP: copyIP(n.IP),
Mask: m,
}
}
// SplitN splits a string into N sized string chunks. // SplitN splits a string into N sized string chunks.
// This might become an exported function once. // This might become an exported function once.
func splitN(s string, n int) []string { func splitN(s string, n int) []string {

View File

@ -3,13 +3,13 @@ package dns
import "fmt" import "fmt"
// Version is current version of this library. // Version is current version of this library.
var Version = V{1, 1, 4} var Version = v{1, 1, 35}
// V holds the version of this library. // v holds the version of this library.
type V struct { type v struct {
Major, Minor, Patch int Major, Minor, Patch int
} }
func (v V) String() string { func (v v) String() string {
return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch) return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
} }

18
vendor/github.com/miekg/dns/xfr.go generated vendored
View File

@ -182,14 +182,17 @@ func (t *Transfer) inIxfr(q *Msg, c chan *Envelope) {
// //
// ch := make(chan *dns.Envelope) // ch := make(chan *dns.Envelope)
// tr := new(dns.Transfer) // tr := new(dns.Transfer)
// go tr.Out(w, r, ch) // var wg sync.WaitGroup
// go func() {
// tr.Out(w, r, ch)
// wg.Done()
// }()
// ch <- &dns.Envelope{RR: []dns.RR{soa, rr1, rr2, rr3, soa}} // ch <- &dns.Envelope{RR: []dns.RR{soa, rr1, rr2, rr3, soa}}
// close(ch) // close(ch)
// w.Hijack() // wg.Wait() // wait until everything is written out
// // w.Close() // Client closes connection // w.Close() // close connection
// //
// The server is responsible for sending the correct sequence of RRs through the // The server is responsible for sending the correct sequence of RRs through the channel ch.
// channel ch.
func (t *Transfer) Out(w ResponseWriter, q *Msg, ch chan *Envelope) error { func (t *Transfer) Out(w ResponseWriter, q *Msg, ch chan *Envelope) error {
for x := range ch { for x := range ch {
r := new(Msg) r := new(Msg)
@ -198,11 +201,14 @@ func (t *Transfer) Out(w ResponseWriter, q *Msg, ch chan *Envelope) error {
r.Authoritative = true r.Authoritative = true
// assume it fits TODO(miek): fix // assume it fits TODO(miek): fix
r.Answer = append(r.Answer, x.RR...) r.Answer = append(r.Answer, x.RR...)
if tsig := q.IsTsig(); tsig != nil && w.TsigStatus() == nil {
r.SetTsig(tsig.Hdr.Name, tsig.Algorithm, tsig.Fudge, time.Now().Unix())
}
if err := w.WriteMsg(r); err != nil { if err := w.WriteMsg(r); err != nil {
return err return err
} }
}
w.TsigTimersOnly(true) w.TsigTimersOnly(true)
}
return nil return nil
} }

View File

@ -37,7 +37,7 @@ func (r1 *AFSDB) isDuplicate(_r2 RR) bool {
if r1.Subtype != r2.Subtype { if r1.Subtype != r2.Subtype {
return false return false
} }
if !isDulicateName(r1.Hostname, r2.Hostname) { if !isDuplicateName(r1.Hostname, r2.Hostname) {
return false return false
} }
return true return true
@ -52,6 +52,23 @@ func (r1 *ANY) isDuplicate(_r2 RR) bool {
return true return true
} }
func (r1 *APL) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*APL)
if !ok {
return false
}
_ = r2
if len(r1.Prefixes) != len(r2.Prefixes) {
return false
}
for i := 0; i < len(r1.Prefixes); i++ {
if !r1.Prefixes[i].equals(&r2.Prefixes[i]) {
return false
}
}
return true
}
func (r1 *AVC) isDuplicate(_r2 RR) bool { func (r1 *AVC) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*AVC) r2, ok := _r2.(*AVC)
if !ok { if !ok {
@ -87,6 +104,48 @@ func (r1 *CAA) isDuplicate(_r2 RR) bool {
return true return true
} }
func (r1 *CDNSKEY) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*CDNSKEY)
if !ok {
return false
}
_ = r2
if r1.Flags != r2.Flags {
return false
}
if r1.Protocol != r2.Protocol {
return false
}
if r1.Algorithm != r2.Algorithm {
return false
}
if r1.PublicKey != r2.PublicKey {
return false
}
return true
}
func (r1 *CDS) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*CDS)
if !ok {
return false
}
_ = r2
if r1.KeyTag != r2.KeyTag {
return false
}
if r1.Algorithm != r2.Algorithm {
return false
}
if r1.DigestType != r2.DigestType {
return false
}
if r1.Digest != r2.Digest {
return false
}
return true
}
func (r1 *CERT) isDuplicate(_r2 RR) bool { func (r1 *CERT) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*CERT) r2, ok := _r2.(*CERT)
if !ok { if !ok {
@ -114,7 +173,7 @@ func (r1 *CNAME) isDuplicate(_r2 RR) bool {
return false return false
} }
_ = r2 _ = r2
if !isDulicateName(r1.Target, r2.Target) { if !isDuplicateName(r1.Target, r2.Target) {
return false return false
} }
return true return true
@ -155,13 +214,34 @@ func (r1 *DHCID) isDuplicate(_r2 RR) bool {
return true return true
} }
func (r1 *DLV) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*DLV)
if !ok {
return false
}
_ = r2
if r1.KeyTag != r2.KeyTag {
return false
}
if r1.Algorithm != r2.Algorithm {
return false
}
if r1.DigestType != r2.DigestType {
return false
}
if r1.Digest != r2.Digest {
return false
}
return true
}
func (r1 *DNAME) isDuplicate(_r2 RR) bool { func (r1 *DNAME) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*DNAME) r2, ok := _r2.(*DNAME)
if !ok { if !ok {
return false return false
} }
_ = r2 _ = r2
if !isDulicateName(r1.Target, r2.Target) { if !isDuplicateName(r1.Target, r2.Target) {
return false return false
} }
return true return true
@ -315,13 +395,55 @@ func (r1 *HIP) isDuplicate(_r2 RR) bool {
return false return false
} }
for i := 0; i < len(r1.RendezvousServers); i++ { for i := 0; i < len(r1.RendezvousServers); i++ {
if !isDulicateName(r1.RendezvousServers[i], r2.RendezvousServers[i]) { if !isDuplicateName(r1.RendezvousServers[i], r2.RendezvousServers[i]) {
return false return false
} }
} }
return true return true
} }
func (r1 *HTTPS) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*HTTPS)
if !ok {
return false
}
_ = r2
if r1.Priority != r2.Priority {
return false
}
if !isDuplicateName(r1.Target, r2.Target) {
return false
}
if len(r1.Value) != len(r2.Value) {
return false
}
if !areSVCBPairArraysEqual(r1.Value, r2.Value) {
return false
}
return true
}
func (r1 *KEY) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*KEY)
if !ok {
return false
}
_ = r2
if r1.Flags != r2.Flags {
return false
}
if r1.Protocol != r2.Protocol {
return false
}
if r1.Algorithm != r2.Algorithm {
return false
}
if r1.PublicKey != r2.PublicKey {
return false
}
return true
}
func (r1 *KX) isDuplicate(_r2 RR) bool { func (r1 *KX) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*KX) r2, ok := _r2.(*KX)
if !ok { if !ok {
@ -331,7 +453,7 @@ func (r1 *KX) isDuplicate(_r2 RR) bool {
if r1.Preference != r2.Preference { if r1.Preference != r2.Preference {
return false return false
} }
if !isDulicateName(r1.Exchanger, r2.Exchanger) { if !isDuplicateName(r1.Exchanger, r2.Exchanger) {
return false return false
} }
return true return true
@ -406,7 +528,7 @@ func (r1 *LP) isDuplicate(_r2 RR) bool {
if r1.Preference != r2.Preference { if r1.Preference != r2.Preference {
return false return false
} }
if !isDulicateName(r1.Fqdn, r2.Fqdn) { if !isDuplicateName(r1.Fqdn, r2.Fqdn) {
return false return false
} }
return true return true
@ -418,7 +540,7 @@ func (r1 *MB) isDuplicate(_r2 RR) bool {
return false return false
} }
_ = r2 _ = r2
if !isDulicateName(r1.Mb, r2.Mb) { if !isDuplicateName(r1.Mb, r2.Mb) {
return false return false
} }
return true return true
@ -430,7 +552,7 @@ func (r1 *MD) isDuplicate(_r2 RR) bool {
return false return false
} }
_ = r2 _ = r2
if !isDulicateName(r1.Md, r2.Md) { if !isDuplicateName(r1.Md, r2.Md) {
return false return false
} }
return true return true
@ -442,7 +564,7 @@ func (r1 *MF) isDuplicate(_r2 RR) bool {
return false return false
} }
_ = r2 _ = r2
if !isDulicateName(r1.Mf, r2.Mf) { if !isDuplicateName(r1.Mf, r2.Mf) {
return false return false
} }
return true return true
@ -454,7 +576,7 @@ func (r1 *MG) isDuplicate(_r2 RR) bool {
return false return false
} }
_ = r2 _ = r2
if !isDulicateName(r1.Mg, r2.Mg) { if !isDuplicateName(r1.Mg, r2.Mg) {
return false return false
} }
return true return true
@ -466,10 +588,10 @@ func (r1 *MINFO) isDuplicate(_r2 RR) bool {
return false return false
} }
_ = r2 _ = r2
if !isDulicateName(r1.Rmail, r2.Rmail) { if !isDuplicateName(r1.Rmail, r2.Rmail) {
return false return false
} }
if !isDulicateName(r1.Email, r2.Email) { if !isDuplicateName(r1.Email, r2.Email) {
return false return false
} }
return true return true
@ -481,7 +603,7 @@ func (r1 *MR) isDuplicate(_r2 RR) bool {
return false return false
} }
_ = r2 _ = r2
if !isDulicateName(r1.Mr, r2.Mr) { if !isDuplicateName(r1.Mr, r2.Mr) {
return false return false
} }
return true return true
@ -496,7 +618,7 @@ func (r1 *MX) isDuplicate(_r2 RR) bool {
if r1.Preference != r2.Preference { if r1.Preference != r2.Preference {
return false return false
} }
if !isDulicateName(r1.Mx, r2.Mx) { if !isDuplicateName(r1.Mx, r2.Mx) {
return false return false
} }
return true return true
@ -523,7 +645,7 @@ func (r1 *NAPTR) isDuplicate(_r2 RR) bool {
if r1.Regexp != r2.Regexp { if r1.Regexp != r2.Regexp {
return false return false
} }
if !isDulicateName(r1.Replacement, r2.Replacement) { if !isDuplicateName(r1.Replacement, r2.Replacement) {
return false return false
} }
return true return true
@ -579,7 +701,7 @@ func (r1 *NS) isDuplicate(_r2 RR) bool {
return false return false
} }
_ = r2 _ = r2
if !isDulicateName(r1.Ns, r2.Ns) { if !isDuplicateName(r1.Ns, r2.Ns) {
return false return false
} }
return true return true
@ -591,7 +713,7 @@ func (r1 *NSAPPTR) isDuplicate(_r2 RR) bool {
return false return false
} }
_ = r2 _ = r2
if !isDulicateName(r1.Ptr, r2.Ptr) { if !isDuplicateName(r1.Ptr, r2.Ptr) {
return false return false
} }
return true return true
@ -603,7 +725,7 @@ func (r1 *NSEC) isDuplicate(_r2 RR) bool {
return false return false
} }
_ = r2 _ = r2
if !isDulicateName(r1.NextDomain, r2.NextDomain) { if !isDuplicateName(r1.NextDomain, r2.NextDomain) {
return false return false
} }
if len(r1.TypeBitMap) != len(r2.TypeBitMap) { if len(r1.TypeBitMap) != len(r2.TypeBitMap) {
@ -709,7 +831,7 @@ func (r1 *PTR) isDuplicate(_r2 RR) bool {
return false return false
} }
_ = r2 _ = r2
if !isDulicateName(r1.Ptr, r2.Ptr) { if !isDuplicateName(r1.Ptr, r2.Ptr) {
return false return false
} }
return true return true
@ -724,10 +846,10 @@ func (r1 *PX) isDuplicate(_r2 RR) bool {
if r1.Preference != r2.Preference { if r1.Preference != r2.Preference {
return false return false
} }
if !isDulicateName(r1.Map822, r2.Map822) { if !isDuplicateName(r1.Map822, r2.Map822) {
return false return false
} }
if !isDulicateName(r1.Mapx400, r2.Mapx400) { if !isDuplicateName(r1.Mapx400, r2.Mapx400) {
return false return false
} }
return true return true
@ -772,10 +894,10 @@ func (r1 *RP) isDuplicate(_r2 RR) bool {
return false return false
} }
_ = r2 _ = r2
if !isDulicateName(r1.Mbox, r2.Mbox) { if !isDuplicateName(r1.Mbox, r2.Mbox) {
return false return false
} }
if !isDulicateName(r1.Txt, r2.Txt) { if !isDuplicateName(r1.Txt, r2.Txt) {
return false return false
} }
return true return true
@ -808,7 +930,7 @@ func (r1 *RRSIG) isDuplicate(_r2 RR) bool {
if r1.KeyTag != r2.KeyTag { if r1.KeyTag != r2.KeyTag {
return false return false
} }
if !isDulicateName(r1.SignerName, r2.SignerName) { if !isDuplicateName(r1.SignerName, r2.SignerName) {
return false return false
} }
if r1.Signature != r2.Signature { if r1.Signature != r2.Signature {
@ -826,7 +948,43 @@ func (r1 *RT) isDuplicate(_r2 RR) bool {
if r1.Preference != r2.Preference { if r1.Preference != r2.Preference {
return false return false
} }
if !isDulicateName(r1.Host, r2.Host) { if !isDuplicateName(r1.Host, r2.Host) {
return false
}
return true
}
func (r1 *SIG) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*SIG)
if !ok {
return false
}
_ = r2
if r1.TypeCovered != r2.TypeCovered {
return false
}
if r1.Algorithm != r2.Algorithm {
return false
}
if r1.Labels != r2.Labels {
return false
}
if r1.OrigTtl != r2.OrigTtl {
return false
}
if r1.Expiration != r2.Expiration {
return false
}
if r1.Inception != r2.Inception {
return false
}
if r1.KeyTag != r2.KeyTag {
return false
}
if !isDuplicateName(r1.SignerName, r2.SignerName) {
return false
}
if r1.Signature != r2.Signature {
return false return false
} }
return true return true
@ -859,10 +1017,10 @@ func (r1 *SOA) isDuplicate(_r2 RR) bool {
return false return false
} }
_ = r2 _ = r2
if !isDulicateName(r1.Ns, r2.Ns) { if !isDuplicateName(r1.Ns, r2.Ns) {
return false return false
} }
if !isDulicateName(r1.Mbox, r2.Mbox) { if !isDuplicateName(r1.Mbox, r2.Mbox) {
return false return false
} }
if r1.Serial != r2.Serial { if r1.Serial != r2.Serial {
@ -915,7 +1073,7 @@ func (r1 *SRV) isDuplicate(_r2 RR) bool {
if r1.Port != r2.Port { if r1.Port != r2.Port {
return false return false
} }
if !isDulicateName(r1.Target, r2.Target) { if !isDuplicateName(r1.Target, r2.Target) {
return false return false
} }
return true return true
@ -939,6 +1097,27 @@ func (r1 *SSHFP) isDuplicate(_r2 RR) bool {
return true return true
} }
func (r1 *SVCB) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*SVCB)
if !ok {
return false
}
_ = r2
if r1.Priority != r2.Priority {
return false
}
if !isDuplicateName(r1.Target, r2.Target) {
return false
}
if len(r1.Value) != len(r2.Value) {
return false
}
if !areSVCBPairArraysEqual(r1.Value, r2.Value) {
return false
}
return true
}
func (r1 *TA) isDuplicate(_r2 RR) bool { func (r1 *TA) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*TA) r2, ok := _r2.(*TA)
if !ok { if !ok {
@ -966,10 +1145,10 @@ func (r1 *TALINK) isDuplicate(_r2 RR) bool {
return false return false
} }
_ = r2 _ = r2
if !isDulicateName(r1.PreviousName, r2.PreviousName) { if !isDuplicateName(r1.PreviousName, r2.PreviousName) {
return false return false
} }
if !isDulicateName(r1.NextName, r2.NextName) { if !isDuplicateName(r1.NextName, r2.NextName) {
return false return false
} }
return true return true
@ -981,7 +1160,7 @@ func (r1 *TKEY) isDuplicate(_r2 RR) bool {
return false return false
} }
_ = r2 _ = r2
if !isDulicateName(r1.Algorithm, r2.Algorithm) { if !isDuplicateName(r1.Algorithm, r2.Algorithm) {
return false return false
} }
if r1.Inception != r2.Inception { if r1.Inception != r2.Inception {
@ -1038,7 +1217,7 @@ func (r1 *TSIG) isDuplicate(_r2 RR) bool {
return false return false
} }
_ = r2 _ = r2
if !isDulicateName(r1.Algorithm, r2.Algorithm) { if !isDuplicateName(r1.Algorithm, r2.Algorithm) {
return false return false
} }
if r1.TimeSigned != r2.TimeSigned { if r1.TimeSigned != r2.TimeSigned {

101
vendor/github.com/miekg/dns/zmsg.go generated vendored
View File

@ -36,6 +36,14 @@ func (rr *ANY) pack(msg []byte, off int, compression compressionMap, compress bo
return off, nil return off, nil
} }
func (rr *APL) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packDataApl(rr.Prefixes, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *AVC) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) { func (rr *AVC) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packStringTxt(rr.Txt, msg, off) off, err = packStringTxt(rr.Txt, msg, off)
if err != nil { if err != nil {
@ -308,6 +316,22 @@ func (rr *HIP) pack(msg []byte, off int, compression compressionMap, compress bo
return off, nil return off, nil
} }
func (rr *HTTPS) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.Priority, msg, off)
if err != nil {
return off, err
}
off, err = packDomainName(rr.Target, msg, off, compression, false)
if err != nil {
return off, err
}
off, err = packDataSVCB(rr.Value, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *KEY) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) { func (rr *KEY) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.Flags, msg, off) off, err = packUint16(rr.Flags, msg, off)
if err != nil { if err != nil {
@ -898,6 +922,22 @@ func (rr *SSHFP) pack(msg []byte, off int, compression compressionMap, compress
return off, nil return off, nil
} }
func (rr *SVCB) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.Priority, msg, off)
if err != nil {
return off, err
}
off, err = packDomainName(rr.Target, msg, off, compression, false)
if err != nil {
return off, err
}
off, err = packDataSVCB(rr.Value, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *TA) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) { func (rr *TA) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.KeyTag, msg, off) off, err = packUint16(rr.KeyTag, msg, off)
if err != nil { if err != nil {
@ -1127,6 +1167,17 @@ func (rr *ANY) unpack(msg []byte, off int) (off1 int, err error) {
return off, nil return off, nil
} }
func (rr *APL) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Prefixes, off, err = unpackDataApl(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *AVC) unpack(msg []byte, off int) (off1 int, err error) { func (rr *AVC) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off rdStart := off
_ = rdStart _ = rdStart
@ -1540,6 +1591,31 @@ func (rr *HIP) unpack(msg []byte, off int) (off1 int, err error) {
return off, nil return off, nil
} }
func (rr *HTTPS) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Priority, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Target, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Value, off, err = unpackDataSVCB(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *KEY) unpack(msg []byte, off int) (off1 int, err error) { func (rr *KEY) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off rdStart := off
_ = rdStart _ = rdStart
@ -2442,6 +2518,31 @@ func (rr *SSHFP) unpack(msg []byte, off int) (off1 int, err error) {
return off, nil return off, nil
} }
func (rr *SVCB) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Priority, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Target, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Value, off, err = unpackDataSVCB(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *TA) unpack(msg []byte, off int) (off1 int, err error) { func (rr *TA) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off rdStart := off
_ = rdStart _ = rdStart

View File

@ -13,6 +13,7 @@ var TypeToRR = map[uint16]func() RR{
TypeAAAA: func() RR { return new(AAAA) }, TypeAAAA: func() RR { return new(AAAA) },
TypeAFSDB: func() RR { return new(AFSDB) }, TypeAFSDB: func() RR { return new(AFSDB) },
TypeANY: func() RR { return new(ANY) }, TypeANY: func() RR { return new(ANY) },
TypeAPL: func() RR { return new(APL) },
TypeAVC: func() RR { return new(AVC) }, TypeAVC: func() RR { return new(AVC) },
TypeCAA: func() RR { return new(CAA) }, TypeCAA: func() RR { return new(CAA) },
TypeCDNSKEY: func() RR { return new(CDNSKEY) }, TypeCDNSKEY: func() RR { return new(CDNSKEY) },
@ -32,6 +33,7 @@ var TypeToRR = map[uint16]func() RR{
TypeGPOS: func() RR { return new(GPOS) }, TypeGPOS: func() RR { return new(GPOS) },
TypeHINFO: func() RR { return new(HINFO) }, TypeHINFO: func() RR { return new(HINFO) },
TypeHIP: func() RR { return new(HIP) }, TypeHIP: func() RR { return new(HIP) },
TypeHTTPS: func() RR { return new(HTTPS) },
TypeKEY: func() RR { return new(KEY) }, TypeKEY: func() RR { return new(KEY) },
TypeKX: func() RR { return new(KX) }, TypeKX: func() RR { return new(KX) },
TypeL32: func() RR { return new(L32) }, TypeL32: func() RR { return new(L32) },
@ -69,6 +71,7 @@ var TypeToRR = map[uint16]func() RR{
TypeSPF: func() RR { return new(SPF) }, TypeSPF: func() RR { return new(SPF) },
TypeSRV: func() RR { return new(SRV) }, TypeSRV: func() RR { return new(SRV) },
TypeSSHFP: func() RR { return new(SSHFP) }, TypeSSHFP: func() RR { return new(SSHFP) },
TypeSVCB: func() RR { return new(SVCB) },
TypeTA: func() RR { return new(TA) }, TypeTA: func() RR { return new(TA) },
TypeTALINK: func() RR { return new(TALINK) }, TypeTALINK: func() RR { return new(TALINK) },
TypeTKEY: func() RR { return new(TKEY) }, TypeTKEY: func() RR { return new(TKEY) },
@ -87,6 +90,7 @@ var TypeToString = map[uint16]string{
TypeAAAA: "AAAA", TypeAAAA: "AAAA",
TypeAFSDB: "AFSDB", TypeAFSDB: "AFSDB",
TypeANY: "ANY", TypeANY: "ANY",
TypeAPL: "APL",
TypeATMA: "ATMA", TypeATMA: "ATMA",
TypeAVC: "AVC", TypeAVC: "AVC",
TypeAXFR: "AXFR", TypeAXFR: "AXFR",
@ -108,6 +112,7 @@ var TypeToString = map[uint16]string{
TypeGPOS: "GPOS", TypeGPOS: "GPOS",
TypeHINFO: "HINFO", TypeHINFO: "HINFO",
TypeHIP: "HIP", TypeHIP: "HIP",
TypeHTTPS: "HTTPS",
TypeISDN: "ISDN", TypeISDN: "ISDN",
TypeIXFR: "IXFR", TypeIXFR: "IXFR",
TypeKEY: "KEY", TypeKEY: "KEY",
@ -151,6 +156,7 @@ var TypeToString = map[uint16]string{
TypeSPF: "SPF", TypeSPF: "SPF",
TypeSRV: "SRV", TypeSRV: "SRV",
TypeSSHFP: "SSHFP", TypeSSHFP: "SSHFP",
TypeSVCB: "SVCB",
TypeTA: "TA", TypeTA: "TA",
TypeTALINK: "TALINK", TypeTALINK: "TALINK",
TypeTKEY: "TKEY", TypeTKEY: "TKEY",
@ -169,6 +175,7 @@ func (rr *A) Header() *RR_Header { return &rr.Hdr }
func (rr *AAAA) Header() *RR_Header { return &rr.Hdr } func (rr *AAAA) Header() *RR_Header { return &rr.Hdr }
func (rr *AFSDB) Header() *RR_Header { return &rr.Hdr } func (rr *AFSDB) Header() *RR_Header { return &rr.Hdr }
func (rr *ANY) Header() *RR_Header { return &rr.Hdr } func (rr *ANY) Header() *RR_Header { return &rr.Hdr }
func (rr *APL) Header() *RR_Header { return &rr.Hdr }
func (rr *AVC) Header() *RR_Header { return &rr.Hdr } func (rr *AVC) Header() *RR_Header { return &rr.Hdr }
func (rr *CAA) Header() *RR_Header { return &rr.Hdr } func (rr *CAA) Header() *RR_Header { return &rr.Hdr }
func (rr *CDNSKEY) Header() *RR_Header { return &rr.Hdr } func (rr *CDNSKEY) Header() *RR_Header { return &rr.Hdr }
@ -188,6 +195,7 @@ func (rr *GID) Header() *RR_Header { return &rr.Hdr }
func (rr *GPOS) Header() *RR_Header { return &rr.Hdr } func (rr *GPOS) Header() *RR_Header { return &rr.Hdr }
func (rr *HINFO) Header() *RR_Header { return &rr.Hdr } func (rr *HINFO) Header() *RR_Header { return &rr.Hdr }
func (rr *HIP) Header() *RR_Header { return &rr.Hdr } func (rr *HIP) Header() *RR_Header { return &rr.Hdr }
func (rr *HTTPS) Header() *RR_Header { return &rr.Hdr }
func (rr *KEY) Header() *RR_Header { return &rr.Hdr } func (rr *KEY) Header() *RR_Header { return &rr.Hdr }
func (rr *KX) Header() *RR_Header { return &rr.Hdr } func (rr *KX) Header() *RR_Header { return &rr.Hdr }
func (rr *L32) Header() *RR_Header { return &rr.Hdr } func (rr *L32) Header() *RR_Header { return &rr.Hdr }
@ -226,6 +234,7 @@ func (rr *SOA) Header() *RR_Header { return &rr.Hdr }
func (rr *SPF) Header() *RR_Header { return &rr.Hdr } func (rr *SPF) Header() *RR_Header { return &rr.Hdr }
func (rr *SRV) Header() *RR_Header { return &rr.Hdr } func (rr *SRV) Header() *RR_Header { return &rr.Hdr }
func (rr *SSHFP) Header() *RR_Header { return &rr.Hdr } func (rr *SSHFP) Header() *RR_Header { return &rr.Hdr }
func (rr *SVCB) Header() *RR_Header { return &rr.Hdr }
func (rr *TA) Header() *RR_Header { return &rr.Hdr } func (rr *TA) Header() *RR_Header { return &rr.Hdr }
func (rr *TALINK) Header() *RR_Header { return &rr.Hdr } func (rr *TALINK) Header() *RR_Header { return &rr.Hdr }
func (rr *TKEY) Header() *RR_Header { return &rr.Hdr } func (rr *TKEY) Header() *RR_Header { return &rr.Hdr }
@ -240,12 +249,16 @@ func (rr *X25) Header() *RR_Header { return &rr.Hdr }
// len() functions // len() functions
func (rr *A) len(off int, compression map[string]struct{}) int { func (rr *A) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len(off, compression)
l += net.IPv4len // A if len(rr.A) != 0 {
l += net.IPv4len
}
return l return l
} }
func (rr *AAAA) len(off int, compression map[string]struct{}) int { func (rr *AAAA) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len(off, compression)
l += net.IPv6len // AAAA if len(rr.AAAA) != 0 {
l += net.IPv6len
}
return l return l
} }
func (rr *AFSDB) len(off int, compression map[string]struct{}) int { func (rr *AFSDB) len(off int, compression map[string]struct{}) int {
@ -258,6 +271,13 @@ func (rr *ANY) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len(off, compression)
return l return l
} }
func (rr *APL) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
for _, x := range rr.Prefixes {
l += x.len()
}
return l
}
func (rr *AVC) len(off int, compression map[string]struct{}) int { func (rr *AVC) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len(off, compression)
for _, x := range rr.Txt { for _, x := range rr.Txt {
@ -308,12 +328,12 @@ func (rr *DS) len(off int, compression map[string]struct{}) int {
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
return l return l
} }
func (rr *EID) len(off int, compression map[string]struct{}) int { func (rr *EID) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len(off, compression)
l += len(rr.Endpoint)/2 + 1 l += len(rr.Endpoint) / 2
return l return l
} }
func (rr *EUI48) len(off int, compression map[string]struct{}) int { func (rr *EUI48) len(off int, compression map[string]struct{}) int {
@ -365,7 +385,9 @@ func (rr *KX) len(off int, compression map[string]struct{}) int {
func (rr *L32) len(off int, compression map[string]struct{}) int { func (rr *L32) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len(off, compression)
l += 2 // Preference l += 2 // Preference
l += net.IPv4len // Locator32 if len(rr.Locator32) != 0 {
l += net.IPv4len
}
return l return l
} }
func (rr *L64) len(off int, compression map[string]struct{}) int { func (rr *L64) len(off int, compression map[string]struct{}) int {
@ -446,7 +468,7 @@ func (rr *NID) len(off int, compression map[string]struct{}) int {
} }
func (rr *NIMLOC) len(off int, compression map[string]struct{}) int { func (rr *NIMLOC) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len(off, compression)
l += len(rr.Locator)/2 + 1 l += len(rr.Locator) / 2
return l return l
} }
func (rr *NINFO) len(off int, compression map[string]struct{}) int { func (rr *NINFO) len(off int, compression map[string]struct{}) int {
@ -499,7 +521,7 @@ func (rr *PX) len(off int, compression map[string]struct{}) int {
} }
func (rr *RFC3597) len(off int, compression map[string]struct{}) int { func (rr *RFC3597) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len(off, compression)
l += len(rr.Rdata)/2 + 1 l += len(rr.Rdata) / 2
return l return l
} }
func (rr *RKEY) len(off int, compression map[string]struct{}) int { func (rr *RKEY) len(off int, compression map[string]struct{}) int {
@ -540,7 +562,7 @@ func (rr *SMIMEA) len(off int, compression map[string]struct{}) int {
l++ // Usage l++ // Usage
l++ // Selector l++ // Selector
l++ // MatchingType l++ // MatchingType
l += len(rr.Certificate)/2 + 1 l += len(rr.Certificate) / 2
return l return l
} }
func (rr *SOA) len(off int, compression map[string]struct{}) int { func (rr *SOA) len(off int, compression map[string]struct{}) int {
@ -573,7 +595,16 @@ func (rr *SSHFP) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression) l := rr.Hdr.len(off, compression)
l++ // Algorithm l++ // Algorithm
l++ // Type l++ // Type
l += len(rr.FingerPrint)/2 + 1 l += len(rr.FingerPrint) / 2
return l
}
func (rr *SVCB) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += 2 // Priority
l += domainNameLen(rr.Target, off+l, compression, false)
for _, x := range rr.Value {
l += 4 + int(x.len())
}
return l return l
} }
func (rr *TA) len(off int, compression map[string]struct{}) int { func (rr *TA) len(off int, compression map[string]struct{}) int {
@ -581,7 +612,7 @@ func (rr *TA) len(off int, compression map[string]struct{}) int {
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
return l return l
} }
func (rr *TALINK) len(off int, compression map[string]struct{}) int { func (rr *TALINK) len(off int, compression map[string]struct{}) int {
@ -608,7 +639,7 @@ func (rr *TLSA) len(off int, compression map[string]struct{}) int {
l++ // Usage l++ // Usage
l++ // Selector l++ // Selector
l++ // MatchingType l++ // MatchingType
l += len(rr.Certificate)/2 + 1 l += len(rr.Certificate) / 2
return l return l
} }
func (rr *TSIG) len(off int, compression map[string]struct{}) int { func (rr *TSIG) len(off int, compression map[string]struct{}) int {
@ -667,6 +698,13 @@ func (rr *AFSDB) copy() RR {
func (rr *ANY) copy() RR { func (rr *ANY) copy() RR {
return &ANY{rr.Hdr} return &ANY{rr.Hdr}
} }
func (rr *APL) copy() RR {
Prefixes := make([]APLPrefix, len(rr.Prefixes))
for i, e := range rr.Prefixes {
Prefixes[i] = e.copy()
}
return &APL{rr.Hdr, Prefixes}
}
func (rr *AVC) copy() RR { 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)
@ -675,6 +713,12 @@ func (rr *AVC) copy() RR {
func (rr *CAA) copy() RR { func (rr *CAA) copy() RR {
return &CAA{rr.Hdr, rr.Flag, rr.Tag, rr.Value} return &CAA{rr.Hdr, rr.Flag, rr.Tag, rr.Value}
} }
func (rr *CDNSKEY) copy() RR {
return &CDNSKEY{*rr.DNSKEY.copy().(*DNSKEY)}
}
func (rr *CDS) copy() RR {
return &CDS{*rr.DS.copy().(*DS)}
}
func (rr *CERT) copy() RR { func (rr *CERT) copy() RR {
return &CERT{rr.Hdr, rr.Type, rr.KeyTag, rr.Algorithm, rr.Certificate} return &CERT{rr.Hdr, rr.Type, rr.KeyTag, rr.Algorithm, rr.Certificate}
} }
@ -689,6 +733,9 @@ func (rr *CSYNC) copy() RR {
func (rr *DHCID) copy() RR { func (rr *DHCID) copy() RR {
return &DHCID{rr.Hdr, rr.Digest} return &DHCID{rr.Hdr, rr.Digest}
} }
func (rr *DLV) copy() RR {
return &DLV{*rr.DS.copy().(*DS)}
}
func (rr *DNAME) copy() RR { func (rr *DNAME) copy() RR {
return &DNAME{rr.Hdr, rr.Target} return &DNAME{rr.Hdr, rr.Target}
} }
@ -721,6 +768,12 @@ func (rr *HIP) copy() RR {
copy(RendezvousServers, rr.RendezvousServers) copy(RendezvousServers, rr.RendezvousServers)
return &HIP{rr.Hdr, rr.HitLength, rr.PublicKeyAlgorithm, rr.PublicKeyLength, rr.Hit, rr.PublicKey, RendezvousServers} return &HIP{rr.Hdr, rr.HitLength, rr.PublicKeyAlgorithm, rr.PublicKeyLength, rr.Hit, rr.PublicKey, RendezvousServers}
} }
func (rr *HTTPS) copy() RR {
return &HTTPS{*rr.SVCB.copy().(*SVCB)}
}
func (rr *KEY) copy() RR {
return &KEY{*rr.DNSKEY.copy().(*DNSKEY)}
}
func (rr *KX) copy() RR { func (rr *KX) copy() RR {
return &KX{rr.Hdr, rr.Preference, rr.Exchanger} return &KX{rr.Hdr, rr.Preference, rr.Exchanger}
} }
@ -824,6 +877,9 @@ func (rr *RRSIG) copy() RR {
func (rr *RT) copy() RR { func (rr *RT) copy() RR {
return &RT{rr.Hdr, rr.Preference, rr.Host} return &RT{rr.Hdr, rr.Preference, rr.Host}
} }
func (rr *SIG) copy() RR {
return &SIG{*rr.RRSIG.copy().(*RRSIG)}
}
func (rr *SMIMEA) copy() RR { func (rr *SMIMEA) copy() RR {
return &SMIMEA{rr.Hdr, rr.Usage, rr.Selector, rr.MatchingType, rr.Certificate} return &SMIMEA{rr.Hdr, rr.Usage, rr.Selector, rr.MatchingType, rr.Certificate}
} }
@ -841,6 +897,13 @@ func (rr *SRV) copy() RR {
func (rr *SSHFP) copy() RR { func (rr *SSHFP) copy() RR {
return &SSHFP{rr.Hdr, rr.Algorithm, rr.Type, rr.FingerPrint} return &SSHFP{rr.Hdr, rr.Algorithm, rr.Type, rr.FingerPrint}
} }
func (rr *SVCB) copy() RR {
Value := make([]SVCBKeyValue, len(rr.Value))
for i, e := range rr.Value {
Value[i] = e.copy()
}
return &SVCB{rr.Hdr, rr.Priority, rr.Target, Value}
}
func (rr *TA) copy() RR { func (rr *TA) copy() RR {
return &TA{rr.Hdr, rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest} return &TA{rr.Hdr, rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest}
} }

4
vendor/modules.txt vendored
View File

@ -783,10 +783,10 @@ github.com/mailru/easyjson/jwriter
# github.com/matttproud/golang_protobuf_extensions => github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 # github.com/matttproud/golang_protobuf_extensions => github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369
github.com/matttproud/golang_protobuf_extensions/pbutil github.com/matttproud/golang_protobuf_extensions/pbutil
# github.com/mholt/certmagic => github.com/mholt/certmagic v0.6.2-0.20190624175158-6a42ef9fe8c2 # github.com/mholt/certmagic => github.com/mholt/certmagic v0.6.2-0.20190624175158-6a42ef9fe8c2
# github.com/miekg/dns v1.1.4 => github.com/miekg/dns v1.1.4 # github.com/miekg/dns v1.1.35 => github.com/miekg/dns v1.1.35
## explicit ## explicit
github.com/miekg/dns github.com/miekg/dns
# github.com/miekg/dns => github.com/miekg/dns v1.1.4 # github.com/miekg/dns => github.com/miekg/dns v1.1.35
# github.com/mindprince/gonvml v0.0.0-20190828220739-9ebdce4bb989 => github.com/mindprince/gonvml v0.0.0-20190828220739-9ebdce4bb989 # github.com/mindprince/gonvml v0.0.0-20190828220739-9ebdce4bb989 => github.com/mindprince/gonvml v0.0.0-20190828220739-9ebdce4bb989
github.com/mindprince/gonvml github.com/mindprince/gonvml
# github.com/mindprince/gonvml => github.com/mindprince/gonvml v0.0.0-20190828220739-9ebdce4bb989 # github.com/mindprince/gonvml => github.com/mindprince/gonvml v0.0.0-20190828220739-9ebdce4bb989