Godeps changes for kube-dns
This commit is contained in:
parent
ae7809d71a
commit
d2dd4911ca
6
Godeps/Godeps.json
generated
6
Godeps/Godeps.json
generated
@ -1335,7 +1335,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/miekg/dns",
|
"ImportPath": "github.com/miekg/dns",
|
||||||
"Rev": "3f504e8dabd5d562e997d19ce0200aa41973e1b2"
|
"Rev": "c2b278e70f35902fd68b54b69238cd10bb1b7451"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/mistifyio/go-zfs",
|
"ImportPath": "github.com/mistifyio/go-zfs",
|
||||||
@ -1779,8 +1779,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/skynetservices/skydns/msg",
|
"ImportPath": "github.com/skynetservices/skydns/msg",
|
||||||
"Comment": "2.5.1a",
|
"Comment": "2.5.3a-32-gf7b6fb7",
|
||||||
"Rev": "1be70b5b8aa07acccd972146d84011b670af88b4"
|
"Rev": "f7b6fb74bcfab300b4e7e0e27b1fe6c0ed555f78"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/spf13/cobra",
|
"ImportPath": "github.com/spf13/cobra",
|
||||||
|
22
vendor/github.com/miekg/dns/.travis.yml
generated
vendored
22
vendor/github.com/miekg/dns/.travis.yml
generated
vendored
@ -1,21 +1,7 @@
|
|||||||
language: go
|
language: go
|
||||||
|
sudo: false
|
||||||
go:
|
go:
|
||||||
- 1.2
|
- 1.5
|
||||||
- 1.3
|
- 1.6
|
||||||
env:
|
|
||||||
# "gvm update" resets GOOS and GOARCH environment variable, workaround it by setting
|
|
||||||
# BUILD_GOOS and BUILD_GOARCH and overriding GOARCH and GOOS in the build script
|
|
||||||
global:
|
|
||||||
- BUILD_GOARCH=amd64
|
|
||||||
matrix:
|
|
||||||
- BUILD_GOOS=linux
|
|
||||||
- BUILD_GOOS=darwin
|
|
||||||
- BUILD_GOOS=windows
|
|
||||||
script:
|
script:
|
||||||
- gvm cross $BUILD_GOOS $BUILD_GOARCH
|
- go test -race -v -bench=.
|
||||||
- GOARCH=$BUILD_GOARCH GOOS=$BUILD_GOOS go build
|
|
||||||
|
|
||||||
# only test on linux
|
|
||||||
# also specify -short; the crypto tests fail in weird ways *sometimes*
|
|
||||||
# See issue #151
|
|
||||||
- if [ $BUILD_GOOS == "linux" ]; then GOARCH=$BUILD_GOARCH GOOS=$BUILD_GOOS go test -short -bench=.; fi
|
|
||||||
|
43
vendor/github.com/miekg/dns/README.md
generated
vendored
43
vendor/github.com/miekg/dns/README.md
generated
vendored
@ -10,9 +10,9 @@ If there is stuff you should know as a DNS programmer there isn't a convenience
|
|||||||
function for it. Server side and client side programming is supported, i.e. you
|
function for it. Server side and client side programming is supported, i.e. you
|
||||||
can build servers and resolvers with it.
|
can build servers and resolvers with it.
|
||||||
|
|
||||||
If you like this, you may also be interested in:
|
We try to keep the "master" branch as sane as possible and at the bleeding edge
|
||||||
|
of standards, avoiding breaking changes wherever reasonable. We support the last
|
||||||
* https://github.com/miekg/unbound -- Go wrapper for the Unbound resolver.
|
two versions of Go, currently: 1.4 and 1.5.
|
||||||
|
|
||||||
# Goals
|
# Goals
|
||||||
|
|
||||||
@ -24,6 +24,7 @@ If you like this, you may also be interested in:
|
|||||||
|
|
||||||
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://cloudflare.com
|
||||||
* https://github.com/abh/geodns
|
* https://github.com/abh/geodns
|
||||||
* http://www.statdns.com/
|
* http://www.statdns.com/
|
||||||
* http://www.dnsinspect.com/
|
* http://www.dnsinspect.com/
|
||||||
@ -32,8 +33,21 @@ A not-so-up-to-date-list-that-may-be-actually-current:
|
|||||||
* https://github.com/fcambus/rrda
|
* https://github.com/fcambus/rrda
|
||||||
* https://github.com/kenshinx/godns
|
* https://github.com/kenshinx/godns
|
||||||
* https://github.com/skynetservices/skydns
|
* https://github.com/skynetservices/skydns
|
||||||
|
* https://github.com/hashicorp/consul
|
||||||
* https://github.com/DevelopersPL/godnsagent
|
* https://github.com/DevelopersPL/godnsagent
|
||||||
* https://github.com/duedil-ltd/discodns
|
* https://github.com/duedil-ltd/discodns
|
||||||
|
* https://github.com/StalkR/dns-reverse-proxy
|
||||||
|
* https://github.com/tianon/rawdns
|
||||||
|
* https://mesosphere.github.io/mesos-dns/
|
||||||
|
* https://pulse.turbobytes.com/
|
||||||
|
* https://play.google.com/store/apps/details?id=com.turbobytes.dig
|
||||||
|
* https://github.com/fcambus/statzone
|
||||||
|
* https://github.com/benschw/dns-clb-go
|
||||||
|
* https://github.com/corny/dnscheck for http://public-dns.info/
|
||||||
|
* https://namesmith.io
|
||||||
|
* https://github.com/miekg/unbound
|
||||||
|
* https://github.com/miekg/exdns
|
||||||
|
* https://dnslookup.org
|
||||||
|
|
||||||
Send pull request if you want to be listed here.
|
Send pull request if you want to be listed here.
|
||||||
|
|
||||||
@ -50,6 +64,7 @@ Send pull request if you want to be listed here.
|
|||||||
* EDNS0, NSID;
|
* EDNS0, NSID;
|
||||||
* AXFR/IXFR;
|
* AXFR/IXFR;
|
||||||
* TSIG, SIG(0);
|
* TSIG, SIG(0);
|
||||||
|
* DNS over TLS: optional encrypted connection between client and server;
|
||||||
* DNS name compression;
|
* DNS name compression;
|
||||||
* Depends only on the standard library.
|
* Depends only on the standard library.
|
||||||
|
|
||||||
@ -67,7 +82,7 @@ correctly, the following should work:
|
|||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
A short "how to use the API" is at the beginning of dns.go (this also will show
|
A short "how to use the API" is at the beginning of doc.go (this also will show
|
||||||
when you call `godoc github.com/miekg/dns`).
|
when you call `godoc github.com/miekg/dns`).
|
||||||
|
|
||||||
Example programs can be found in the `github.com/miekg/exdns` repository.
|
Example programs can be found in the `github.com/miekg/exdns` repository.
|
||||||
@ -77,7 +92,7 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
|
|||||||
*all of them*
|
*all of them*
|
||||||
|
|
||||||
* 103{4,5} - DNS standard
|
* 103{4,5} - DNS standard
|
||||||
* 1348 - NSAP record
|
* 1348 - NSAP record (removed the record)
|
||||||
* 1982 - Serial Arithmetic
|
* 1982 - Serial Arithmetic
|
||||||
* 1876 - LOC record
|
* 1876 - LOC record
|
||||||
* 1995 - IXFR
|
* 1995 - IXFR
|
||||||
@ -95,7 +110,8 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
|
|||||||
* 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
|
||||||
* 3597 - Unkown RRs
|
* 3597 - Unknown RRs
|
||||||
|
* 4025 - IPSECKEY
|
||||||
* 403{3,4,5} - DNSSEC + validation functions
|
* 403{3,4,5} - DNSSEC + validation functions
|
||||||
* 4255 - SSHFP record
|
* 4255 - SSHFP record
|
||||||
* 4343 - Case insensitivity
|
* 4343 - Case insensitivity
|
||||||
@ -114,13 +130,16 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
|
|||||||
* 6605 - ECDSA
|
* 6605 - ECDSA
|
||||||
* 6725 - IANA Registry Update
|
* 6725 - IANA Registry Update
|
||||||
* 6742 - ILNP DNS
|
* 6742 - ILNP DNS
|
||||||
|
* 6840 - Clarifications and Implementation Notes for DNS Security
|
||||||
|
* 6844 - CAA record
|
||||||
* 6891 - EDNS0 update
|
* 6891 - EDNS0 update
|
||||||
* 6895 - DNS IANA considerations
|
* 6895 - DNS IANA considerations
|
||||||
* 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
|
||||||
* xxxx - URI record (draft)
|
* 7553 - URI record
|
||||||
* xxxx - EDNS0 DNS Update Lease (draft)
|
* xxxx - EDNS0 DNS Update Lease (draft)
|
||||||
|
* yyyy - DNS over TLS: Initiation and Performance Considerations (draft)
|
||||||
|
|
||||||
## Loosely based upon
|
## Loosely based upon
|
||||||
|
|
||||||
@ -132,9 +151,7 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
|
|||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
* privatekey.Precompute() when signing?
|
* privatekey.Precompute() when signing?
|
||||||
* Last remaining RRs: APL, ATMA, A6 and NXT;
|
* Last remaining RRs: APL, ATMA, A6, NSAP and NXT.
|
||||||
* Missing in parsing: ISDN, UNSPEC, ATMA;
|
* Missing in parsing: ISDN, UNSPEC, NSAP and ATMA.
|
||||||
* CAA parsing is broken;
|
* NSEC(3) cover/match/closest enclose.
|
||||||
* NSEC(3) cover/match/closest enclose;
|
* Replies with TC bit are not parsed to the end.
|
||||||
* Replies with TC bit are not parsed to the end;
|
|
||||||
* Create IsMsg to validate a message before fully parsing it.
|
|
||||||
|
297
vendor/github.com/miekg/dns/client.go
generated
vendored
297
vendor/github.com/miekg/dns/client.go
generated
vendored
@ -4,12 +4,13 @@ package dns
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/tls"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const dnsTimeout time.Duration = 2 * 1e9
|
const dnsTimeout time.Duration = 2 * time.Second
|
||||||
const tcpIdleTimeout time.Duration = 8 * time.Second
|
const tcpIdleTimeout time.Duration = 8 * time.Second
|
||||||
|
|
||||||
// A Conn represents a connection to a DNS server.
|
// A Conn represents a connection to a DNS server.
|
||||||
@ -24,11 +25,12 @@ type Conn struct {
|
|||||||
|
|
||||||
// A Client defines parameters for a DNS client.
|
// A Client defines parameters for a DNS client.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
Net string // if "tcp" a TCP query will be initiated, otherwise an UDP one (default is "" for UDP)
|
Net string // if "tcp" or "tcp-tls" (DNS over TLS) a TCP query will be initiated, otherwise an UDP one (default is "" for UDP)
|
||||||
UDPSize uint16 // minimum receive buffer for UDP messages
|
UDPSize uint16 // minimum receive buffer for UDP messages
|
||||||
DialTimeout time.Duration // net.DialTimeout (ns), defaults to 2 * 1e9
|
TLSConfig *tls.Config // TLS connection configuration
|
||||||
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections (ns), defaults to 2 * 1e9
|
DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds
|
||||||
WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections (ns), defaults to 2 * 1e9
|
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds
|
||||||
|
WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds
|
||||||
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified
|
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified
|
||||||
SingleInflight bool // if true suppress multiple outstanding queries for the same Qname, Qtype and Qclass
|
SingleInflight bool // if true suppress multiple outstanding queries for the same Qname, Qtype and Qclass
|
||||||
group singleflight
|
group singleflight
|
||||||
@ -37,14 +39,7 @@ type Client struct {
|
|||||||
// Exchange performs a synchronous UDP query. It sends the message m to the address
|
// Exchange performs a synchronous UDP query. It sends the message m to the address
|
||||||
// contained in a and waits for an reply. Exchange does not retry a failed query, nor
|
// contained in a and waits for an reply. Exchange does not retry a failed query, nor
|
||||||
// will it fall back to TCP in case of truncation.
|
// will it fall back to TCP in case of truncation.
|
||||||
// If you need to send a DNS message on an already existing connection, you can use the
|
// See client.Exchange for more information on setting larger buffer sizes.
|
||||||
// following:
|
|
||||||
//
|
|
||||||
// co := &dns.Conn{Conn: c} // c is your net.Conn
|
|
||||||
// co.WriteMsg(m)
|
|
||||||
// in, err := co.ReadMsg()
|
|
||||||
// co.Close()
|
|
||||||
//
|
|
||||||
func Exchange(m *Msg, a string) (r *Msg, err error) {
|
func Exchange(m *Msg, a string) (r *Msg, err error) {
|
||||||
var co *Conn
|
var co *Conn
|
||||||
co, err = DialTimeout("udp", a, dnsTimeout)
|
co, err = DialTimeout("udp", a, dnsTimeout)
|
||||||
@ -53,12 +48,23 @@ func Exchange(m *Msg, a string) (r *Msg, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
defer co.Close()
|
defer co.Close()
|
||||||
co.SetReadDeadline(time.Now().Add(dnsTimeout))
|
|
||||||
|
opt := m.IsEdns0()
|
||||||
|
// If EDNS0 is used use that for size.
|
||||||
|
if opt != nil && opt.UDPSize() >= MinMsgSize {
|
||||||
|
co.UDPSize = opt.UDPSize()
|
||||||
|
}
|
||||||
|
|
||||||
co.SetWriteDeadline(time.Now().Add(dnsTimeout))
|
co.SetWriteDeadline(time.Now().Add(dnsTimeout))
|
||||||
if err = co.WriteMsg(m); err != nil {
|
if err = co.WriteMsg(m); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
co.SetReadDeadline(time.Now().Add(dnsTimeout))
|
||||||
r, err = co.ReadMsg()
|
r, err = co.ReadMsg()
|
||||||
|
if err == nil && r.Id != m.Id {
|
||||||
|
err = ErrId
|
||||||
|
}
|
||||||
return r, err
|
return r, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,6 +85,9 @@ func ExchangeConn(c net.Conn, m *Msg) (r *Msg, err error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
r, err = co.ReadMsg()
|
r, err = co.ReadMsg()
|
||||||
|
if err == nil && r.Id != m.Id {
|
||||||
|
err = ErrId
|
||||||
|
}
|
||||||
return r, err
|
return r, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,6 +99,10 @@ func ExchangeConn(c net.Conn, m *Msg) (r *Msg, err error) {
|
|||||||
//
|
//
|
||||||
// Exchange does not retry a failed query, nor will it fall back to TCP in
|
// Exchange does not retry a failed query, nor will it fall back to TCP in
|
||||||
// case of truncation.
|
// case of truncation.
|
||||||
|
// It is up to the caller to create a message that allows for larger responses to be
|
||||||
|
// returned. Specifically this means adding an EDNS0 OPT RR that will advertise a larger
|
||||||
|
// buffer, see SetEdns0. Messsages without an OPT RR will fallback to the historic limit
|
||||||
|
// of 512 bytes.
|
||||||
func (c *Client) Exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
|
func (c *Client) Exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
|
||||||
if !c.SingleInflight {
|
if !c.SingleInflight {
|
||||||
return c.exchange(m, a)
|
return c.exchange(m, a)
|
||||||
@ -115,31 +128,59 @@ func (c *Client) Exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro
|
|||||||
return r, rtt, nil
|
return r, rtt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
|
func (c *Client) dialTimeout() time.Duration {
|
||||||
timeout := dnsTimeout
|
|
||||||
var co *Conn
|
|
||||||
if c.DialTimeout != 0 {
|
if c.DialTimeout != 0 {
|
||||||
timeout = c.DialTimeout
|
return c.DialTimeout
|
||||||
}
|
}
|
||||||
if c.Net == "" {
|
return dnsTimeout
|
||||||
co, err = DialTimeout("udp", a, timeout)
|
}
|
||||||
|
|
||||||
|
func (c *Client) readTimeout() time.Duration {
|
||||||
|
if c.ReadTimeout != 0 {
|
||||||
|
return c.ReadTimeout
|
||||||
|
}
|
||||||
|
return dnsTimeout
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) writeTimeout() time.Duration {
|
||||||
|
if c.WriteTimeout != 0 {
|
||||||
|
return c.WriteTimeout
|
||||||
|
}
|
||||||
|
return dnsTimeout
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
|
||||||
|
var co *Conn
|
||||||
|
network := "udp"
|
||||||
|
tls := false
|
||||||
|
|
||||||
|
switch c.Net {
|
||||||
|
case "tcp-tls":
|
||||||
|
network = "tcp"
|
||||||
|
tls = true
|
||||||
|
case "tcp4-tls":
|
||||||
|
network = "tcp4"
|
||||||
|
tls = true
|
||||||
|
case "tcp6-tls":
|
||||||
|
network = "tcp6"
|
||||||
|
tls = true
|
||||||
|
default:
|
||||||
|
if c.Net != "" {
|
||||||
|
network = c.Net
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if tls {
|
||||||
|
co, err = DialTimeoutWithTLS(network, a, c.TLSConfig, c.dialTimeout())
|
||||||
} else {
|
} else {
|
||||||
co, err = DialTimeout(c.Net, a, timeout)
|
co, err = DialTimeout(network, a, c.dialTimeout())
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
timeout = dnsTimeout
|
|
||||||
if c.ReadTimeout != 0 {
|
|
||||||
timeout = c.ReadTimeout
|
|
||||||
}
|
|
||||||
co.SetReadDeadline(time.Now().Add(timeout))
|
|
||||||
timeout = dnsTimeout
|
|
||||||
if c.WriteTimeout != 0 {
|
|
||||||
timeout = c.WriteTimeout
|
|
||||||
}
|
|
||||||
co.SetWriteDeadline(time.Now().Add(timeout))
|
|
||||||
defer co.Close()
|
defer co.Close()
|
||||||
|
|
||||||
opt := m.IsEdns0()
|
opt := m.IsEdns0()
|
||||||
// If EDNS0 is used use that for size.
|
// If EDNS0 is used use that for size.
|
||||||
if opt != nil && opt.UDPSize() >= MinMsgSize {
|
if opt != nil && opt.UDPSize() >= MinMsgSize {
|
||||||
@ -149,11 +190,18 @@ func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro
|
|||||||
if opt == nil && c.UDPSize >= MinMsgSize {
|
if opt == nil && c.UDPSize >= MinMsgSize {
|
||||||
co.UDPSize = c.UDPSize
|
co.UDPSize = c.UDPSize
|
||||||
}
|
}
|
||||||
|
|
||||||
co.TsigSecret = c.TsigSecret
|
co.TsigSecret = c.TsigSecret
|
||||||
|
co.SetWriteDeadline(time.Now().Add(c.writeTimeout()))
|
||||||
if err = co.WriteMsg(m); err != nil {
|
if err = co.WriteMsg(m); err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
co.SetReadDeadline(time.Now().Add(c.readTimeout()))
|
||||||
r, err = co.ReadMsg()
|
r, err = co.ReadMsg()
|
||||||
|
if err == nil && r.Id != m.Id {
|
||||||
|
err = ErrId
|
||||||
|
}
|
||||||
return r, co.rtt, err
|
return r, co.rtt, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,26 +209,21 @@ func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro
|
|||||||
// If the received message contains a TSIG record the transaction
|
// If the received message contains a TSIG record the transaction
|
||||||
// signature is verified.
|
// signature is verified.
|
||||||
func (co *Conn) ReadMsg() (*Msg, error) {
|
func (co *Conn) ReadMsg() (*Msg, error) {
|
||||||
var p []byte
|
p, err := co.ReadMsgHeader(nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
m := new(Msg)
|
m := new(Msg)
|
||||||
if _, ok := co.Conn.(*net.TCPConn); ok {
|
|
||||||
p = make([]byte, MaxMsgSize)
|
|
||||||
} else {
|
|
||||||
if co.UDPSize >= 512 {
|
|
||||||
p = make([]byte, co.UDPSize)
|
|
||||||
} else {
|
|
||||||
p = make([]byte, MinMsgSize)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
n, err := co.Read(p)
|
|
||||||
if err != nil && n == 0 {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
p = p[:n]
|
|
||||||
if err := m.Unpack(p); err != nil {
|
if err := m.Unpack(p); err != nil {
|
||||||
|
// If ErrTruncated was returned, we still want to allow the user to use
|
||||||
|
// the message, but naively they can just check err if they don't want
|
||||||
|
// to use a truncated message
|
||||||
|
if err == ErrTruncated {
|
||||||
|
return m, err
|
||||||
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
co.rtt = time.Since(co.t)
|
|
||||||
if t := m.IsTsig(); t != nil {
|
if t := m.IsTsig(); t != nil {
|
||||||
if _, ok := co.TsigSecret[t.Hdr.Name]; !ok {
|
if _, ok := co.TsigSecret[t.Hdr.Name]; !ok {
|
||||||
return m, ErrSecret
|
return m, ErrSecret
|
||||||
@ -191,6 +234,86 @@ func (co *Conn) ReadMsg() (*Msg, error) {
|
|||||||
return m, err
|
return m, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadMsgHeader reads a DNS message, parses and populates hdr (when hdr is not nil).
|
||||||
|
// Returns message as a byte slice to be parsed with Msg.Unpack later on.
|
||||||
|
// Note that error handling on the message body is not possible as only the header is parsed.
|
||||||
|
func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) {
|
||||||
|
var (
|
||||||
|
p []byte
|
||||||
|
n int
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
switch t := co.Conn.(type) {
|
||||||
|
case *net.TCPConn, *tls.Conn:
|
||||||
|
r := t.(io.Reader)
|
||||||
|
|
||||||
|
// First two bytes specify the length of the entire message.
|
||||||
|
l, err := tcpMsgLen(r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
p = make([]byte, l)
|
||||||
|
n, err = tcpRead(r, p)
|
||||||
|
co.rtt = time.Since(co.t)
|
||||||
|
default:
|
||||||
|
if co.UDPSize > MinMsgSize {
|
||||||
|
p = make([]byte, co.UDPSize)
|
||||||
|
} else {
|
||||||
|
p = make([]byte, MinMsgSize)
|
||||||
|
}
|
||||||
|
n, err = co.Read(p)
|
||||||
|
co.rtt = time.Since(co.t)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if n < headerSize {
|
||||||
|
return nil, ErrShortRead
|
||||||
|
}
|
||||||
|
|
||||||
|
p = p[:n]
|
||||||
|
if hdr != nil {
|
||||||
|
if _, err = UnpackStruct(hdr, p, 0); err != nil {
|
||||||
|
return nil, 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
|
||||||
|
}
|
||||||
|
if n != 2 {
|
||||||
|
return 0, ErrShortRead
|
||||||
|
}
|
||||||
|
l, _ := unpackUint16(p, 0)
|
||||||
|
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 {
|
||||||
@ -199,32 +322,18 @@ func (co *Conn) Read(p []byte) (n int, err error) {
|
|||||||
if len(p) < 2 {
|
if len(p) < 2 {
|
||||||
return 0, io.ErrShortBuffer
|
return 0, io.ErrShortBuffer
|
||||||
}
|
}
|
||||||
if t, ok := co.Conn.(*net.TCPConn); ok {
|
switch t := co.Conn.(type) {
|
||||||
n, err = t.Read(p[0:2])
|
case *net.TCPConn, *tls.Conn:
|
||||||
if err != nil || n != 2 {
|
r := t.(io.Reader)
|
||||||
return n, err
|
|
||||||
|
l, err := tcpMsgLen(r)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
}
|
}
|
||||||
l, _ := unpackUint16(p[0:2], 0)
|
if l > len(p) {
|
||||||
if l == 0 {
|
|
||||||
return 0, ErrShortRead
|
|
||||||
}
|
|
||||||
if int(l) > len(p) {
|
|
||||||
return int(l), io.ErrShortBuffer
|
return int(l), io.ErrShortBuffer
|
||||||
}
|
}
|
||||||
n, err = t.Read(p[:l])
|
return tcpRead(r, p[:l])
|
||||||
if err != nil {
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
i := n
|
|
||||||
for i < int(l) {
|
|
||||||
j, err := t.Read(p[i:int(l)])
|
|
||||||
if err != nil {
|
|
||||||
return i, err
|
|
||||||
}
|
|
||||||
i += j
|
|
||||||
}
|
|
||||||
n = i
|
|
||||||
return n, err
|
|
||||||
}
|
}
|
||||||
// UDP connection
|
// UDP connection
|
||||||
n, err = co.Conn.Read(p)
|
n, err = co.Conn.Read(p)
|
||||||
@ -234,7 +343,7 @@ func (co *Conn) Read(p []byte) (n int, err error) {
|
|||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteMsg sends a message throught the connection co.
|
// WriteMsg sends a message through the connection co.
|
||||||
// If the message m contains a TSIG record the transaction
|
// If the message m contains a TSIG record the transaction
|
||||||
// signature is calculated.
|
// signature is calculated.
|
||||||
func (co *Conn) WriteMsg(m *Msg) (err error) {
|
func (co *Conn) WriteMsg(m *Msg) (err error) {
|
||||||
@ -245,7 +354,7 @@ func (co *Conn) WriteMsg(m *Msg) (err error) {
|
|||||||
return ErrSecret
|
return ErrSecret
|
||||||
}
|
}
|
||||||
out, mac, err = TsigGenerate(m, co.TsigSecret[t.Hdr.Name], co.tsigRequestMAC, false)
|
out, mac, err = TsigGenerate(m, co.TsigSecret[t.Hdr.Name], co.tsigRequestMAC, false)
|
||||||
// Set for the next read, allthough only used in zone transfers
|
// Set for the next read, although only used in zone transfers
|
||||||
co.tsigRequestMAC = mac
|
co.tsigRequestMAC = mac
|
||||||
} else {
|
} else {
|
||||||
out, err = m.Pack()
|
out, err = m.Pack()
|
||||||
@ -262,7 +371,10 @@ 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) (n int, err error) {
|
||||||
if t, ok := co.Conn.(*net.TCPConn); ok {
|
switch t := co.Conn.(type) {
|
||||||
|
case *net.TCPConn, *tls.Conn:
|
||||||
|
w := t.(io.Writer)
|
||||||
|
|
||||||
lp := len(p)
|
lp := len(p)
|
||||||
if lp < 2 {
|
if lp < 2 {
|
||||||
return 0, io.ErrShortBuffer
|
return 0, io.ErrShortBuffer
|
||||||
@ -273,7 +385,7 @@ func (co *Conn) Write(p []byte) (n int, err error) {
|
|||||||
l := make([]byte, 2, lp+2)
|
l := make([]byte, 2, lp+2)
|
||||||
l[0], l[1] = packUint16(uint16(lp))
|
l[0], l[1] = packUint16(uint16(lp))
|
||||||
p = append(l, p...)
|
p = append(l, p...)
|
||||||
n, err := io.Copy(t, bytes.NewReader(p))
|
n, err := io.Copy(w, bytes.NewReader(p))
|
||||||
return int(n), err
|
return int(n), err
|
||||||
}
|
}
|
||||||
n, err = co.Conn.(*net.UDPConn).Write(p)
|
n, err = co.Conn.(*net.UDPConn).Write(p)
|
||||||
@ -290,7 +402,7 @@ func Dial(network, address string) (conn *Conn, err error) {
|
|||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dialtimeout acts like Dial but takes a timeout.
|
// DialTimeout acts like Dial but takes a timeout.
|
||||||
func DialTimeout(network, address string, timeout time.Duration) (conn *Conn, err error) {
|
func DialTimeout(network, address string, timeout time.Duration) (conn *Conn, err error) {
|
||||||
conn = new(Conn)
|
conn = new(Conn)
|
||||||
conn.Conn, err = net.DialTimeout(network, address, timeout)
|
conn.Conn, err = net.DialTimeout(network, address, timeout)
|
||||||
@ -300,20 +412,25 @@ func DialTimeout(network, address string, timeout time.Duration) (conn *Conn, er
|
|||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close implements the net.Conn Close method.
|
// DialWithTLS connects to the address on the named network with TLS.
|
||||||
func (co *Conn) Close() error { return co.Conn.Close() }
|
func DialWithTLS(network, address string, tlsConfig *tls.Config) (conn *Conn, err error) {
|
||||||
|
conn = new(Conn)
|
||||||
|
conn.Conn, err = tls.Dial(network, address, tlsConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
// LocalAddr implements the net.Conn LocalAddr method.
|
// DialTimeoutWithTLS acts like DialWithTLS but takes a timeout.
|
||||||
func (co *Conn) LocalAddr() net.Addr { return co.Conn.LocalAddr() }
|
func DialTimeoutWithTLS(network, address string, tlsConfig *tls.Config, timeout time.Duration) (conn *Conn, err error) {
|
||||||
|
var dialer net.Dialer
|
||||||
|
dialer.Timeout = timeout
|
||||||
|
|
||||||
// RemoteAddr implements the net.Conn RemoteAddr method.
|
conn = new(Conn)
|
||||||
func (co *Conn) RemoteAddr() net.Addr { return co.Conn.RemoteAddr() }
|
conn.Conn, err = tls.DialWithDialer(&dialer, network, address, tlsConfig)
|
||||||
|
if err != nil {
|
||||||
// SetDeadline implements the net.Conn SetDeadline method.
|
return nil, err
|
||||||
func (co *Conn) SetDeadline(t time.Time) error { return co.Conn.SetDeadline(t) }
|
}
|
||||||
|
return conn, nil
|
||||||
// SetReadDeadline implements the net.Conn SetReadDeadline method.
|
}
|
||||||
func (co *Conn) SetReadDeadline(t time.Time) error { return co.Conn.SetReadDeadline(t) }
|
|
||||||
|
|
||||||
// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
|
|
||||||
func (co *Conn) SetWriteDeadline(t time.Time) error { return co.Conn.SetWriteDeadline(t) }
|
|
||||||
|
11
vendor/github.com/miekg/dns/clientconfig.go
generated
vendored
11
vendor/github.com/miekg/dns/clientconfig.go
generated
vendored
@ -7,7 +7,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Wraps the contents of the /etc/resolv.conf.
|
// ClientConfig wraps the contents of the /etc/resolv.conf file.
|
||||||
type ClientConfig struct {
|
type ClientConfig struct {
|
||||||
Servers []string // servers to use
|
Servers []string // servers to use
|
||||||
Search []string // suffixes to append to local name
|
Search []string // suffixes to append to local name
|
||||||
@ -26,14 +26,19 @@ func ClientConfigFromFile(resolvconf string) (*ClientConfig, error) {
|
|||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
c := new(ClientConfig)
|
c := new(ClientConfig)
|
||||||
b := bufio.NewReader(file)
|
scanner := bufio.NewScanner(file)
|
||||||
c.Servers = make([]string, 0)
|
c.Servers = make([]string, 0)
|
||||||
c.Search = make([]string, 0)
|
c.Search = make([]string, 0)
|
||||||
c.Port = "53"
|
c.Port = "53"
|
||||||
c.Ndots = 1
|
c.Ndots = 1
|
||||||
c.Timeout = 5
|
c.Timeout = 5
|
||||||
c.Attempts = 2
|
c.Attempts = 2
|
||||||
for line, ok := b.ReadString('\n'); ok == nil; line, ok = b.ReadString('\n') {
|
|
||||||
|
for scanner.Scan() {
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
line := scanner.Text()
|
||||||
f := strings.Fields(line)
|
f := strings.Fields(line)
|
||||||
if len(f) < 1 {
|
if len(f) < 1 {
|
||||||
continue
|
continue
|
||||||
|
54
vendor/github.com/miekg/dns/defaults.go
generated
vendored
54
vendor/github.com/miekg/dns/defaults.go
generated
vendored
@ -24,7 +24,9 @@ func (dns *Msg) SetReply(request *Msg) *Msg {
|
|||||||
return dns
|
return dns
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetQuestion creates a question message.
|
// SetQuestion creates a question message, it sets the Question
|
||||||
|
// section, generates an Id and sets the RecursionDesired (RD)
|
||||||
|
// bit to true.
|
||||||
func (dns *Msg) SetQuestion(z string, t uint16) *Msg {
|
func (dns *Msg) SetQuestion(z string, t uint16) *Msg {
|
||||||
dns.Id = Id()
|
dns.Id = Id()
|
||||||
dns.RecursionDesired = true
|
dns.RecursionDesired = true
|
||||||
@ -33,7 +35,9 @@ func (dns *Msg) SetQuestion(z string, t uint16) *Msg {
|
|||||||
return dns
|
return dns
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetNotify creates a notify message.
|
// SetNotify creates a notify message, it sets the Question
|
||||||
|
// section, generates an Id and sets the Authoritative (AA)
|
||||||
|
// bit to true.
|
||||||
func (dns *Msg) SetNotify(z string) *Msg {
|
func (dns *Msg) SetNotify(z string) *Msg {
|
||||||
dns.Opcode = OpcodeNotify
|
dns.Opcode = OpcodeNotify
|
||||||
dns.Authoritative = true
|
dns.Authoritative = true
|
||||||
@ -73,13 +77,15 @@ func (dns *Msg) SetUpdate(z string) *Msg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetIxfr creates message for requesting an IXFR.
|
// SetIxfr creates message for requesting an IXFR.
|
||||||
func (dns *Msg) SetIxfr(z string, serial uint32) *Msg {
|
func (dns *Msg) SetIxfr(z string, serial uint32, ns, mbox string) *Msg {
|
||||||
dns.Id = Id()
|
dns.Id = Id()
|
||||||
dns.Question = make([]Question, 1)
|
dns.Question = make([]Question, 1)
|
||||||
dns.Ns = make([]RR, 1)
|
dns.Ns = make([]RR, 1)
|
||||||
s := new(SOA)
|
s := new(SOA)
|
||||||
s.Hdr = RR_Header{z, TypeSOA, ClassINET, defaultTtl, 0}
|
s.Hdr = RR_Header{z, TypeSOA, ClassINET, defaultTtl, 0}
|
||||||
s.Serial = serial
|
s.Serial = serial
|
||||||
|
s.Ns = ns
|
||||||
|
s.Mbox = mbox
|
||||||
dns.Question[0] = Question{z, TypeIXFR, ClassINET}
|
dns.Question[0] = Question{z, TypeIXFR, ClassINET}
|
||||||
dns.Ns[0] = s
|
dns.Ns[0] = s
|
||||||
return dns
|
return dns
|
||||||
@ -144,11 +150,14 @@ func (dns *Msg) IsEdns0() *OPT {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsDomainName checks if s is a valid domainname, it returns
|
// IsDomainName checks if s is a valid domain name, it returns the number of
|
||||||
// the number of labels and true, when a domain name is valid.
|
// labels and true, when a domain name is valid. Note that non fully qualified
|
||||||
// Note that non fully qualified domain name is considered valid, in this case the
|
// domain name is considered valid, in this case the last label is counted in
|
||||||
// last label is counted in the number of labels.
|
// the number of labels. When false is returned the number of labels is not
|
||||||
// When false is returned the number of labels is not defined.
|
// defined. Also note that this function is extremely liberal; almost any
|
||||||
|
// string is a valid domain name as the DNS is 8 bit protocol. It checks if each
|
||||||
|
// label fits in 63 characters, but there is no length check for the entire
|
||||||
|
// string s. I.e. a domain name longer than 255 characters is considered valid.
|
||||||
func IsDomainName(s string) (labels int, ok bool) {
|
func IsDomainName(s string) (labels int, ok bool) {
|
||||||
_, labels, err := packDomainName(s, nil, 0, nil, false)
|
_, labels, err := packDomainName(s, nil, 0, nil, false)
|
||||||
return labels, err == nil
|
return labels, err == nil
|
||||||
@ -182,7 +191,34 @@ func IsFqdn(s string) bool {
|
|||||||
return s[l-1] == '.'
|
return s[l-1] == '.'
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fqdns return the fully qualified domain name from s.
|
// IsRRset checks if a set of RRs is a valid RRset as defined by RFC 2181.
|
||||||
|
// This means the RRs need to have the same type, name, and class. Returns true
|
||||||
|
// if the RR set is valid, otherwise false.
|
||||||
|
func IsRRset(rrset []RR) bool {
|
||||||
|
if len(rrset) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if len(rrset) == 1 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
rrHeader := rrset[0].Header()
|
||||||
|
rrType := rrHeader.Rrtype
|
||||||
|
rrClass := rrHeader.Class
|
||||||
|
rrName := rrHeader.Name
|
||||||
|
|
||||||
|
for _, rr := range rrset[1:] {
|
||||||
|
curRRHeader := rr.Header()
|
||||||
|
if curRRHeader.Rrtype != rrType || curRRHeader.Class != rrClass || curRRHeader.Name != rrName {
|
||||||
|
// Mismatch between the records, so this is not a valid rrset for
|
||||||
|
//signing/verifying
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fqdn return the fully qualified domain name from s.
|
||||||
// If s is already fully qualified, it behaves as the identity function.
|
// If s is already fully qualified, it behaves as the identity function.
|
||||||
func Fqdn(s string) string {
|
func Fqdn(s string) string {
|
||||||
if IsFqdn(s) {
|
if IsFqdn(s) {
|
||||||
|
119
vendor/github.com/miekg/dns/dns.go
generated
vendored
119
vendor/github.com/miekg/dns/dns.go
generated
vendored
@ -1,108 +1,16 @@
|
|||||||
// Package dns implements a full featured interface to the Domain Name System.
|
|
||||||
// Server- and client-side programming is supported.
|
|
||||||
// The package allows complete control over what is send out to the DNS. The package
|
|
||||||
// API follows the less-is-more principle, by presenting a small, clean interface.
|
|
||||||
//
|
|
||||||
// The package dns supports (asynchronous) querying/replying, incoming/outgoing zone transfers,
|
|
||||||
// TSIG, EDNS0, dynamic updates, notifies and DNSSEC validation/signing.
|
|
||||||
// Note that domain names MUST be fully qualified, before sending them, unqualified
|
|
||||||
// names in a message will result in a packing failure.
|
|
||||||
//
|
|
||||||
// Resource records are native types. They are not stored in wire format.
|
|
||||||
// Basic usage pattern for creating a new resource record:
|
|
||||||
//
|
|
||||||
// r := new(dns.MX)
|
|
||||||
// r.Hdr = dns.RR_Header{Name: "miek.nl.", Rrtype: dns.TypeMX, Class: dns.ClassINET, Ttl: 3600}
|
|
||||||
// r.Preference = 10
|
|
||||||
// r.Mx = "mx.miek.nl."
|
|
||||||
//
|
|
||||||
// Or directly from a string:
|
|
||||||
//
|
|
||||||
// mx, err := dns.NewRR("miek.nl. 3600 IN MX 10 mx.miek.nl.")
|
|
||||||
//
|
|
||||||
// Or when the default TTL (3600) and class (IN) suit you:
|
|
||||||
//
|
|
||||||
// mx, err := dns.NewRR("miek.nl. MX 10 mx.miek.nl.")
|
|
||||||
//
|
|
||||||
// Or even:
|
|
||||||
//
|
|
||||||
// mx, err := dns.NewRR("$ORIGIN nl.\nmiek 1H IN MX 10 mx.miek")
|
|
||||||
//
|
|
||||||
// In the DNS messages are exchanged, these messages contain resource
|
|
||||||
// records (sets). Use pattern for creating a message:
|
|
||||||
//
|
|
||||||
// m := new(dns.Msg)
|
|
||||||
// m.SetQuestion("miek.nl.", dns.TypeMX)
|
|
||||||
//
|
|
||||||
// Or when not certain if the domain name is fully qualified:
|
|
||||||
//
|
|
||||||
// m.SetQuestion(dns.Fqdn("miek.nl"), dns.TypeMX)
|
|
||||||
//
|
|
||||||
// The message m is now a message with the question section set to ask
|
|
||||||
// the MX records for the miek.nl. zone.
|
|
||||||
//
|
|
||||||
// The following is slightly more verbose, but more flexible:
|
|
||||||
//
|
|
||||||
// m1 := new(dns.Msg)
|
|
||||||
// m1.Id = dns.Id()
|
|
||||||
// m1.RecursionDesired = true
|
|
||||||
// m1.Question = make([]dns.Question, 1)
|
|
||||||
// m1.Question[0] = dns.Question{"miek.nl.", dns.TypeMX, dns.ClassINET}
|
|
||||||
//
|
|
||||||
// After creating a message it can be send.
|
|
||||||
// Basic use pattern for synchronous querying the DNS at a
|
|
||||||
// server configured on 127.0.0.1 and port 53:
|
|
||||||
//
|
|
||||||
// c := new(dns.Client)
|
|
||||||
// in, rtt, err := c.Exchange(m1, "127.0.0.1:53")
|
|
||||||
//
|
|
||||||
// Suppressing
|
|
||||||
// multiple outstanding queries (with the same question, type and class) is as easy as setting:
|
|
||||||
//
|
|
||||||
// c.SingleInflight = true
|
|
||||||
//
|
|
||||||
// If these "advanced" features are not needed, a simple UDP query can be send,
|
|
||||||
// with:
|
|
||||||
//
|
|
||||||
// in, err := dns.Exchange(m1, "127.0.0.1:53")
|
|
||||||
//
|
|
||||||
// When this functions returns you will get dns message. A dns message consists
|
|
||||||
// out of four sections.
|
|
||||||
// The question section: in.Question, the answer section: in.Answer,
|
|
||||||
// the authority section: in.Ns and the additional section: in.Extra.
|
|
||||||
//
|
|
||||||
// Each of these sections (except the Question section) contain a []RR. Basic
|
|
||||||
// use pattern for accessing the rdata of a TXT RR as the first RR in
|
|
||||||
// the Answer section:
|
|
||||||
//
|
|
||||||
// if t, ok := in.Answer[0].(*dns.TXT); ok {
|
|
||||||
// // do something with t.Txt
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Domain Name and TXT Character String Representations
|
|
||||||
//
|
|
||||||
// Both domain names and TXT character strings are converted to presentation
|
|
||||||
// form both when unpacked and when converted to strings.
|
|
||||||
//
|
|
||||||
// For TXT character strings, tabs, carriage returns and line feeds will be
|
|
||||||
// converted to \t, \r and \n respectively. Back slashes and quotations marks
|
|
||||||
// will be escaped. Bytes below 32 and above 127 will be converted to \DDD
|
|
||||||
// form.
|
|
||||||
//
|
|
||||||
// For domain names, in addition to the above rules brackets, periods,
|
|
||||||
// spaces, semicolons and the at symbol are escaped.
|
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import "strconv"
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
year68 = 1 << 31 // For RFC1982 (Serial Arithmetic) calculations in 32 bits.
|
year68 = 1 << 31 // For RFC1982 (Serial Arithmetic) calculations in 32 bits.
|
||||||
DefaultMsgSize = 4096 // Standard default for larger than 512 bytes.
|
// DefaultMsgSize is the standard default for messages larger than 512 bytes.
|
||||||
MinMsgSize = 512 // Minimal size of a DNS packet.
|
DefaultMsgSize = 4096
|
||||||
MaxMsgSize = 65536 // Largest possible DNS packet.
|
// MinMsgSize is the minimal size of a DNS packet.
|
||||||
defaultTtl = 3600 // Default TTL.
|
MinMsgSize = 512
|
||||||
|
// MaxMsgSize is the largest possible DNS packet.
|
||||||
|
MaxMsgSize = 65535
|
||||||
|
defaultTtl = 3600 // Default internal TTL.
|
||||||
)
|
)
|
||||||
|
|
||||||
// Error represents a DNS error
|
// Error represents a DNS error
|
||||||
@ -124,13 +32,11 @@ type RR interface {
|
|||||||
String() string
|
String() string
|
||||||
// copy returns a copy of the RR
|
// copy returns a copy of the RR
|
||||||
copy() RR
|
copy() RR
|
||||||
// len returns the length (in octects) of the uncompressed RR in wire format.
|
// len returns the length (in octets) of the uncompressed RR in wire format.
|
||||||
len() int
|
len() int
|
||||||
}
|
}
|
||||||
|
|
||||||
// DNS resource records.
|
// RR_Header is the header all DNS resource records share.
|
||||||
// There are many types of RRs,
|
|
||||||
// but they all share the same header.
|
|
||||||
type RR_Header struct {
|
type RR_Header struct {
|
||||||
Name string `dns:"cdomain-name"`
|
Name string `dns:"cdomain-name"`
|
||||||
Rrtype uint16
|
Rrtype uint16
|
||||||
@ -139,9 +45,10 @@ type RR_Header struct {
|
|||||||
Rdlength uint16 // length of data after header
|
Rdlength uint16 // length of data after header
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Header returns itself. This is here to make RR_Header implement the RR interface.
|
||||||
func (h *RR_Header) Header() *RR_Header { return h }
|
func (h *RR_Header) Header() *RR_Header { return h }
|
||||||
|
|
||||||
// Just to imlement the RR interface
|
// Just to imlement the RR interface.
|
||||||
func (h *RR_Header) copy() RR { return nil }
|
func (h *RR_Header) copy() RR { return nil }
|
||||||
|
|
||||||
func (h *RR_Header) copyHeader() *RR_Header {
|
func (h *RR_Header) copyHeader() *RR_Header {
|
||||||
|
464
vendor/github.com/miekg/dns/dnssec.go
generated
vendored
464
vendor/github.com/miekg/dns/dnssec.go
generated
vendored
@ -1,16 +1,3 @@
|
|||||||
// DNSSEC
|
|
||||||
//
|
|
||||||
// DNSSEC (DNS Security Extension) adds a layer of security to the DNS. It
|
|
||||||
// uses public key cryptography to sign resource records. The
|
|
||||||
// public keys are stored in DNSKEY records and the signatures in RRSIG records.
|
|
||||||
//
|
|
||||||
// Requesting DNSSEC information for a zone is done by adding the DO (DNSSEC OK) bit
|
|
||||||
// to an request.
|
|
||||||
//
|
|
||||||
// m := new(dns.Msg)
|
|
||||||
// m.SetEdns0(4096, true)
|
|
||||||
//
|
|
||||||
// Signature generation, signature verification and key generation are all supported.
|
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -19,15 +6,14 @@ import (
|
|||||||
"crypto/dsa"
|
"crypto/dsa"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"crypto/elliptic"
|
"crypto/elliptic"
|
||||||
"crypto/md5"
|
_ "crypto/md5"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
"crypto/sha1"
|
_ "crypto/sha1"
|
||||||
"crypto/sha256"
|
_ "crypto/sha256"
|
||||||
"crypto/sha512"
|
_ "crypto/sha512"
|
||||||
|
"encoding/asn1"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"hash"
|
|
||||||
"io"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
@ -56,6 +42,38 @@ const (
|
|||||||
PRIVATEOID uint8 = 254
|
PRIVATEOID uint8 = 254
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Map for algorithm names.
|
||||||
|
var AlgorithmToString = map[uint8]string{
|
||||||
|
RSAMD5: "RSAMD5",
|
||||||
|
DH: "DH",
|
||||||
|
DSA: "DSA",
|
||||||
|
RSASHA1: "RSASHA1",
|
||||||
|
DSANSEC3SHA1: "DSA-NSEC3-SHA1",
|
||||||
|
RSASHA1NSEC3SHA1: "RSASHA1-NSEC3-SHA1",
|
||||||
|
RSASHA256: "RSASHA256",
|
||||||
|
RSASHA512: "RSASHA512",
|
||||||
|
ECCGOST: "ECC-GOST",
|
||||||
|
ECDSAP256SHA256: "ECDSAP256SHA256",
|
||||||
|
ECDSAP384SHA384: "ECDSAP384SHA384",
|
||||||
|
INDIRECT: "INDIRECT",
|
||||||
|
PRIVATEDNS: "PRIVATEDNS",
|
||||||
|
PRIVATEOID: "PRIVATEOID",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map of algorithm strings.
|
||||||
|
var StringToAlgorithm = reverseInt8(AlgorithmToString)
|
||||||
|
|
||||||
|
// Map of algorithm crypto hashes.
|
||||||
|
var AlgorithmToHash = map[uint8]crypto.Hash{
|
||||||
|
RSAMD5: crypto.MD5, // Deprecated in RFC 6725
|
||||||
|
RSASHA1: crypto.SHA1,
|
||||||
|
RSASHA1NSEC3SHA1: crypto.SHA1,
|
||||||
|
RSASHA256: crypto.SHA256,
|
||||||
|
ECDSAP256SHA256: crypto.SHA256,
|
||||||
|
ECDSAP384SHA384: crypto.SHA384,
|
||||||
|
RSASHA512: crypto.SHA512,
|
||||||
|
}
|
||||||
|
|
||||||
// DNSSEC hashing algorithm codes.
|
// DNSSEC hashing algorithm codes.
|
||||||
const (
|
const (
|
||||||
_ uint8 = iota
|
_ uint8 = iota
|
||||||
@ -66,6 +84,18 @@ const (
|
|||||||
SHA512 // Experimental
|
SHA512 // Experimental
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Map for hash names.
|
||||||
|
var HashToString = map[uint8]string{
|
||||||
|
SHA1: "SHA1",
|
||||||
|
SHA256: "SHA256",
|
||||||
|
GOST94: "GOST94",
|
||||||
|
SHA384: "SHA384",
|
||||||
|
SHA512: "SHA512",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map of hash strings.
|
||||||
|
var StringToHash = reverseInt8(HashToString)
|
||||||
|
|
||||||
// DNSKEY flag values.
|
// DNSKEY flag values.
|
||||||
const (
|
const (
|
||||||
SEP = 1
|
SEP = 1
|
||||||
@ -74,7 +104,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// The RRSIG needs to be converted to wireformat with some of
|
// The RRSIG needs to be converted to wireformat with some of
|
||||||
// the rdata (the signature) missing. Use this struct to easy
|
// the rdata (the signature) missing. Use this struct to ease
|
||||||
// the conversion (and re-use the pack/unpack functions).
|
// the conversion (and re-use the pack/unpack functions).
|
||||||
type rrsigWireFmt struct {
|
type rrsigWireFmt struct {
|
||||||
TypeCovered uint16
|
TypeCovered uint16
|
||||||
@ -182,35 +212,49 @@ func (k *DNSKEY) ToDS(h uint8) *DS {
|
|||||||
// digest buffer
|
// digest buffer
|
||||||
digest := append(owner, wire...) // another copy
|
digest := append(owner, wire...) // another copy
|
||||||
|
|
||||||
|
var hash crypto.Hash
|
||||||
switch h {
|
switch h {
|
||||||
case SHA1:
|
case SHA1:
|
||||||
s := sha1.New()
|
hash = crypto.SHA1
|
||||||
io.WriteString(s, string(digest))
|
|
||||||
ds.Digest = hex.EncodeToString(s.Sum(nil))
|
|
||||||
case SHA256:
|
case SHA256:
|
||||||
s := sha256.New()
|
hash = crypto.SHA256
|
||||||
io.WriteString(s, string(digest))
|
|
||||||
ds.Digest = hex.EncodeToString(s.Sum(nil))
|
|
||||||
case SHA384:
|
case SHA384:
|
||||||
s := sha512.New384()
|
hash = crypto.SHA384
|
||||||
io.WriteString(s, string(digest))
|
case SHA512:
|
||||||
ds.Digest = hex.EncodeToString(s.Sum(nil))
|
hash = crypto.SHA512
|
||||||
case GOST94:
|
|
||||||
/* I have no clue */
|
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s := hash.New()
|
||||||
|
s.Write(digest)
|
||||||
|
ds.Digest = hex.EncodeToString(s.Sum(nil))
|
||||||
return ds
|
return ds
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sign signs an RRSet. The signature needs to be filled in with
|
// ToCDNSKEY converts a DNSKEY record to a CDNSKEY record.
|
||||||
// the values: Inception, Expiration, KeyTag, SignerName and Algorithm.
|
func (k *DNSKEY) ToCDNSKEY() *CDNSKEY {
|
||||||
// The rest is copied from the RRset. Sign returns true when the signing went OK,
|
c := &CDNSKEY{DNSKEY: *k}
|
||||||
// otherwise false.
|
c.Hdr = *k.Hdr.copyHeader()
|
||||||
// There is no check if RRSet is a proper (RFC 2181) RRSet.
|
c.Hdr.Rrtype = TypeCDNSKEY
|
||||||
// If OrigTTL is non zero, it is used as-is, otherwise the TTL of the RRset
|
return c
|
||||||
// is used as the OrigTTL.
|
}
|
||||||
func (rr *RRSIG) Sign(k PrivateKey, rrset []RR) error {
|
|
||||||
|
// ToCDS converts a DS record to a CDS record.
|
||||||
|
func (d *DS) ToCDS() *CDS {
|
||||||
|
c := &CDS{DS: *d}
|
||||||
|
c.Hdr = *d.Hdr.copyHeader()
|
||||||
|
c.Hdr.Rrtype = TypeCDS
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sign signs an RRSet. The signature needs to be filled in with the values:
|
||||||
|
// Inception, Expiration, KeyTag, SignerName and Algorithm. The rest is copied
|
||||||
|
// from the RRset. Sign returns a non-nill error when the signing went OK.
|
||||||
|
// There is no check if RRSet is a proper (RFC 2181) RRSet. If OrigTTL is non
|
||||||
|
// zero, it is used as-is, otherwise the TTL of the RRset is used as the
|
||||||
|
// OrigTTL.
|
||||||
|
func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
|
||||||
if k == nil {
|
if k == nil {
|
||||||
return ErrPrivKey
|
return ErrPrivKey
|
||||||
}
|
}
|
||||||
@ -256,72 +300,72 @@ func (rr *RRSIG) Sign(k PrivateKey, rrset []RR) error {
|
|||||||
}
|
}
|
||||||
signdata = append(signdata, wire...)
|
signdata = append(signdata, wire...)
|
||||||
|
|
||||||
var sighash []byte
|
hash, ok := AlgorithmToHash[rr.Algorithm]
|
||||||
var h hash.Hash
|
if !ok {
|
||||||
var ch crypto.Hash // Only need for RSA
|
|
||||||
var intlen int
|
|
||||||
switch rr.Algorithm {
|
|
||||||
case DSA, DSANSEC3SHA1:
|
|
||||||
// Implicit in the ParameterSizes
|
|
||||||
case RSASHA1, RSASHA1NSEC3SHA1:
|
|
||||||
h = sha1.New()
|
|
||||||
ch = crypto.SHA1
|
|
||||||
case RSASHA256, ECDSAP256SHA256:
|
|
||||||
h = sha256.New()
|
|
||||||
ch = crypto.SHA256
|
|
||||||
intlen = 32
|
|
||||||
case ECDSAP384SHA384:
|
|
||||||
h = sha512.New384()
|
|
||||||
intlen = 48
|
|
||||||
case RSASHA512:
|
|
||||||
h = sha512.New()
|
|
||||||
ch = crypto.SHA512
|
|
||||||
case RSAMD5:
|
|
||||||
fallthrough // Deprecated in RFC 6725
|
|
||||||
default:
|
|
||||||
return ErrAlg
|
return ErrAlg
|
||||||
}
|
}
|
||||||
io.WriteString(h, string(signdata))
|
|
||||||
sighash = h.Sum(nil)
|
|
||||||
|
|
||||||
switch p := k.(type) {
|
h := hash.New()
|
||||||
case *dsa.PrivateKey:
|
h.Write(signdata)
|
||||||
r1, s1, err := dsa.Sign(rand.Reader, p, sighash)
|
|
||||||
if err != nil {
|
signature, err := sign(k, h.Sum(nil), hash, rr.Algorithm)
|
||||||
return err
|
if err != nil {
|
||||||
}
|
return err
|
||||||
signature := []byte{0x4D} // T value, here the ASCII M for Miek (not used in DNSSEC)
|
|
||||||
signature = append(signature, intToBytes(r1, 20)...)
|
|
||||||
signature = append(signature, intToBytes(s1, 20)...)
|
|
||||||
rr.Signature = toBase64(signature)
|
|
||||||
case *rsa.PrivateKey:
|
|
||||||
// We can use nil as rand.Reader here (says AGL)
|
|
||||||
signature, err := rsa.SignPKCS1v15(nil, p, ch, sighash)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
rr.Signature = toBase64(signature)
|
|
||||||
case *ecdsa.PrivateKey:
|
|
||||||
r1, s1, err := ecdsa.Sign(rand.Reader, p, sighash)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
signature := intToBytes(r1, intlen)
|
|
||||||
signature = append(signature, intToBytes(s1, intlen)...)
|
|
||||||
rr.Signature = toBase64(signature)
|
|
||||||
default:
|
|
||||||
// Not given the correct key
|
|
||||||
return ErrKeyAlg
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rr.Signature = toBase64(signature)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sign(k crypto.Signer, hashed []byte, hash crypto.Hash, alg uint8) ([]byte, error) {
|
||||||
|
signature, err := k.Sign(rand.Reader, hashed, hash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch alg {
|
||||||
|
case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512:
|
||||||
|
return signature, nil
|
||||||
|
|
||||||
|
case ECDSAP256SHA256, ECDSAP384SHA384:
|
||||||
|
ecdsaSignature := &struct {
|
||||||
|
R, S *big.Int
|
||||||
|
}{}
|
||||||
|
if _, err := asn1.Unmarshal(signature, ecdsaSignature); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var intlen int
|
||||||
|
switch alg {
|
||||||
|
case ECDSAP256SHA256:
|
||||||
|
intlen = 32
|
||||||
|
case ECDSAP384SHA384:
|
||||||
|
intlen = 48
|
||||||
|
}
|
||||||
|
|
||||||
|
signature := intToBytes(ecdsaSignature.R, intlen)
|
||||||
|
signature = append(signature, intToBytes(ecdsaSignature.S, intlen)...)
|
||||||
|
return signature, nil
|
||||||
|
|
||||||
|
// There is no defined interface for what a DSA backed crypto.Signer returns
|
||||||
|
case DSA, DSANSEC3SHA1:
|
||||||
|
// t := divRoundUp(divRoundUp(p.PublicKey.Y.BitLen(), 8)-64, 8)
|
||||||
|
// signature := []byte{byte(t)}
|
||||||
|
// signature = append(signature, intToBytes(r1, 20)...)
|
||||||
|
// signature = append(signature, intToBytes(s1, 20)...)
|
||||||
|
// rr.Signature = signature
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
// cryptographic test, the signature validity period must be checked separately.
|
// cryptographic test, the signature validity period must be checked separately.
|
||||||
// This function copies the rdata of some RRs (to lowercase domain names) for the validation to work.
|
// This function copies the rdata of some RRs (to lowercase domain names) for the validation to work.
|
||||||
func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
|
func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
|
||||||
// First the easy checks
|
// First the easy checks
|
||||||
if len(rrset) == 0 {
|
if !IsRRset(rrset) {
|
||||||
return ErrRRset
|
return ErrRRset
|
||||||
}
|
}
|
||||||
if rr.KeyTag != k.KeyTag() {
|
if rr.KeyTag != k.KeyTag() {
|
||||||
@ -339,14 +383,17 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
|
|||||||
if k.Protocol != 3 {
|
if k.Protocol != 3 {
|
||||||
return ErrKey
|
return ErrKey
|
||||||
}
|
}
|
||||||
for _, r := range rrset {
|
|
||||||
if r.Header().Class != rr.Hdr.Class {
|
// IsRRset checked that we have at least one RR and that the RRs in
|
||||||
return ErrRRset
|
// the set have consistent type, class, and name. Also check that type and
|
||||||
}
|
// class matches the RRSIG record.
|
||||||
if r.Header().Rrtype != rr.TypeCovered {
|
if rrset[0].Header().Class != rr.Hdr.Class {
|
||||||
return ErrRRset
|
return ErrRRset
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if rrset[0].Header().Rrtype != rr.TypeCovered {
|
||||||
|
return ErrRRset
|
||||||
|
}
|
||||||
|
|
||||||
// RFC 4035 5.3.2. Reconstructing the Signed Data
|
// RFC 4035 5.3.2. Reconstructing the Signed Data
|
||||||
// Copy the sig, except the rrsig data
|
// Copy the sig, except the rrsig data
|
||||||
sigwire := new(rrsigWireFmt)
|
sigwire := new(rrsigWireFmt)
|
||||||
@ -373,8 +420,13 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
|
|||||||
|
|
||||||
sigbuf := rr.sigBuf() // Get the binary signature data
|
sigbuf := rr.sigBuf() // Get the binary signature data
|
||||||
if rr.Algorithm == PRIVATEDNS { // PRIVATEOID
|
if rr.Algorithm == PRIVATEDNS { // PRIVATEOID
|
||||||
// TODO(mg)
|
// TODO(miek)
|
||||||
// remove the domain name and assume its our
|
// remove the domain name and assume its ours?
|
||||||
|
}
|
||||||
|
|
||||||
|
hash, ok := AlgorithmToHash[rr.Algorithm]
|
||||||
|
if !ok {
|
||||||
|
return ErrAlg
|
||||||
}
|
}
|
||||||
|
|
||||||
switch rr.Algorithm {
|
switch rr.Algorithm {
|
||||||
@ -384,57 +436,37 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
|
|||||||
if pubkey == nil {
|
if pubkey == nil {
|
||||||
return ErrKey
|
return ErrKey
|
||||||
}
|
}
|
||||||
// Setup the hash as defined for this alg.
|
|
||||||
var h hash.Hash
|
h := hash.New()
|
||||||
var ch crypto.Hash
|
h.Write(signeddata)
|
||||||
switch rr.Algorithm {
|
return rsa.VerifyPKCS1v15(pubkey, hash, h.Sum(nil), sigbuf)
|
||||||
case RSAMD5:
|
|
||||||
h = md5.New()
|
|
||||||
ch = crypto.MD5
|
|
||||||
case RSASHA1, RSASHA1NSEC3SHA1:
|
|
||||||
h = sha1.New()
|
|
||||||
ch = crypto.SHA1
|
|
||||||
case RSASHA256:
|
|
||||||
h = sha256.New()
|
|
||||||
ch = crypto.SHA256
|
|
||||||
case RSASHA512:
|
|
||||||
h = sha512.New()
|
|
||||||
ch = crypto.SHA512
|
|
||||||
}
|
|
||||||
io.WriteString(h, string(signeddata))
|
|
||||||
sighash := h.Sum(nil)
|
|
||||||
return rsa.VerifyPKCS1v15(pubkey, ch, sighash, sigbuf)
|
|
||||||
case ECDSAP256SHA256, ECDSAP384SHA384:
|
case ECDSAP256SHA256, ECDSAP384SHA384:
|
||||||
pubkey := k.publicKeyCurve()
|
pubkey := k.publicKeyECDSA()
|
||||||
if pubkey == nil {
|
if pubkey == nil {
|
||||||
return ErrKey
|
return ErrKey
|
||||||
}
|
}
|
||||||
var h hash.Hash
|
|
||||||
switch rr.Algorithm {
|
|
||||||
case ECDSAP256SHA256:
|
|
||||||
h = sha256.New()
|
|
||||||
case ECDSAP384SHA384:
|
|
||||||
h = sha512.New384()
|
|
||||||
}
|
|
||||||
io.WriteString(h, string(signeddata))
|
|
||||||
sighash := h.Sum(nil)
|
|
||||||
// Split sigbuf into the r and s coordinates
|
// Split sigbuf into the r and s coordinates
|
||||||
r := big.NewInt(0)
|
r := new(big.Int).SetBytes(sigbuf[:len(sigbuf)/2])
|
||||||
r.SetBytes(sigbuf[:len(sigbuf)/2])
|
s := new(big.Int).SetBytes(sigbuf[len(sigbuf)/2:])
|
||||||
s := big.NewInt(0)
|
|
||||||
s.SetBytes(sigbuf[len(sigbuf)/2:])
|
h := hash.New()
|
||||||
if ecdsa.Verify(pubkey, sighash, r, s) {
|
h.Write(signeddata)
|
||||||
|
if ecdsa.Verify(pubkey, h.Sum(nil), r, s) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return ErrSig
|
return ErrSig
|
||||||
|
|
||||||
|
default:
|
||||||
|
return ErrAlg
|
||||||
}
|
}
|
||||||
// Unknown alg
|
|
||||||
return ErrAlg
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidityPeriod uses RFC1982 serial arithmetic to calculate
|
// ValidityPeriod uses RFC1982 serial arithmetic to calculate
|
||||||
// if a signature period is valid. If t is the zero time, the
|
// if a signature period is valid. If t is the zero time, the
|
||||||
// current time is taken other t is.
|
// current time is taken other t is. Returns true if the signature
|
||||||
|
// is valid at the given time, otherwise returns false.
|
||||||
func (rr *RRSIG) ValidityPeriod(t time.Time) bool {
|
func (rr *RRSIG) ValidityPeriod(t time.Time) bool {
|
||||||
var utc int64
|
var utc int64
|
||||||
if t.IsZero() {
|
if t.IsZero() {
|
||||||
@ -450,39 +482,14 @@ func (rr *RRSIG) ValidityPeriod(t time.Time) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return the signatures base64 encodedig sigdata as a byte slice.
|
// Return the signatures base64 encodedig sigdata as a byte slice.
|
||||||
func (s *RRSIG) sigBuf() []byte {
|
func (rr *RRSIG) sigBuf() []byte {
|
||||||
sigbuf, err := fromBase64([]byte(s.Signature))
|
sigbuf, err := fromBase64([]byte(rr.Signature))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return sigbuf
|
return sigbuf
|
||||||
}
|
}
|
||||||
|
|
||||||
// setPublicKeyInPrivate sets the public key in the private key.
|
|
||||||
func (k *DNSKEY) setPublicKeyInPrivate(p PrivateKey) bool {
|
|
||||||
switch t := p.(type) {
|
|
||||||
case *dsa.PrivateKey:
|
|
||||||
x := k.publicKeyDSA()
|
|
||||||
if x == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
t.PublicKey = *x
|
|
||||||
case *rsa.PrivateKey:
|
|
||||||
x := k.publicKeyRSA()
|
|
||||||
if x == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
t.PublicKey = *x
|
|
||||||
case *ecdsa.PrivateKey:
|
|
||||||
x := k.publicKeyCurve()
|
|
||||||
if x == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
t.PublicKey = *x
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// publicKeyRSA returns the RSA public key from a DNSKEY record.
|
// publicKeyRSA returns the RSA public key from a DNSKEY record.
|
||||||
func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey {
|
func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey {
|
||||||
keybuf, err := fromBase64([]byte(k.PublicKey))
|
keybuf, err := fromBase64([]byte(k.PublicKey))
|
||||||
@ -521,8 +528,8 @@ func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey {
|
|||||||
return pubkey
|
return pubkey
|
||||||
}
|
}
|
||||||
|
|
||||||
// publicKeyCurve returns the Curve public key from the DNSKEY record.
|
// publicKeyECDSA returns the Curve public key from the DNSKEY record.
|
||||||
func (k *DNSKEY) publicKeyCurve() *ecdsa.PublicKey {
|
func (k *DNSKEY) publicKeyECDSA() *ecdsa.PublicKey {
|
||||||
keybuf, err := fromBase64([]byte(k.PublicKey))
|
keybuf, err := fromBase64([]byte(k.PublicKey))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
@ -573,81 +580,6 @@ func (k *DNSKEY) publicKeyDSA() *dsa.PublicKey {
|
|||||||
return pubkey
|
return pubkey
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the public key (the value E and N)
|
|
||||||
func (k *DNSKEY) setPublicKeyRSA(_E int, _N *big.Int) bool {
|
|
||||||
if _E == 0 || _N == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
buf := exponentToBuf(_E)
|
|
||||||
buf = append(buf, _N.Bytes()...)
|
|
||||||
k.PublicKey = toBase64(buf)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the public key for Elliptic Curves
|
|
||||||
func (k *DNSKEY) setPublicKeyCurve(_X, _Y *big.Int) bool {
|
|
||||||
if _X == nil || _Y == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
var intlen int
|
|
||||||
switch k.Algorithm {
|
|
||||||
case ECDSAP256SHA256:
|
|
||||||
intlen = 32
|
|
||||||
case ECDSAP384SHA384:
|
|
||||||
intlen = 48
|
|
||||||
}
|
|
||||||
k.PublicKey = toBase64(curveToBuf(_X, _Y, intlen))
|
|
||||||
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 (the values E and N) for RSA
|
|
||||||
// RFC 3110: Section 2. RSA Public KEY Resource Records
|
|
||||||
func exponentToBuf(_E int) []byte {
|
|
||||||
var buf []byte
|
|
||||||
i := big.NewInt(int64(_E))
|
|
||||||
if len(i.Bytes()) < 256 {
|
|
||||||
buf = make([]byte, 1)
|
|
||||||
buf[0] = uint8(len(i.Bytes()))
|
|
||||||
} else {
|
|
||||||
buf = make([]byte, 3)
|
|
||||||
buf[0] = 0
|
|
||||||
buf[1] = uint8(len(i.Bytes()) >> 8)
|
|
||||||
buf[2] = uint8(len(i.Bytes()))
|
|
||||||
}
|
|
||||||
buf = append(buf, i.Bytes()...)
|
|
||||||
return buf
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the public key for X and Y for Curve. The two
|
|
||||||
// values are just concatenated.
|
|
||||||
func curveToBuf(_X, _Y *big.Int, intlen int) []byte {
|
|
||||||
buf := intToBytes(_X, intlen)
|
|
||||||
buf = append(buf, intToBytes(_Y, intlen)...)
|
|
||||||
return buf
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the public key for X and Y for Curve. The two
|
|
||||||
// values are just concatenated.
|
|
||||||
func dsaToBuf(_Q, _P, _G, _Y *big.Int) []byte {
|
|
||||||
t := divRoundUp(divRoundUp(_G.BitLen(), 8)-64, 8)
|
|
||||||
buf := []byte{byte(t)}
|
|
||||||
buf = append(buf, intToBytes(_Q, 20)...)
|
|
||||||
buf = append(buf, intToBytes(_P, 64+t*8)...)
|
|
||||||
buf = append(buf, intToBytes(_G, 64+t*8)...)
|
|
||||||
buf = append(buf, intToBytes(_Y, 64+t*8)...)
|
|
||||||
return buf
|
|
||||||
}
|
|
||||||
|
|
||||||
type wireSlice [][]byte
|
type wireSlice [][]byte
|
||||||
|
|
||||||
func (p wireSlice) Len() int { return len(p) }
|
func (p wireSlice) Len() int { return len(p) }
|
||||||
@ -676,6 +608,12 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
|
|||||||
// 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,
|
||||||
// SRV, DNAME, A6
|
// SRV, DNAME, A6
|
||||||
|
//
|
||||||
|
// RFC 6840 - Clarifications and Implementation Notes for DNS Security (DNSSEC):
|
||||||
|
// Section 6.2 of [RFC4034] also erroneously lists HINFO as a record
|
||||||
|
// that needs conversion to lowercase, and twice at that. Since HINFO
|
||||||
|
// records contain no domain names, they are not subject to case
|
||||||
|
// conversion.
|
||||||
switch x := r1.(type) {
|
switch x := r1.(type) {
|
||||||
case *NS:
|
case *NS:
|
||||||
x.Ns = strings.ToLower(x.Ns)
|
x.Ns = strings.ToLower(x.Ns)
|
||||||
@ -716,41 +654,11 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
|
|||||||
wires[i] = wire
|
wires[i] = wire
|
||||||
}
|
}
|
||||||
sort.Sort(wires)
|
sort.Sort(wires)
|
||||||
for _, wire := range wires {
|
for i, wire := range wires {
|
||||||
|
if i > 0 && bytes.Equal(wire, wires[i-1]) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
buf = append(buf, wire...)
|
buf = append(buf, wire...)
|
||||||
}
|
}
|
||||||
return buf, nil
|
return buf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map for algorithm names.
|
|
||||||
var AlgorithmToString = map[uint8]string{
|
|
||||||
RSAMD5: "RSAMD5",
|
|
||||||
DH: "DH",
|
|
||||||
DSA: "DSA",
|
|
||||||
RSASHA1: "RSASHA1",
|
|
||||||
DSANSEC3SHA1: "DSA-NSEC3-SHA1",
|
|
||||||
RSASHA1NSEC3SHA1: "RSASHA1-NSEC3-SHA1",
|
|
||||||
RSASHA256: "RSASHA256",
|
|
||||||
RSASHA512: "RSASHA512",
|
|
||||||
ECCGOST: "ECC-GOST",
|
|
||||||
ECDSAP256SHA256: "ECDSAP256SHA256",
|
|
||||||
ECDSAP384SHA384: "ECDSAP384SHA384",
|
|
||||||
INDIRECT: "INDIRECT",
|
|
||||||
PRIVATEDNS: "PRIVATEDNS",
|
|
||||||
PRIVATEOID: "PRIVATEOID",
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map of algorithm strings.
|
|
||||||
var StringToAlgorithm = reverseInt8(AlgorithmToString)
|
|
||||||
|
|
||||||
// Map for hash names.
|
|
||||||
var HashToString = map[uint8]string{
|
|
||||||
SHA1: "SHA1",
|
|
||||||
SHA256: "SHA256",
|
|
||||||
GOST94: "GOST94",
|
|
||||||
SHA384: "SHA384",
|
|
||||||
SHA512: "SHA512",
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map of hash strings.
|
|
||||||
var StringToHash = reverseInt8(HashToString)
|
|
||||||
|
156
vendor/github.com/miekg/dns/dnssec_keygen.go
generated
vendored
Normal file
156
vendor/github.com/miekg/dns/dnssec_keygen.go
generated
vendored
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
package dns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto"
|
||||||
|
"crypto/dsa"
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"crypto/elliptic"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/rsa"
|
||||||
|
"math/big"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Generate generates a DNSKEY of the given bit size.
|
||||||
|
// The public part is put inside the DNSKEY record.
|
||||||
|
// The Algorithm in the key must be set as this will define
|
||||||
|
// what kind of DNSKEY will be generated.
|
||||||
|
// The ECDSA algorithms imply a fixed keysize, in that case
|
||||||
|
// bits should be set to the size of the algorithm.
|
||||||
|
func (k *DNSKEY) Generate(bits int) (crypto.PrivateKey, error) {
|
||||||
|
switch k.Algorithm {
|
||||||
|
case DSA, DSANSEC3SHA1:
|
||||||
|
if bits != 1024 {
|
||||||
|
return nil, ErrKeySize
|
||||||
|
}
|
||||||
|
case RSAMD5, RSASHA1, RSASHA256, RSASHA1NSEC3SHA1:
|
||||||
|
if bits < 512 || bits > 4096 {
|
||||||
|
return nil, ErrKeySize
|
||||||
|
}
|
||||||
|
case RSASHA512:
|
||||||
|
if bits < 1024 || bits > 4096 {
|
||||||
|
return nil, ErrKeySize
|
||||||
|
}
|
||||||
|
case ECDSAP256SHA256:
|
||||||
|
if bits != 256 {
|
||||||
|
return nil, ErrKeySize
|
||||||
|
}
|
||||||
|
case ECDSAP384SHA384:
|
||||||
|
if bits != 384 {
|
||||||
|
return nil, ErrKeySize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch k.Algorithm {
|
||||||
|
case DSA, DSANSEC3SHA1:
|
||||||
|
params := new(dsa.Parameters)
|
||||||
|
if err := dsa.GenerateParameters(params, rand.Reader, dsa.L1024N160); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
priv := new(dsa.PrivateKey)
|
||||||
|
priv.PublicKey.Parameters = *params
|
||||||
|
err := dsa.GenerateKey(priv, rand.Reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
k.setPublicKeyDSA(params.Q, params.P, params.G, priv.PublicKey.Y)
|
||||||
|
return priv, nil
|
||||||
|
case RSAMD5, RSASHA1, RSASHA256, RSASHA512, RSASHA1NSEC3SHA1:
|
||||||
|
priv, err := rsa.GenerateKey(rand.Reader, bits)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
k.setPublicKeyRSA(priv.PublicKey.E, priv.PublicKey.N)
|
||||||
|
return priv, nil
|
||||||
|
case ECDSAP256SHA256, ECDSAP384SHA384:
|
||||||
|
var c elliptic.Curve
|
||||||
|
switch k.Algorithm {
|
||||||
|
case ECDSAP256SHA256:
|
||||||
|
c = elliptic.P256()
|
||||||
|
case ECDSAP384SHA384:
|
||||||
|
c = elliptic.P384()
|
||||||
|
}
|
||||||
|
priv, err := ecdsa.GenerateKey(c, rand.Reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
k.setPublicKeyECDSA(priv.PublicKey.X, priv.PublicKey.Y)
|
||||||
|
return priv, nil
|
||||||
|
default:
|
||||||
|
return nil, ErrAlg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the public key (the value E and N)
|
||||||
|
func (k *DNSKEY) setPublicKeyRSA(_E int, _N *big.Int) bool {
|
||||||
|
if _E == 0 || _N == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
buf := exponentToBuf(_E)
|
||||||
|
buf = append(buf, _N.Bytes()...)
|
||||||
|
k.PublicKey = toBase64(buf)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the public key for Elliptic Curves
|
||||||
|
func (k *DNSKEY) setPublicKeyECDSA(_X, _Y *big.Int) bool {
|
||||||
|
if _X == nil || _Y == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
var intlen int
|
||||||
|
switch k.Algorithm {
|
||||||
|
case ECDSAP256SHA256:
|
||||||
|
intlen = 32
|
||||||
|
case ECDSAP384SHA384:
|
||||||
|
intlen = 48
|
||||||
|
}
|
||||||
|
k.PublicKey = toBase64(curveToBuf(_X, _Y, intlen))
|
||||||
|
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 (the values E and N) for RSA
|
||||||
|
// RFC 3110: Section 2. RSA Public KEY Resource Records
|
||||||
|
func exponentToBuf(_E int) []byte {
|
||||||
|
var buf []byte
|
||||||
|
i := big.NewInt(int64(_E))
|
||||||
|
if len(i.Bytes()) < 256 {
|
||||||
|
buf = make([]byte, 1)
|
||||||
|
buf[0] = uint8(len(i.Bytes()))
|
||||||
|
} else {
|
||||||
|
buf = make([]byte, 3)
|
||||||
|
buf[0] = 0
|
||||||
|
buf[1] = uint8(len(i.Bytes()) >> 8)
|
||||||
|
buf[2] = uint8(len(i.Bytes()))
|
||||||
|
}
|
||||||
|
buf = append(buf, i.Bytes()...)
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the public key for X and Y for Curve. The two
|
||||||
|
// values are just concatenated.
|
||||||
|
func curveToBuf(_X, _Y *big.Int, intlen int) []byte {
|
||||||
|
buf := intToBytes(_X, intlen)
|
||||||
|
buf = append(buf, intToBytes(_Y, intlen)...)
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the public key for X and Y for Curve. The two
|
||||||
|
// values are just concatenated.
|
||||||
|
func dsaToBuf(_Q, _P, _G, _Y *big.Int) []byte {
|
||||||
|
t := divRoundUp(divRoundUp(_G.BitLen(), 8)-64, 8)
|
||||||
|
buf := []byte{byte(t)}
|
||||||
|
buf = append(buf, intToBytes(_Q, 20)...)
|
||||||
|
buf = append(buf, intToBytes(_P, 64+t*8)...)
|
||||||
|
buf = append(buf, intToBytes(_G, 64+t*8)...)
|
||||||
|
buf = append(buf, intToBytes(_Y, 64+t*8)...)
|
||||||
|
return buf
|
||||||
|
}
|
133
vendor/github.com/miekg/dns/kscan.go → vendor/github.com/miekg/dns/dnssec_keyscan.go
generated
vendored
133
vendor/github.com/miekg/dns/kscan.go → vendor/github.com/miekg/dns/dnssec_keyscan.go
generated
vendored
@ -1,15 +1,19 @@
|
|||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto"
|
||||||
"crypto/dsa"
|
"crypto/dsa"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (k *DNSKEY) NewPrivateKey(s string) (PrivateKey, error) {
|
// NewPrivateKey returns a PrivateKey by parsing the string s.
|
||||||
|
// s should be in the same form of the BIND private key files.
|
||||||
|
func (k *DNSKEY) NewPrivateKey(s string) (crypto.PrivateKey, error) {
|
||||||
if s[len(s)-1] != '\n' { // We need a closing newline
|
if s[len(s)-1] != '\n' { // We need a closing newline
|
||||||
return k.ReadPrivateKey(strings.NewReader(s+"\n"), "")
|
return k.ReadPrivateKey(strings.NewReader(s+"\n"), "")
|
||||||
}
|
}
|
||||||
@ -18,9 +22,9 @@ func (k *DNSKEY) NewPrivateKey(s string) (PrivateKey, error) {
|
|||||||
|
|
||||||
// ReadPrivateKey reads a private key from the io.Reader q. The string file is
|
// ReadPrivateKey reads a private key from the io.Reader q. The string file is
|
||||||
// only used in error reporting.
|
// only used in error reporting.
|
||||||
// The public key must be
|
// The public key must be known, because some cryptographic algorithms embed
|
||||||
// known, because some cryptographic algorithms embed the public inside the privatekey.
|
// the public inside the privatekey.
|
||||||
func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (PrivateKey, error) {
|
func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, error) {
|
||||||
m, e := parseKey(q, file)
|
m, e := parseKey(q, file)
|
||||||
if m == nil {
|
if m == nil {
|
||||||
return nil, e
|
return nil, e
|
||||||
@ -32,57 +36,63 @@ func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (PrivateKey, error) {
|
|||||||
return nil, ErrPrivKey
|
return nil, ErrPrivKey
|
||||||
}
|
}
|
||||||
// TODO(mg): check if the pubkey matches the private key
|
// TODO(mg): check if the pubkey matches the private key
|
||||||
switch m["algorithm"] {
|
algo, err := strconv.Atoi(strings.SplitN(m["algorithm"], " ", 2)[0])
|
||||||
case "3 (DSA)":
|
if err != nil {
|
||||||
p, e := readPrivateKeyDSA(m)
|
return nil, ErrPrivKey
|
||||||
if e != nil {
|
}
|
||||||
return nil, e
|
switch uint8(algo) {
|
||||||
}
|
case DSA:
|
||||||
if !k.setPublicKeyInPrivate(p) {
|
priv, e := readPrivateKeyDSA(m)
|
||||||
return nil, ErrKey
|
if e != nil {
|
||||||
}
|
return nil, e
|
||||||
return p, e
|
}
|
||||||
case "1 (RSAMD5)":
|
pub := k.publicKeyDSA()
|
||||||
fallthrough
|
if pub == nil {
|
||||||
case "5 (RSASHA1)":
|
return nil, ErrKey
|
||||||
fallthrough
|
}
|
||||||
case "7 (RSASHA1NSEC3SHA1)":
|
priv.PublicKey = *pub
|
||||||
fallthrough
|
return priv, e
|
||||||
case "8 (RSASHA256)":
|
case RSAMD5:
|
||||||
fallthrough
|
fallthrough
|
||||||
case "10 (RSASHA512)":
|
case RSASHA1:
|
||||||
p, e := readPrivateKeyRSA(m)
|
fallthrough
|
||||||
if e != nil {
|
case RSASHA1NSEC3SHA1:
|
||||||
return nil, e
|
fallthrough
|
||||||
}
|
case RSASHA256:
|
||||||
if !k.setPublicKeyInPrivate(p) {
|
fallthrough
|
||||||
return nil, ErrKey
|
case RSASHA512:
|
||||||
}
|
priv, e := readPrivateKeyRSA(m)
|
||||||
return p, e
|
if e != nil {
|
||||||
case "12 (ECC-GOST)":
|
return nil, e
|
||||||
p, e := readPrivateKeyGOST(m)
|
}
|
||||||
if e != nil {
|
pub := k.publicKeyRSA()
|
||||||
return nil, e
|
if pub == nil {
|
||||||
}
|
return nil, ErrKey
|
||||||
// setPublicKeyInPrivate(p)
|
}
|
||||||
return p, e
|
priv.PublicKey = *pub
|
||||||
case "13 (ECDSAP256SHA256)":
|
return priv, e
|
||||||
fallthrough
|
case ECCGOST:
|
||||||
case "14 (ECDSAP384SHA384)":
|
return nil, ErrPrivKey
|
||||||
p, e := readPrivateKeyECDSA(m)
|
case ECDSAP256SHA256:
|
||||||
if e != nil {
|
fallthrough
|
||||||
return nil, e
|
case ECDSAP384SHA384:
|
||||||
}
|
priv, e := readPrivateKeyECDSA(m)
|
||||||
if !k.setPublicKeyInPrivate(p) {
|
if e != nil {
|
||||||
return nil, ErrKey
|
return nil, e
|
||||||
}
|
}
|
||||||
return p, e
|
pub := k.publicKeyECDSA()
|
||||||
|
if pub == nil {
|
||||||
|
return nil, ErrKey
|
||||||
|
}
|
||||||
|
priv.PublicKey = *pub
|
||||||
|
return priv, e
|
||||||
|
default:
|
||||||
|
return nil, ErrPrivKey
|
||||||
}
|
}
|
||||||
return nil, ErrPrivKey
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read a private key (file) string and create a public key. Return the private key.
|
// Read a private key (file) string and create a public key. Return the private key.
|
||||||
func readPrivateKeyRSA(m map[string]string) (PrivateKey, error) {
|
func readPrivateKeyRSA(m map[string]string) (*rsa.PrivateKey, error) {
|
||||||
p := new(rsa.PrivateKey)
|
p := new(rsa.PrivateKey)
|
||||||
p.Primes = []*big.Int{nil, nil}
|
p.Primes = []*big.Int{nil, nil}
|
||||||
for k, v := range m {
|
for k, v := range m {
|
||||||
@ -119,7 +129,7 @@ func readPrivateKeyRSA(m map[string]string) (PrivateKey, error) {
|
|||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func readPrivateKeyDSA(m map[string]string) (PrivateKey, error) {
|
func readPrivateKeyDSA(m map[string]string) (*dsa.PrivateKey, error) {
|
||||||
p := new(dsa.PrivateKey)
|
p := new(dsa.PrivateKey)
|
||||||
p.X = big.NewInt(0)
|
p.X = big.NewInt(0)
|
||||||
for k, v := range m {
|
for k, v := range m {
|
||||||
@ -137,7 +147,7 @@ func readPrivateKeyDSA(m map[string]string) (PrivateKey, error) {
|
|||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func readPrivateKeyECDSA(m map[string]string) (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 = big.NewInt(0)
|
||||||
// TODO: validate that the required flags are present
|
// TODO: validate that the required flags are present
|
||||||
@ -156,11 +166,6 @@ func readPrivateKeyECDSA(m map[string]string) (PrivateKey, error) {
|
|||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func readPrivateKeyGOST(m map[string]string) (PrivateKey, error) {
|
|
||||||
// TODO(miek)
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseKey reads a private key from r. It returns a map[string]string,
|
// parseKey reads a private key from r. It returns a map[string]string,
|
||||||
// with the key-value pairs, or an error when the file is not correct.
|
// with the key-value pairs, or an error when the file is not correct.
|
||||||
func parseKey(r io.Reader, file string) (map[string]string, error) {
|
func parseKey(r io.Reader, file string) (map[string]string, error) {
|
||||||
@ -173,9 +178,9 @@ func parseKey(r io.Reader, file string) (map[string]string, error) {
|
|||||||
for l := range c {
|
for l := range c {
|
||||||
// It should alternate
|
// It should alternate
|
||||||
switch l.value {
|
switch l.value {
|
||||||
case _KEY:
|
case zKey:
|
||||||
k = l.token
|
k = l.token
|
||||||
case _VALUE:
|
case zValue:
|
||||||
if k == "" {
|
if k == "" {
|
||||||
return nil, &ParseError{file, "no private key seen", l}
|
return nil, &ParseError{file, "no private key seen", l}
|
||||||
}
|
}
|
||||||
@ -205,14 +210,14 @@ func klexer(s *scan, c chan lex) {
|
|||||||
}
|
}
|
||||||
l.token = str
|
l.token = str
|
||||||
if key {
|
if key {
|
||||||
l.value = _KEY
|
l.value = zKey
|
||||||
c <- l
|
c <- l
|
||||||
// Next token is a space, eat it
|
// Next token is a space, eat it
|
||||||
s.tokenText()
|
s.tokenText()
|
||||||
key = false
|
key = false
|
||||||
str = ""
|
str = ""
|
||||||
} else {
|
} else {
|
||||||
l.value = _VALUE
|
l.value = zValue
|
||||||
}
|
}
|
||||||
case ';':
|
case ';':
|
||||||
commt = true
|
commt = true
|
||||||
@ -221,7 +226,7 @@ func klexer(s *scan, c chan lex) {
|
|||||||
// Reset a comment
|
// Reset a comment
|
||||||
commt = false
|
commt = false
|
||||||
}
|
}
|
||||||
l.value = _VALUE
|
l.value = zValue
|
||||||
l.token = str
|
l.token = str
|
||||||
c <- l
|
c <- l
|
||||||
str = ""
|
str = ""
|
||||||
@ -238,7 +243,7 @@ func klexer(s *scan, c chan lex) {
|
|||||||
if len(str) > 0 {
|
if len(str) > 0 {
|
||||||
// Send remainder
|
// Send remainder
|
||||||
l.token = str
|
l.token = str
|
||||||
l.value = _VALUE
|
l.value = zValue
|
||||||
c <- l
|
c <- l
|
||||||
}
|
}
|
||||||
}
|
}
|
85
vendor/github.com/miekg/dns/dnssec_privkey.go
generated
vendored
Normal file
85
vendor/github.com/miekg/dns/dnssec_privkey.go
generated
vendored
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
package dns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto"
|
||||||
|
"crypto/dsa"
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"crypto/rsa"
|
||||||
|
"math/big"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
const format = "Private-key-format: v1.3\n"
|
||||||
|
|
||||||
|
// PrivateKeyString converts a PrivateKey to a string. This string has the same
|
||||||
|
// format as the private-key-file of BIND9 (Private-key-format: v1.3).
|
||||||
|
// It needs some info from the key (the algorithm), so its a method of the DNSKEY
|
||||||
|
// It supports rsa.PrivateKey, ecdsa.PrivateKey and dsa.PrivateKey
|
||||||
|
func (r *DNSKEY) PrivateKeyString(p crypto.PrivateKey) string {
|
||||||
|
algorithm := strconv.Itoa(int(r.Algorithm))
|
||||||
|
algorithm += " (" + AlgorithmToString[r.Algorithm] + ")"
|
||||||
|
|
||||||
|
switch p := p.(type) {
|
||||||
|
case *rsa.PrivateKey:
|
||||||
|
modulus := toBase64(p.PublicKey.N.Bytes())
|
||||||
|
e := big.NewInt(int64(p.PublicKey.E))
|
||||||
|
publicExponent := toBase64(e.Bytes())
|
||||||
|
privateExponent := toBase64(p.D.Bytes())
|
||||||
|
prime1 := toBase64(p.Primes[0].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
|
||||||
|
// and from: http://code.google.com/p/go/issues/detail?id=987
|
||||||
|
one := big.NewInt(1)
|
||||||
|
p1 := big.NewInt(0).Sub(p.Primes[0], one)
|
||||||
|
q1 := big.NewInt(0).Sub(p.Primes[1], one)
|
||||||
|
exp1 := big.NewInt(0).Mod(p.D, p1)
|
||||||
|
exp2 := big.NewInt(0).Mod(p.D, q1)
|
||||||
|
coeff := big.NewInt(0).ModInverse(p.Primes[1], p.Primes[0])
|
||||||
|
|
||||||
|
exponent1 := toBase64(exp1.Bytes())
|
||||||
|
exponent2 := toBase64(exp2.Bytes())
|
||||||
|
coefficient := toBase64(coeff.Bytes())
|
||||||
|
|
||||||
|
return format +
|
||||||
|
"Algorithm: " + algorithm + "\n" +
|
||||||
|
"Modulus: " + modulus + "\n" +
|
||||||
|
"PublicExponent: " + publicExponent + "\n" +
|
||||||
|
"PrivateExponent: " + privateExponent + "\n" +
|
||||||
|
"Prime1: " + prime1 + "\n" +
|
||||||
|
"Prime2: " + prime2 + "\n" +
|
||||||
|
"Exponent1: " + exponent1 + "\n" +
|
||||||
|
"Exponent2: " + exponent2 + "\n" +
|
||||||
|
"Coefficient: " + coefficient + "\n"
|
||||||
|
|
||||||
|
case *ecdsa.PrivateKey:
|
||||||
|
var intlen int
|
||||||
|
switch r.Algorithm {
|
||||||
|
case ECDSAP256SHA256:
|
||||||
|
intlen = 32
|
||||||
|
case ECDSAP384SHA384:
|
||||||
|
intlen = 48
|
||||||
|
}
|
||||||
|
private := toBase64(intToBytes(p.D, intlen))
|
||||||
|
return format +
|
||||||
|
"Algorithm: " + algorithm + "\n" +
|
||||||
|
"PrivateKey: " + private + "\n"
|
||||||
|
|
||||||
|
case *dsa.PrivateKey:
|
||||||
|
T := divRoundUp(divRoundUp(p.PublicKey.Parameters.G.BitLen(), 8)-64, 8)
|
||||||
|
prime := toBase64(intToBytes(p.PublicKey.Parameters.P, 64+T*8))
|
||||||
|
subprime := toBase64(intToBytes(p.PublicKey.Parameters.Q, 20))
|
||||||
|
base := toBase64(intToBytes(p.PublicKey.Parameters.G, 64+T*8))
|
||||||
|
priv := toBase64(intToBytes(p.X, 20))
|
||||||
|
pub := toBase64(intToBytes(p.PublicKey.Y, 64+T*8))
|
||||||
|
return format +
|
||||||
|
"Algorithm: " + algorithm + "\n" +
|
||||||
|
"Prime(p): " + prime + "\n" +
|
||||||
|
"Subprime(q): " + subprime + "\n" +
|
||||||
|
"Base(g): " + base + "\n" +
|
||||||
|
"Private_value(x): " + priv + "\n" +
|
||||||
|
"Public_value(y): " + pub + "\n"
|
||||||
|
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
251
vendor/github.com/miekg/dns/doc.go
generated
vendored
Normal file
251
vendor/github.com/miekg/dns/doc.go
generated
vendored
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
/*
|
||||||
|
Package dns implements a full featured interface to the Domain Name System.
|
||||||
|
Server- and client-side programming is supported.
|
||||||
|
The package allows complete control over what is send out to the DNS. The package
|
||||||
|
API follows the less-is-more principle, by presenting a small, clean interface.
|
||||||
|
|
||||||
|
The package dns supports (asynchronous) querying/replying, incoming/outgoing zone transfers,
|
||||||
|
TSIG, EDNS0, dynamic updates, notifies and DNSSEC validation/signing.
|
||||||
|
Note that domain names MUST be fully qualified, before sending them, unqualified
|
||||||
|
names in a message will result in a packing failure.
|
||||||
|
|
||||||
|
Resource records are native types. They are not stored in wire format.
|
||||||
|
Basic usage pattern for creating a new resource record:
|
||||||
|
|
||||||
|
r := new(dns.MX)
|
||||||
|
r.Hdr = dns.RR_Header{Name: "miek.nl.", Rrtype: dns.TypeMX,
|
||||||
|
Class: dns.ClassINET, Ttl: 3600}
|
||||||
|
r.Preference = 10
|
||||||
|
r.Mx = "mx.miek.nl."
|
||||||
|
|
||||||
|
Or directly from a string:
|
||||||
|
|
||||||
|
mx, err := dns.NewRR("miek.nl. 3600 IN MX 10 mx.miek.nl.")
|
||||||
|
|
||||||
|
Or when the default TTL (3600) and class (IN) suit you:
|
||||||
|
|
||||||
|
mx, err := dns.NewRR("miek.nl. MX 10 mx.miek.nl.")
|
||||||
|
|
||||||
|
Or even:
|
||||||
|
|
||||||
|
mx, err := dns.NewRR("$ORIGIN nl.\nmiek 1H IN MX 10 mx.miek")
|
||||||
|
|
||||||
|
In the DNS messages are exchanged, these messages contain resource
|
||||||
|
records (sets). Use pattern for creating a message:
|
||||||
|
|
||||||
|
m := new(dns.Msg)
|
||||||
|
m.SetQuestion("miek.nl.", dns.TypeMX)
|
||||||
|
|
||||||
|
Or when not certain if the domain name is fully qualified:
|
||||||
|
|
||||||
|
m.SetQuestion(dns.Fqdn("miek.nl"), dns.TypeMX)
|
||||||
|
|
||||||
|
The message m is now a message with the question section set to ask
|
||||||
|
the MX records for the miek.nl. zone.
|
||||||
|
|
||||||
|
The following is slightly more verbose, but more flexible:
|
||||||
|
|
||||||
|
m1 := new(dns.Msg)
|
||||||
|
m1.Id = dns.Id()
|
||||||
|
m1.RecursionDesired = true
|
||||||
|
m1.Question = make([]dns.Question, 1)
|
||||||
|
m1.Question[0] = dns.Question{"miek.nl.", dns.TypeMX, dns.ClassINET}
|
||||||
|
|
||||||
|
After creating a message it can be send.
|
||||||
|
Basic use pattern for synchronous querying the DNS at a
|
||||||
|
server configured on 127.0.0.1 and port 53:
|
||||||
|
|
||||||
|
c := new(dns.Client)
|
||||||
|
in, rtt, err := c.Exchange(m1, "127.0.0.1:53")
|
||||||
|
|
||||||
|
Suppressing multiple outstanding queries (with the same question, type and
|
||||||
|
class) is as easy as setting:
|
||||||
|
|
||||||
|
c.SingleInflight = true
|
||||||
|
|
||||||
|
If these "advanced" features are not needed, a simple UDP query can be send,
|
||||||
|
with:
|
||||||
|
|
||||||
|
in, err := dns.Exchange(m1, "127.0.0.1:53")
|
||||||
|
|
||||||
|
When this functions returns you will get dns message. A dns message consists
|
||||||
|
out of four sections.
|
||||||
|
The question section: in.Question, the answer section: in.Answer,
|
||||||
|
the authority section: in.Ns and the additional section: in.Extra.
|
||||||
|
|
||||||
|
Each of these sections (except the Question section) contain a []RR. Basic
|
||||||
|
use pattern for accessing the rdata of a TXT RR as the first RR in
|
||||||
|
the Answer section:
|
||||||
|
|
||||||
|
if t, ok := in.Answer[0].(*dns.TXT); ok {
|
||||||
|
// do something with t.Txt
|
||||||
|
}
|
||||||
|
|
||||||
|
Domain Name and TXT Character String Representations
|
||||||
|
|
||||||
|
Both domain names and TXT character strings are converted to presentation
|
||||||
|
form both when unpacked and when converted to strings.
|
||||||
|
|
||||||
|
For TXT character strings, tabs, carriage returns and line feeds will be
|
||||||
|
converted to \t, \r and \n respectively. Back slashes and quotations marks
|
||||||
|
will be escaped. Bytes below 32 and above 127 will be converted to \DDD
|
||||||
|
form.
|
||||||
|
|
||||||
|
For domain names, in addition to the above rules brackets, periods,
|
||||||
|
spaces, semicolons and the at symbol are escaped.
|
||||||
|
|
||||||
|
DNSSEC
|
||||||
|
|
||||||
|
DNSSEC (DNS Security Extension) adds a layer of security to the DNS. It
|
||||||
|
uses public key cryptography to sign resource records. The
|
||||||
|
public keys are stored in DNSKEY records and the signatures in RRSIG records.
|
||||||
|
|
||||||
|
Requesting DNSSEC information for a zone is done by adding the DO (DNSSEC OK) bit
|
||||||
|
to a request.
|
||||||
|
|
||||||
|
m := new(dns.Msg)
|
||||||
|
m.SetEdns0(4096, true)
|
||||||
|
|
||||||
|
Signature generation, signature verification and key generation are all supported.
|
||||||
|
|
||||||
|
DYNAMIC UPDATES
|
||||||
|
|
||||||
|
Dynamic updates reuses the DNS message format, but renames three of
|
||||||
|
the sections. Question is Zone, Answer is Prerequisite, Authority is
|
||||||
|
Update, only the Additional is not renamed. See RFC 2136 for the gory details.
|
||||||
|
|
||||||
|
You can set a rather complex set of rules for the existence of absence of
|
||||||
|
certain resource records or names in a zone to specify if resource records
|
||||||
|
should be added or removed. The table from RFC 2136 supplemented with the Go
|
||||||
|
DNS function shows which functions exist to specify the prerequisites.
|
||||||
|
|
||||||
|
3.2.4 - Table Of Metavalues Used In Prerequisite Section
|
||||||
|
|
||||||
|
CLASS TYPE RDATA Meaning Function
|
||||||
|
--------------------------------------------------------------
|
||||||
|
ANY ANY empty Name is in use dns.NameUsed
|
||||||
|
ANY rrset empty RRset exists (value indep) dns.RRsetUsed
|
||||||
|
NONE ANY empty Name is not in use dns.NameNotUsed
|
||||||
|
NONE rrset empty RRset does not exist dns.RRsetNotUsed
|
||||||
|
zone rrset rr RRset exists (value dep) dns.Used
|
||||||
|
|
||||||
|
The prerequisite section can also be left empty.
|
||||||
|
If you have decided on the prerequisites you can tell what RRs should
|
||||||
|
be added or deleted. The next table shows the options you have and
|
||||||
|
what functions to call.
|
||||||
|
|
||||||
|
3.4.2.6 - Table Of Metavalues Used In Update Section
|
||||||
|
|
||||||
|
CLASS TYPE RDATA Meaning Function
|
||||||
|
---------------------------------------------------------------
|
||||||
|
ANY ANY empty Delete all RRsets from name dns.RemoveName
|
||||||
|
ANY rrset empty Delete an RRset dns.RemoveRRset
|
||||||
|
NONE rrset rr Delete an RR from RRset dns.Remove
|
||||||
|
zone rrset rr Add to an RRset dns.Insert
|
||||||
|
|
||||||
|
TRANSACTION SIGNATURE
|
||||||
|
|
||||||
|
An TSIG or transaction signature adds a HMAC TSIG record to each message sent.
|
||||||
|
The supported algorithms include: HmacMD5, HmacSHA1, HmacSHA256 and HmacSHA512.
|
||||||
|
|
||||||
|
Basic use pattern when querying with a TSIG name "axfr." (note that these key names
|
||||||
|
must be fully qualified - as they are domain names) and the base64 secret
|
||||||
|
"so6ZGir4GPAqINNh9U5c3A==":
|
||||||
|
|
||||||
|
c := new(dns.Client)
|
||||||
|
c.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="}
|
||||||
|
m := new(dns.Msg)
|
||||||
|
m.SetQuestion("miek.nl.", dns.TypeMX)
|
||||||
|
m.SetTsig("axfr.", dns.HmacMD5, 300, time.Now().Unix())
|
||||||
|
...
|
||||||
|
// When sending the TSIG RR is calculated and filled in before sending
|
||||||
|
|
||||||
|
When requesting an zone transfer (almost all TSIG usage is when requesting zone transfers), with
|
||||||
|
TSIG, this is the basic use pattern. In this example we request an AXFR for
|
||||||
|
miek.nl. with TSIG key named "axfr." and secret "so6ZGir4GPAqINNh9U5c3A=="
|
||||||
|
and using the server 176.58.119.54:
|
||||||
|
|
||||||
|
t := new(dns.Transfer)
|
||||||
|
m := new(dns.Msg)
|
||||||
|
t.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="}
|
||||||
|
m.SetAxfr("miek.nl.")
|
||||||
|
m.SetTsig("axfr.", dns.HmacMD5, 300, time.Now().Unix())
|
||||||
|
c, err := t.In(m, "176.58.119.54:53")
|
||||||
|
for r := range c { ... }
|
||||||
|
|
||||||
|
You can now read the records from the transfer as they come in. Each envelope is checked with TSIG.
|
||||||
|
If something is not correct an error is returned.
|
||||||
|
|
||||||
|
Basic use pattern validating and replying to a message that has TSIG set.
|
||||||
|
|
||||||
|
server := &dns.Server{Addr: ":53", Net: "udp"}
|
||||||
|
server.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="}
|
||||||
|
go server.ListenAndServe()
|
||||||
|
dns.HandleFunc(".", handleRequest)
|
||||||
|
|
||||||
|
func handleRequest(w dns.ResponseWriter, r *dns.Msg) {
|
||||||
|
m := new(dns.Msg)
|
||||||
|
m.SetReply(r)
|
||||||
|
if r.IsTsig() != nil {
|
||||||
|
if w.TsigStatus() == nil {
|
||||||
|
// *Msg r has an TSIG record and it was validated
|
||||||
|
m.SetTsig("axfr.", dns.HmacMD5, 300, time.Now().Unix())
|
||||||
|
} else {
|
||||||
|
// *Msg r has an TSIG records and it was not valided
|
||||||
|
}
|
||||||
|
}
|
||||||
|
w.WriteMsg(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
PRIVATE RRS
|
||||||
|
|
||||||
|
RFC 6895 sets aside a range of type codes for private use. This range
|
||||||
|
is 65,280 - 65,534 (0xFF00 - 0xFFFE). When experimenting with new Resource Records these
|
||||||
|
can be used, before requesting an official type code from IANA.
|
||||||
|
|
||||||
|
see http://miek.nl/posts/2014/Sep/21/Private%20RRs%20and%20IDN%20in%20Go%20DNS/ for more
|
||||||
|
information.
|
||||||
|
|
||||||
|
EDNS0
|
||||||
|
|
||||||
|
EDNS0 is an extension mechanism for the DNS defined in RFC 2671 and updated
|
||||||
|
by RFC 6891. It defines an new RR type, the OPT RR, which is then completely
|
||||||
|
abused.
|
||||||
|
Basic use pattern for creating an (empty) OPT RR:
|
||||||
|
|
||||||
|
o := new(dns.OPT)
|
||||||
|
o.Hdr.Name = "." // MUST be the root zone, per definition.
|
||||||
|
o.Hdr.Rrtype = dns.TypeOPT
|
||||||
|
|
||||||
|
The rdata of an OPT RR consists out of a slice of EDNS0 (RFC 6891)
|
||||||
|
interfaces. Currently only a few have been standardized: EDNS0_NSID
|
||||||
|
(RFC 5001) and EDNS0_SUBNET (draft-vandergaast-edns-client-subnet-02). Note
|
||||||
|
that these options may be combined in an OPT RR.
|
||||||
|
Basic use pattern for a server to check if (and which) options are set:
|
||||||
|
|
||||||
|
// o is a dns.OPT
|
||||||
|
for _, s := range o.Option {
|
||||||
|
switch e := s.(type) {
|
||||||
|
case *dns.EDNS0_NSID:
|
||||||
|
// do stuff with e.Nsid
|
||||||
|
case *dns.EDNS0_SUBNET:
|
||||||
|
// access e.Family, e.Address, etc.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SIG(0)
|
||||||
|
|
||||||
|
From RFC 2931:
|
||||||
|
|
||||||
|
SIG(0) provides protection for DNS transactions and requests ....
|
||||||
|
... protection for glue records, DNS requests, protection for message headers
|
||||||
|
on requests and responses, and protection of the overall integrity of a response.
|
||||||
|
|
||||||
|
It works like TSIG, except that SIG(0) uses public key cryptography, instead of the shared
|
||||||
|
secret approach in TSIG.
|
||||||
|
Supported algorithms: DSA, ECDSAP256SHA256, ECDSAP384SHA384, RSASHA1, RSASHA256 and
|
||||||
|
RSASHA512.
|
||||||
|
|
||||||
|
Signing subsequent messages in multi-message sessions is not implemented.
|
||||||
|
*/
|
||||||
|
package dns
|
156
vendor/github.com/miekg/dns/edns.go
generated
vendored
156
vendor/github.com/miekg/dns/edns.go
generated
vendored
@ -1,29 +1,3 @@
|
|||||||
// EDNS0
|
|
||||||
//
|
|
||||||
// EDNS0 is an extension mechanism for the DNS defined in RFC 2671 and updated
|
|
||||||
// by RFC 6891. It defines an new RR type, the OPT RR, which is then completely
|
|
||||||
// abused.
|
|
||||||
// Basic use pattern for creating an (empty) OPT RR:
|
|
||||||
//
|
|
||||||
// o := new(dns.OPT)
|
|
||||||
// o.Hdr.Name = "." // MUST be the root zone, per definition.
|
|
||||||
// o.Hdr.Rrtype = dns.TypeOPT
|
|
||||||
//
|
|
||||||
// The rdata of an OPT RR consists out of a slice of EDNS0 (RFC 6891)
|
|
||||||
// interfaces. Currently only a few have been standardized: EDNS0_NSID
|
|
||||||
// (RFC 5001) and EDNS0_SUBNET (draft-vandergaast-edns-client-subnet-02). Note
|
|
||||||
// that these options may be combined in an OPT RR.
|
|
||||||
// Basic use pattern for a server to check if (and which) options are set:
|
|
||||||
//
|
|
||||||
// // o is a dns.OPT
|
|
||||||
// for _, s := range o.Option {
|
|
||||||
// switch e := s.(type) {
|
|
||||||
// case *dns.EDNS0_NSID:
|
|
||||||
// // do stuff with e.Nsid
|
|
||||||
// case *dns.EDNS0_SUBNET:
|
|
||||||
// // access e.Family, e.Address, etc.
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -44,18 +18,18 @@ const (
|
|||||||
EDNS0SUBNET = 0x8 // client-subnet (RFC6891)
|
EDNS0SUBNET = 0x8 // client-subnet (RFC6891)
|
||||||
EDNS0EXPIRE = 0x9 // EDNS0 expire
|
EDNS0EXPIRE = 0x9 // EDNS0 expire
|
||||||
EDNS0SUBNETDRAFT = 0x50fa // Don't use! Use EDNS0SUBNET
|
EDNS0SUBNETDRAFT = 0x50fa // Don't use! Use EDNS0SUBNET
|
||||||
|
EDNS0LOCALSTART = 0xFDE9 // Beginning of range reserved for local/experimental use (RFC6891)
|
||||||
|
EDNS0LOCALEND = 0xFFFE // End of range reserved for local/experimental use (RFC6891)
|
||||||
_DO = 1 << 15 // dnssec ok
|
_DO = 1 << 15 // dnssec ok
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// OPT is the EDNS0 RR appended to messages to convey extra (meta) information.
|
||||||
|
// See RFC 6891.
|
||||||
type OPT struct {
|
type OPT struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Option []EDNS0 `dns:"opt"`
|
Option []EDNS0 `dns:"opt"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rr *OPT) Header() *RR_Header {
|
|
||||||
return &rr.Hdr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rr *OPT) String() string {
|
func (rr *OPT) String() string {
|
||||||
s := "\n;; OPT PSEUDOSECTION:\n; EDNS: version " + strconv.Itoa(int(rr.Version())) + "; "
|
s := "\n;; OPT PSEUDOSECTION:\n; EDNS: version " + strconv.Itoa(int(rr.Version())) + "; "
|
||||||
if rr.Do() {
|
if rr.Do() {
|
||||||
@ -92,6 +66,8 @@ func (rr *OPT) String() string {
|
|||||||
s += "\n; DS HASH UNDERSTOOD: " + o.String()
|
s += "\n; DS HASH UNDERSTOOD: " + o.String()
|
||||||
case *EDNS0_N3U:
|
case *EDNS0_N3U:
|
||||||
s += "\n; NSEC3 HASH UNDERSTOOD: " + o.String()
|
s += "\n; NSEC3 HASH UNDERSTOOD: " + o.String()
|
||||||
|
case *EDNS0_LOCAL:
|
||||||
|
s += "\n; LOCAL OPT: " + o.String()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
@ -100,16 +76,13 @@ func (rr *OPT) String() string {
|
|||||||
func (rr *OPT) len() int {
|
func (rr *OPT) len() int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len()
|
||||||
for i := 0; i < len(rr.Option); i++ {
|
for i := 0; i < len(rr.Option); i++ {
|
||||||
|
l += 4 // Account for 2-byte option code and 2-byte option length.
|
||||||
lo, _ := rr.Option[i].pack()
|
lo, _ := rr.Option[i].pack()
|
||||||
l += 2 + len(lo)
|
l += len(lo)
|
||||||
}
|
}
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rr *OPT) copy() RR {
|
|
||||||
return &OPT{*rr.Hdr.copyHeader(), rr.Option}
|
|
||||||
}
|
|
||||||
|
|
||||||
// return the old value -> delete SetVersion?
|
// return the old value -> delete SetVersion?
|
||||||
|
|
||||||
// Version returns the EDNS version used. Only zero is defined.
|
// Version returns the EDNS version used. Only zero is defined.
|
||||||
@ -195,7 +168,7 @@ func (e *EDNS0_NSID) Option() uint16 { return EDNS0NSID }
|
|||||||
func (e *EDNS0_NSID) unpack(b []byte) error { e.Nsid = hex.EncodeToString(b); return nil }
|
func (e *EDNS0_NSID) unpack(b []byte) error { e.Nsid = hex.EncodeToString(b); return nil }
|
||||||
func (e *EDNS0_NSID) String() string { return string(e.Nsid) }
|
func (e *EDNS0_NSID) String() string { return string(e.Nsid) }
|
||||||
|
|
||||||
// The subnet EDNS0 option is used to give the remote nameserver
|
// EDNS0_SUBNET is the subnet option that is used to give the remote nameserver
|
||||||
// an idea of where the client lives. It can then give back a different
|
// an idea of where the client lives. It can then give back a different
|
||||||
// answer depending on the location or network topology.
|
// answer depending on the location or network topology.
|
||||||
// Basic use pattern for creating an subnet option:
|
// Basic use pattern for creating an subnet option:
|
||||||
@ -211,6 +184,11 @@ func (e *EDNS0_NSID) String() string { return string(e.Nsid) }
|
|||||||
// e.Address = net.ParseIP("127.0.0.1").To4() // for IPv4
|
// e.Address = net.ParseIP("127.0.0.1").To4() // for IPv4
|
||||||
// // e.Address = net.ParseIP("2001:7b8:32a::2") // for IPV6
|
// // e.Address = net.ParseIP("2001:7b8:32a::2") // for IPV6
|
||||||
// o.Option = append(o.Option, e)
|
// o.Option = append(o.Option, e)
|
||||||
|
//
|
||||||
|
// Note: the spec (draft-ietf-dnsop-edns-client-subnet-00) has some insane logic
|
||||||
|
// for which netmask applies to the address. This code will parse all the
|
||||||
|
// available bits when unpacking (up to optlen). When packing it will apply
|
||||||
|
// SourceNetmask. If you need more advanced logic, patches welcome and good luck.
|
||||||
type EDNS0_SUBNET struct {
|
type EDNS0_SUBNET struct {
|
||||||
Code uint16 // Always EDNS0SUBNET
|
Code uint16 // Always EDNS0SUBNET
|
||||||
Family uint16 // 1 for IP, 2 for IP6
|
Family uint16 // 1 for IP, 2 for IP6
|
||||||
@ -237,38 +215,22 @@ func (e *EDNS0_SUBNET) pack() ([]byte, error) {
|
|||||||
if e.SourceNetmask > net.IPv4len*8 {
|
if e.SourceNetmask > net.IPv4len*8 {
|
||||||
return nil, errors.New("dns: bad netmask")
|
return nil, errors.New("dns: bad netmask")
|
||||||
}
|
}
|
||||||
ip := make([]byte, net.IPv4len)
|
if len(e.Address.To4()) != net.IPv4len {
|
||||||
a := e.Address.To4().Mask(net.CIDRMask(int(e.SourceNetmask), net.IPv4len*8))
|
return nil, errors.New("dns: bad address")
|
||||||
for i := 0; i < net.IPv4len; i++ {
|
|
||||||
if i+1 > len(e.Address) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
ip[i] = a[i]
|
|
||||||
}
|
}
|
||||||
needLength := e.SourceNetmask / 8
|
ip := e.Address.To4().Mask(net.CIDRMask(int(e.SourceNetmask), net.IPv4len*8))
|
||||||
if e.SourceNetmask%8 > 0 {
|
needLength := (e.SourceNetmask + 8 - 1) / 8 // division rounding up
|
||||||
needLength++
|
b = append(b, ip[:needLength]...)
|
||||||
}
|
|
||||||
ip = ip[:needLength]
|
|
||||||
b = append(b, ip...)
|
|
||||||
case 2:
|
case 2:
|
||||||
if e.SourceNetmask > net.IPv6len*8 {
|
if e.SourceNetmask > net.IPv6len*8 {
|
||||||
return nil, errors.New("dns: bad netmask")
|
return nil, errors.New("dns: bad netmask")
|
||||||
}
|
}
|
||||||
ip := make([]byte, net.IPv6len)
|
if len(e.Address) != net.IPv6len {
|
||||||
a := e.Address.Mask(net.CIDRMask(int(e.SourceNetmask), net.IPv6len*8))
|
return nil, errors.New("dns: bad address")
|
||||||
for i := 0; i < net.IPv6len; i++ {
|
|
||||||
if i+1 > len(e.Address) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
ip[i] = a[i]
|
|
||||||
}
|
}
|
||||||
needLength := e.SourceNetmask / 8
|
ip := e.Address.Mask(net.CIDRMask(int(e.SourceNetmask), net.IPv6len*8))
|
||||||
if e.SourceNetmask%8 > 0 {
|
needLength := (e.SourceNetmask + 8 - 1) / 8 // division rounding up
|
||||||
needLength++
|
b = append(b, ip[:needLength]...)
|
||||||
}
|
|
||||||
ip = ip[:needLength]
|
|
||||||
b = append(b, ip...)
|
|
||||||
default:
|
default:
|
||||||
return nil, errors.New("dns: bad address family")
|
return nil, errors.New("dns: bad address family")
|
||||||
}
|
}
|
||||||
@ -276,8 +238,7 @@ func (e *EDNS0_SUBNET) pack() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *EDNS0_SUBNET) unpack(b []byte) error {
|
func (e *EDNS0_SUBNET) unpack(b []byte) error {
|
||||||
lb := len(b)
|
if len(b) < 4 {
|
||||||
if lb < 4 {
|
|
||||||
return ErrBuf
|
return ErrBuf
|
||||||
}
|
}
|
||||||
e.Family, _ = unpackUint16(b, 0)
|
e.Family, _ = unpackUint16(b, 0)
|
||||||
@ -285,25 +246,27 @@ func (e *EDNS0_SUBNET) unpack(b []byte) error {
|
|||||||
e.SourceScope = b[3]
|
e.SourceScope = b[3]
|
||||||
switch e.Family {
|
switch e.Family {
|
||||||
case 1:
|
case 1:
|
||||||
addr := make([]byte, 4)
|
if e.SourceNetmask > net.IPv4len*8 || e.SourceScope > net.IPv4len*8 {
|
||||||
for i := 0; i < int(e.SourceNetmask/8); i++ {
|
return errors.New("dns: bad netmask")
|
||||||
if i >= len(addr) || 4+i >= len(b) {
|
}
|
||||||
return ErrBuf
|
addr := make([]byte, net.IPv4len)
|
||||||
}
|
for i := 0; i < net.IPv4len && 4+i < len(b); i++ {
|
||||||
addr[i] = b[4+i]
|
addr[i] = b[4+i]
|
||||||
}
|
}
|
||||||
e.Address = net.IPv4(addr[0], addr[1], addr[2], addr[3])
|
e.Address = net.IPv4(addr[0], addr[1], addr[2], addr[3])
|
||||||
case 2:
|
case 2:
|
||||||
addr := make([]byte, 16)
|
if e.SourceNetmask > net.IPv6len*8 || e.SourceScope > net.IPv6len*8 {
|
||||||
for i := 0; i < int(e.SourceNetmask/8); i++ {
|
return errors.New("dns: bad netmask")
|
||||||
if i >= len(addr) || 4+i >= len(b) {
|
}
|
||||||
return ErrBuf
|
addr := make([]byte, net.IPv6len)
|
||||||
}
|
for i := 0; i < net.IPv6len && 4+i < len(b); i++ {
|
||||||
addr[i] = b[4+i]
|
addr[i] = b[4+i]
|
||||||
}
|
}
|
||||||
e.Address = net.IP{addr[0], addr[1], addr[2], addr[3], addr[4],
|
e.Address = net.IP{addr[0], addr[1], addr[2], addr[3], addr[4],
|
||||||
addr[5], addr[6], addr[7], addr[8], addr[9], addr[10],
|
addr[5], addr[6], addr[7], addr[8], addr[9], addr[10],
|
||||||
addr[11], addr[12], addr[13], addr[14], addr[15]}
|
addr[11], addr[12], addr[13], addr[14], addr[15]}
|
||||||
|
default:
|
||||||
|
return errors.New("dns: bad address family")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -320,7 +283,7 @@ func (e *EDNS0_SUBNET) String() (s string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// The UL (Update Lease) EDNS0 (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
|
// http://files.dns-sd.org/draft-sekar-dns-ul.txt
|
||||||
@ -358,7 +321,7 @@ func (e *EDNS0_UL) unpack(b []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Long Lived Queries: http://tools.ietf.org/html/draft-sekar-dns-llq-01
|
// EDNS0_LLQ stands for Long Lived Queries: http://tools.ietf.org/html/draft-sekar-dns-llq-01
|
||||||
// Implemented for completeness, as the EDNS0 type code is assigned.
|
// Implemented for completeness, as the EDNS0 type code is assigned.
|
||||||
type EDNS0_LLQ struct {
|
type EDNS0_LLQ struct {
|
||||||
Code uint16 // Always EDNS0LLQ
|
Code uint16 // Always EDNS0LLQ
|
||||||
@ -499,3 +462,44 @@ func (e *EDNS0_EXPIRE) unpack(b []byte) error {
|
|||||||
e.Expire = uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3])
|
e.Expire = uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3])
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The EDNS0_LOCAL option is used for local/experimental purposes. The option
|
||||||
|
// code is recommended to be within the range [EDNS0LOCALSTART, EDNS0LOCALEND]
|
||||||
|
// (RFC6891), although any unassigned code can actually be used. The content of
|
||||||
|
// the option is made available in Data, unaltered.
|
||||||
|
// Basic use pattern for creating a local option:
|
||||||
|
//
|
||||||
|
// o := new(dns.OPT)
|
||||||
|
// o.Hdr.Name = "."
|
||||||
|
// o.Hdr.Rrtype = dns.TypeOPT
|
||||||
|
// e := new(dns.EDNS0_LOCAL)
|
||||||
|
// e.Code = dns.EDNS0LOCALSTART
|
||||||
|
// e.Data = []byte{72, 82, 74}
|
||||||
|
// o.Option = append(o.Option, e)
|
||||||
|
type EDNS0_LOCAL struct {
|
||||||
|
Code uint16
|
||||||
|
Data []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *EDNS0_LOCAL) Option() uint16 { return e.Code }
|
||||||
|
func (e *EDNS0_LOCAL) String() string {
|
||||||
|
return strconv.FormatInt(int64(e.Code), 10) + ":0x" + hex.EncodeToString(e.Data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *EDNS0_LOCAL) pack() ([]byte, error) {
|
||||||
|
b := make([]byte, len(e.Data))
|
||||||
|
copied := copy(b, e.Data)
|
||||||
|
if copied != len(e.Data) {
|
||||||
|
return nil, ErrBuf
|
||||||
|
}
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *EDNS0_LOCAL) unpack(b []byte) error {
|
||||||
|
e.Data = make([]byte, len(b))
|
||||||
|
copied := copy(e.Data, b)
|
||||||
|
if copied != len(b) {
|
||||||
|
return ErrBuf
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
96
vendor/github.com/miekg/dns/format.go
generated
vendored
Normal file
96
vendor/github.com/miekg/dns/format.go
generated
vendored
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
package dns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NumField returns the number of rdata fields r has.
|
||||||
|
func NumField(r RR) int {
|
||||||
|
return reflect.ValueOf(r).Elem().NumField() - 1 // Remove RR_Header
|
||||||
|
}
|
||||||
|
|
||||||
|
// Field returns the rdata field i as a string. Fields are indexed starting from 1.
|
||||||
|
// RR types that holds slice data, for instance the NSEC type bitmap will return a single
|
||||||
|
// string where the types are concatenated using a space.
|
||||||
|
// Accessing non existing fields will cause a panic.
|
||||||
|
func Field(r RR, i int) string {
|
||||||
|
if i == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
d := reflect.ValueOf(r).Elem().Field(i)
|
||||||
|
switch k := d.Kind(); k {
|
||||||
|
case reflect.String:
|
||||||
|
return d.String()
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
return strconv.FormatInt(d.Int(), 10)
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||||
|
return strconv.FormatUint(d.Uint(), 10)
|
||||||
|
case reflect.Slice:
|
||||||
|
switch reflect.ValueOf(r).Elem().Type().Field(i).Tag {
|
||||||
|
case `dns:"a"`:
|
||||||
|
// TODO(miek): Hmm store this as 16 bytes
|
||||||
|
if d.Len() < net.IPv6len {
|
||||||
|
return net.IPv4(byte(d.Index(0).Uint()),
|
||||||
|
byte(d.Index(1).Uint()),
|
||||||
|
byte(d.Index(2).Uint()),
|
||||||
|
byte(d.Index(3).Uint())).String()
|
||||||
|
}
|
||||||
|
return net.IPv4(byte(d.Index(12).Uint()),
|
||||||
|
byte(d.Index(13).Uint()),
|
||||||
|
byte(d.Index(14).Uint()),
|
||||||
|
byte(d.Index(15).Uint())).String()
|
||||||
|
case `dns:"aaaa"`:
|
||||||
|
return net.IP{
|
||||||
|
byte(d.Index(0).Uint()),
|
||||||
|
byte(d.Index(1).Uint()),
|
||||||
|
byte(d.Index(2).Uint()),
|
||||||
|
byte(d.Index(3).Uint()),
|
||||||
|
byte(d.Index(4).Uint()),
|
||||||
|
byte(d.Index(5).Uint()),
|
||||||
|
byte(d.Index(6).Uint()),
|
||||||
|
byte(d.Index(7).Uint()),
|
||||||
|
byte(d.Index(8).Uint()),
|
||||||
|
byte(d.Index(9).Uint()),
|
||||||
|
byte(d.Index(10).Uint()),
|
||||||
|
byte(d.Index(11).Uint()),
|
||||||
|
byte(d.Index(12).Uint()),
|
||||||
|
byte(d.Index(13).Uint()),
|
||||||
|
byte(d.Index(14).Uint()),
|
||||||
|
byte(d.Index(15).Uint()),
|
||||||
|
}.String()
|
||||||
|
case `dns:"nsec"`:
|
||||||
|
if d.Len() == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
s := Type(d.Index(0).Uint()).String()
|
||||||
|
for i := 1; i < d.Len(); i++ {
|
||||||
|
s += " " + Type(d.Index(i).Uint()).String()
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
case `dns:"wks"`:
|
||||||
|
if d.Len() == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
s := strconv.Itoa(int(d.Index(0).Uint()))
|
||||||
|
for i := 0; i < d.Len(); i++ {
|
||||||
|
s += " " + strconv.Itoa(int(d.Index(i).Uint()))
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
default:
|
||||||
|
// if it does not have a tag its a string slice
|
||||||
|
fallthrough
|
||||||
|
case `dns:"txt"`:
|
||||||
|
if d.Len() == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
s := d.Index(0).String()
|
||||||
|
for i := 1; i < d.Len(); i++ {
|
||||||
|
s += " " + d.Index(i).String()
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
157
vendor/github.com/miekg/dns/keygen.go
generated
vendored
157
vendor/github.com/miekg/dns/keygen.go
generated
vendored
@ -1,157 +0,0 @@
|
|||||||
package dns
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/dsa"
|
|
||||||
"crypto/ecdsa"
|
|
||||||
"crypto/elliptic"
|
|
||||||
"crypto/rand"
|
|
||||||
"crypto/rsa"
|
|
||||||
"math/big"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
const _FORMAT = "Private-key-format: v1.3\n"
|
|
||||||
|
|
||||||
// Empty interface that is used as a wrapper around all possible
|
|
||||||
// private key implementations from the crypto package.
|
|
||||||
type PrivateKey interface{}
|
|
||||||
|
|
||||||
// Generate generates a DNSKEY of the given bit size.
|
|
||||||
// The public part is put inside the DNSKEY record.
|
|
||||||
// The Algorithm in the key must be set as this will define
|
|
||||||
// what kind of DNSKEY will be generated.
|
|
||||||
// The ECDSA algorithms imply a fixed keysize, in that case
|
|
||||||
// bits should be set to the size of the algorithm.
|
|
||||||
func (r *DNSKEY) Generate(bits int) (PrivateKey, error) {
|
|
||||||
switch r.Algorithm {
|
|
||||||
case DSA, DSANSEC3SHA1:
|
|
||||||
if bits != 1024 {
|
|
||||||
return nil, ErrKeySize
|
|
||||||
}
|
|
||||||
case RSAMD5, RSASHA1, RSASHA256, RSASHA1NSEC3SHA1:
|
|
||||||
if bits < 512 || bits > 4096 {
|
|
||||||
return nil, ErrKeySize
|
|
||||||
}
|
|
||||||
case RSASHA512:
|
|
||||||
if bits < 1024 || bits > 4096 {
|
|
||||||
return nil, ErrKeySize
|
|
||||||
}
|
|
||||||
case ECDSAP256SHA256:
|
|
||||||
if bits != 256 {
|
|
||||||
return nil, ErrKeySize
|
|
||||||
}
|
|
||||||
case ECDSAP384SHA384:
|
|
||||||
if bits != 384 {
|
|
||||||
return nil, ErrKeySize
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch r.Algorithm {
|
|
||||||
case DSA, DSANSEC3SHA1:
|
|
||||||
params := new(dsa.Parameters)
|
|
||||||
if err := dsa.GenerateParameters(params, rand.Reader, dsa.L1024N160); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
priv := new(dsa.PrivateKey)
|
|
||||||
priv.PublicKey.Parameters = *params
|
|
||||||
err := dsa.GenerateKey(priv, rand.Reader)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
r.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)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
r.setPublicKeyRSA(priv.PublicKey.E, priv.PublicKey.N)
|
|
||||||
return priv, nil
|
|
||||||
case ECDSAP256SHA256, ECDSAP384SHA384:
|
|
||||||
var c elliptic.Curve
|
|
||||||
switch r.Algorithm {
|
|
||||||
case ECDSAP256SHA256:
|
|
||||||
c = elliptic.P256()
|
|
||||||
case ECDSAP384SHA384:
|
|
||||||
c = elliptic.P384()
|
|
||||||
}
|
|
||||||
priv, err := ecdsa.GenerateKey(c, rand.Reader)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
r.setPublicKeyCurve(priv.PublicKey.X, priv.PublicKey.Y)
|
|
||||||
return priv, nil
|
|
||||||
default:
|
|
||||||
return nil, ErrAlg
|
|
||||||
}
|
|
||||||
return nil, nil // Dummy return
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrivateKeyString converts a PrivateKey to a string. This
|
|
||||||
// string has the same format as the private-key-file of BIND9 (Private-key-format: v1.3).
|
|
||||||
// It needs some info from the key (hashing, keytag), so its a method of the DNSKEY.
|
|
||||||
func (r *DNSKEY) PrivateKeyString(p PrivateKey) (s string) {
|
|
||||||
switch t := p.(type) {
|
|
||||||
case *rsa.PrivateKey:
|
|
||||||
algorithm := strconv.Itoa(int(r.Algorithm)) + " (" + AlgorithmToString[r.Algorithm] + ")"
|
|
||||||
modulus := toBase64(t.PublicKey.N.Bytes())
|
|
||||||
e := big.NewInt(int64(t.PublicKey.E))
|
|
||||||
publicExponent := toBase64(e.Bytes())
|
|
||||||
privateExponent := toBase64(t.D.Bytes())
|
|
||||||
prime1 := toBase64(t.Primes[0].Bytes())
|
|
||||||
prime2 := toBase64(t.Primes[1].Bytes())
|
|
||||||
// Calculate Exponent1/2 and Coefficient as per: http://en.wikipedia.org/wiki/RSA#Using_the_Chinese_remainder_algorithm
|
|
||||||
// and from: http://code.google.com/p/go/issues/detail?id=987
|
|
||||||
one := big.NewInt(1)
|
|
||||||
minusone := big.NewInt(-1)
|
|
||||||
p_1 := big.NewInt(0).Sub(t.Primes[0], one)
|
|
||||||
q_1 := big.NewInt(0).Sub(t.Primes[1], one)
|
|
||||||
exp1 := big.NewInt(0).Mod(t.D, p_1)
|
|
||||||
exp2 := big.NewInt(0).Mod(t.D, q_1)
|
|
||||||
coeff := big.NewInt(0).Exp(t.Primes[1], minusone, t.Primes[0])
|
|
||||||
|
|
||||||
exponent1 := toBase64(exp1.Bytes())
|
|
||||||
exponent2 := toBase64(exp2.Bytes())
|
|
||||||
coefficient := toBase64(coeff.Bytes())
|
|
||||||
|
|
||||||
s = _FORMAT +
|
|
||||||
"Algorithm: " + algorithm + "\n" +
|
|
||||||
"Modules: " + modulus + "\n" +
|
|
||||||
"PublicExponent: " + publicExponent + "\n" +
|
|
||||||
"PrivateExponent: " + privateExponent + "\n" +
|
|
||||||
"Prime1: " + prime1 + "\n" +
|
|
||||||
"Prime2: " + prime2 + "\n" +
|
|
||||||
"Exponent1: " + exponent1 + "\n" +
|
|
||||||
"Exponent2: " + exponent2 + "\n" +
|
|
||||||
"Coefficient: " + coefficient + "\n"
|
|
||||||
case *ecdsa.PrivateKey:
|
|
||||||
algorithm := strconv.Itoa(int(r.Algorithm)) + " (" + AlgorithmToString[r.Algorithm] + ")"
|
|
||||||
var intlen int
|
|
||||||
switch r.Algorithm {
|
|
||||||
case ECDSAP256SHA256:
|
|
||||||
intlen = 32
|
|
||||||
case ECDSAP384SHA384:
|
|
||||||
intlen = 48
|
|
||||||
}
|
|
||||||
private := toBase64(intToBytes(t.D, intlen))
|
|
||||||
s = _FORMAT +
|
|
||||||
"Algorithm: " + algorithm + "\n" +
|
|
||||||
"PrivateKey: " + private + "\n"
|
|
||||||
case *dsa.PrivateKey:
|
|
||||||
algorithm := strconv.Itoa(int(r.Algorithm)) + " (" + AlgorithmToString[r.Algorithm] + ")"
|
|
||||||
T := divRoundUp(divRoundUp(t.PublicKey.Parameters.G.BitLen(), 8)-64, 8)
|
|
||||||
prime := toBase64(intToBytes(t.PublicKey.Parameters.P, 64+T*8))
|
|
||||||
subprime := toBase64(intToBytes(t.PublicKey.Parameters.Q, 20))
|
|
||||||
base := toBase64(intToBytes(t.PublicKey.Parameters.G, 64+T*8))
|
|
||||||
priv := toBase64(intToBytes(t.X, 20))
|
|
||||||
pub := toBase64(intToBytes(t.PublicKey.Y, 64+T*8))
|
|
||||||
s = _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"
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
12
vendor/github.com/miekg/dns/labels.go
generated
vendored
12
vendor/github.com/miekg/dns/labels.go
generated
vendored
@ -4,9 +4,11 @@ package dns
|
|||||||
|
|
||||||
// SplitDomainName splits a name string into it's labels.
|
// SplitDomainName splits a name string into it's labels.
|
||||||
// www.miek.nl. returns []string{"www", "miek", "nl"}
|
// www.miek.nl. returns []string{"www", "miek", "nl"}
|
||||||
|
// .www.miek.nl. returns []string{"", "www", "miek", "nl"},
|
||||||
// The root label (.) returns nil. Note that using
|
// The root label (.) returns nil. Note that using
|
||||||
// strings.Split(s) will work in most cases, but does not handle
|
// strings.Split(s) will work in most cases, but does not handle
|
||||||
// escaped dots (\.) for instance.
|
// escaped dots (\.) for instance.
|
||||||
|
// s must be a syntactically valid domain name, see IsDomainName.
|
||||||
func SplitDomainName(s string) (labels []string) {
|
func SplitDomainName(s string) (labels []string) {
|
||||||
if len(s) == 0 {
|
if len(s) == 0 {
|
||||||
return nil
|
return nil
|
||||||
@ -45,6 +47,8 @@ func SplitDomainName(s string) (labels []string) {
|
|||||||
//
|
//
|
||||||
// www.miek.nl. and miek.nl. have two labels in common: miek and nl
|
// www.miek.nl. and miek.nl. have two labels in common: miek and nl
|
||||||
// www.miek.nl. and www.bla.nl. have one label in common: nl
|
// www.miek.nl. and www.bla.nl. have one label in common: nl
|
||||||
|
//
|
||||||
|
// s1 and s2 must be syntactically valid domain names.
|
||||||
func CompareDomainName(s1, s2 string) (n int) {
|
func CompareDomainName(s1, s2 string) (n int) {
|
||||||
s1 = Fqdn(s1)
|
s1 = Fqdn(s1)
|
||||||
s2 = Fqdn(s2)
|
s2 = Fqdn(s2)
|
||||||
@ -85,6 +89,7 @@ func CompareDomainName(s1, s2 string) (n int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CountLabel counts the the number of labels in the string s.
|
// CountLabel counts the the number of labels in the string s.
|
||||||
|
// s must be a syntactically valid domain name.
|
||||||
func CountLabel(s string) (labels int) {
|
func CountLabel(s string) (labels int) {
|
||||||
if s == "." {
|
if s == "." {
|
||||||
return
|
return
|
||||||
@ -98,12 +103,12 @@ func CountLabel(s string) (labels int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panic("dns: not reached")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Split splits a name s into its label indexes.
|
// Split splits a name s into its label indexes.
|
||||||
// www.miek.nl. returns []int{0, 4, 9}, www.miek.nl also returns []int{0, 4, 9}.
|
// www.miek.nl. returns []int{0, 4, 9}, www.miek.nl also returns []int{0, 4, 9}.
|
||||||
// The root name (.) returns nil. Also see dns.SplitDomainName.
|
// The root name (.) returns nil. Also see SplitDomainName.
|
||||||
|
// s must be a syntactically valid domain name.
|
||||||
func Split(s string) []int {
|
func Split(s string) []int {
|
||||||
if s == "." {
|
if s == "." {
|
||||||
return nil
|
return nil
|
||||||
@ -119,12 +124,12 @@ func Split(s string) []int {
|
|||||||
}
|
}
|
||||||
idx = append(idx, off)
|
idx = append(idx, off)
|
||||||
}
|
}
|
||||||
panic("dns: not reached")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NextLabel returns the index of the start of the next label in the
|
// NextLabel returns the index of the start of the next label in the
|
||||||
// string s starting at offset.
|
// string s starting at offset.
|
||||||
// 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.
|
||||||
func NextLabel(s string, offset int) (i int, end bool) {
|
func NextLabel(s string, offset int) (i int, end bool) {
|
||||||
quote := false
|
quote := false
|
||||||
for i = offset; i < len(s)-1; i++ {
|
for i = offset; i < len(s)-1; i++ {
|
||||||
@ -147,6 +152,7 @@ func NextLabel(s string, offset int) (i int, end bool) {
|
|||||||
// PrevLabel returns the index of the label when starting from the right and
|
// PrevLabel returns the index of the label when starting from the right and
|
||||||
// jumping n labels to the left.
|
// jumping n labels to the left.
|
||||||
// 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.
|
||||||
func PrevLabel(s string, n int) (i int, start bool) {
|
func PrevLabel(s string, n int) (i int, start bool) {
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return len(s), false
|
return len(s), false
|
||||||
|
559
vendor/github.com/miekg/dns/msg.go
generated
vendored
559
vendor/github.com/miekg/dns/msg.go
generated
vendored
@ -23,29 +23,40 @@ import (
|
|||||||
const maxCompressionOffset = 2 << 13 // We have 14 bits for the compression pointer
|
const maxCompressionOffset = 2 << 13 // We have 14 bits for the compression pointer
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrAlg error = &Error{err: "bad algorithm"}
|
// ErrAlg indicates an error with the (DNSSEC) algorithm.
|
||||||
ErrAuth error = &Error{err: "bad authentication"}
|
ErrAlg error = &Error{err: "bad algorithm"}
|
||||||
ErrBuf error = &Error{err: "buffer size too small"}
|
// ErrAuth indicates an error in the TSIG authentication.
|
||||||
ErrConnEmpty error = &Error{err: "conn has no connection"}
|
ErrAuth error = &Error{err: "bad authentication"}
|
||||||
ErrConn error = &Error{err: "conn holds both UDP and TCP connection"}
|
// ErrBuf indicates that the buffer used it too small for the message.
|
||||||
|
ErrBuf error = &Error{err: "buffer size too small"}
|
||||||
|
// ErrConnEmpty indicates a connection is being uses before it is initialized.
|
||||||
|
ErrConnEmpty error = &Error{err: "conn has no connection"}
|
||||||
|
// ErrExtendedRcode ...
|
||||||
ErrExtendedRcode error = &Error{err: "bad extended rcode"}
|
ErrExtendedRcode error = &Error{err: "bad extended rcode"}
|
||||||
ErrFqdn error = &Error{err: "domain must be fully qualified"}
|
// ErrFqdn indicates that a domain name does not have a closing dot.
|
||||||
ErrId error = &Error{err: "id mismatch"}
|
ErrFqdn error = &Error{err: "domain must be fully qualified"}
|
||||||
ErrKeyAlg error = &Error{err: "bad key algorithm"}
|
// ErrId indicates there is a mismatch with the message's ID.
|
||||||
ErrKey error = &Error{err: "bad key"}
|
ErrId error = &Error{err: "id mismatch"}
|
||||||
ErrKeySize error = &Error{err: "bad key size"}
|
// ErrKeyAlg indicates that the algorithm in the key is not valid.
|
||||||
ErrNoSig error = &Error{err: "no signature found"}
|
ErrKeyAlg error = &Error{err: "bad key algorithm"}
|
||||||
ErrPrivKey error = &Error{err: "bad private key"}
|
ErrKey error = &Error{err: "bad key"}
|
||||||
ErrRcode error = &Error{err: "bad rcode"}
|
ErrKeySize error = &Error{err: "bad key size"}
|
||||||
ErrRdata error = &Error{err: "bad rdata"}
|
ErrNoSig error = &Error{err: "no signature found"}
|
||||||
ErrRRset error = &Error{err: "bad rrset"}
|
ErrPrivKey error = &Error{err: "bad private key"}
|
||||||
ErrSecret error = &Error{err: "no secrets defined"}
|
ErrRcode error = &Error{err: "bad rcode"}
|
||||||
ErrServ error = &Error{err: "no servers could be reached"}
|
ErrRdata error = &Error{err: "bad rdata"}
|
||||||
ErrShortRead error = &Error{err: "short read"}
|
ErrRRset error = &Error{err: "bad rrset"}
|
||||||
ErrSig error = &Error{err: "bad signature"}
|
ErrSecret error = &Error{err: "no secrets defined"}
|
||||||
ErrSigGen error = &Error{err: "bad signature generation"}
|
ErrShortRead error = &Error{err: "short read"}
|
||||||
ErrSoa error = &Error{err: "no SOA"}
|
// ErrSig indicates that a signature can not be cryptographically validated.
|
||||||
ErrTime error = &Error{err: "bad time"}
|
ErrSig error = &Error{err: "bad signature"}
|
||||||
|
// ErrSOA indicates that no SOA RR was seen when doing zone transfers.
|
||||||
|
ErrSoa error = &Error{err: "no SOA"}
|
||||||
|
// ErrTime indicates a timing error in TSIG authentication.
|
||||||
|
ErrTime error = &Error{err: "bad time"}
|
||||||
|
// ErrTruncated indicates that we failed to unpack a truncated message.
|
||||||
|
// We unpacked as much as we had so Msg can still be used, if desired.
|
||||||
|
ErrTruncated error = &Error{err: "failed to unpack truncated message"}
|
||||||
)
|
)
|
||||||
|
|
||||||
// Id, by default, returns a 16 bits random number to be used as a
|
// Id, by default, returns a 16 bits random number to be used as a
|
||||||
@ -56,8 +67,7 @@ var (
|
|||||||
// dns.Id = func() uint16 { return 3 }
|
// dns.Id = func() uint16 { return 3 }
|
||||||
var Id func() uint16 = id
|
var Id func() uint16 = id
|
||||||
|
|
||||||
// A manually-unpacked version of (id, bits).
|
// MsgHdr is a a manually-unpacked version of (id, bits).
|
||||||
// This is in its own struct for easy printing.
|
|
||||||
type MsgHdr struct {
|
type MsgHdr struct {
|
||||||
Id uint16
|
Id uint16
|
||||||
Response bool
|
Response bool
|
||||||
@ -72,7 +82,7 @@ type MsgHdr struct {
|
|||||||
Rcode int
|
Rcode int
|
||||||
}
|
}
|
||||||
|
|
||||||
// The layout of a DNS message.
|
// Msg contains the layout of a DNS message.
|
||||||
type Msg struct {
|
type Msg struct {
|
||||||
MsgHdr
|
MsgHdr
|
||||||
Compress bool `json:"-"` // If true, the message will be compressed when converted to wire format. This not part of the official DNS packet format.
|
Compress bool `json:"-"` // If true, the message will be compressed when converted to wire format. This not part of the official DNS packet format.
|
||||||
@ -82,87 +92,10 @@ type Msg struct {
|
|||||||
Extra []RR // Holds the RR(s) of the additional section.
|
Extra []RR // Holds the RR(s) of the additional section.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map of strings for each RR wire type.
|
// StringToType is the reverse of TypeToString, needed for string parsing.
|
||||||
var TypeToString = map[uint16]string{
|
|
||||||
TypeA: "A",
|
|
||||||
TypeAAAA: "AAAA",
|
|
||||||
TypeAFSDB: "AFSDB",
|
|
||||||
TypeANY: "ANY", // Meta RR
|
|
||||||
TypeATMA: "ATMA",
|
|
||||||
TypeAXFR: "AXFR", // Meta RR
|
|
||||||
TypeCAA: "CAA",
|
|
||||||
TypeCDNSKEY: "CDNSKEY",
|
|
||||||
TypeCDS: "CDS",
|
|
||||||
TypeCERT: "CERT",
|
|
||||||
TypeCNAME: "CNAME",
|
|
||||||
TypeDHCID: "DHCID",
|
|
||||||
TypeDLV: "DLV",
|
|
||||||
TypeDNAME: "DNAME",
|
|
||||||
TypeDNSKEY: "DNSKEY",
|
|
||||||
TypeDS: "DS",
|
|
||||||
TypeEID: "EID",
|
|
||||||
TypeEUI48: "EUI48",
|
|
||||||
TypeEUI64: "EUI64",
|
|
||||||
TypeGID: "GID",
|
|
||||||
TypeGPOS: "GPOS",
|
|
||||||
TypeHINFO: "HINFO",
|
|
||||||
TypeHIP: "HIP",
|
|
||||||
TypeIPSECKEY: "IPSECKEY",
|
|
||||||
TypeISDN: "ISDN",
|
|
||||||
TypeIXFR: "IXFR", // Meta RR
|
|
||||||
TypeKEY: "KEY",
|
|
||||||
TypeKX: "KX",
|
|
||||||
TypeL32: "L32",
|
|
||||||
TypeL64: "L64",
|
|
||||||
TypeLOC: "LOC",
|
|
||||||
TypeLP: "LP",
|
|
||||||
TypeMB: "MB",
|
|
||||||
TypeMD: "MD",
|
|
||||||
TypeMF: "MF",
|
|
||||||
TypeMG: "MG",
|
|
||||||
TypeMINFO: "MINFO",
|
|
||||||
TypeMR: "MR",
|
|
||||||
TypeMX: "MX",
|
|
||||||
TypeNAPTR: "NAPTR",
|
|
||||||
TypeNID: "NID",
|
|
||||||
TypeNINFO: "NINFO",
|
|
||||||
TypeNIMLOC: "NIMLOC",
|
|
||||||
TypeNS: "NS",
|
|
||||||
TypeNSAP: "NSAP",
|
|
||||||
TypeNSAPPTR: "NSAP-PTR",
|
|
||||||
TypeNSEC3: "NSEC3",
|
|
||||||
TypeNSEC3PARAM: "NSEC3PARAM",
|
|
||||||
TypeNSEC: "NSEC",
|
|
||||||
TypeNULL: "NULL",
|
|
||||||
TypeOPT: "OPT",
|
|
||||||
TypeOPENPGPKEY: "OPENPGPKEY",
|
|
||||||
TypePTR: "PTR",
|
|
||||||
TypeRKEY: "RKEY",
|
|
||||||
TypeRP: "RP",
|
|
||||||
TypeRRSIG: "RRSIG",
|
|
||||||
TypeRT: "RT",
|
|
||||||
TypeSIG: "SIG",
|
|
||||||
TypeSOA: "SOA",
|
|
||||||
TypeSPF: "SPF",
|
|
||||||
TypeSRV: "SRV",
|
|
||||||
TypeSSHFP: "SSHFP",
|
|
||||||
TypeTA: "TA",
|
|
||||||
TypeTALINK: "TALINK",
|
|
||||||
TypeTKEY: "TKEY", // Meta RR
|
|
||||||
TypeTLSA: "TLSA",
|
|
||||||
TypeTSIG: "TSIG", // Meta RR
|
|
||||||
TypeTXT: "TXT",
|
|
||||||
TypePX: "PX",
|
|
||||||
TypeUID: "UID",
|
|
||||||
TypeUINFO: "UINFO",
|
|
||||||
TypeUNSPEC: "UNSPEC",
|
|
||||||
TypeURI: "URI",
|
|
||||||
TypeWKS: "WKS",
|
|
||||||
TypeX25: "X25",
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reverse, needed for string parsing.
|
|
||||||
var StringToType = reverseInt16(TypeToString)
|
var StringToType = reverseInt16(TypeToString)
|
||||||
|
|
||||||
|
// StringToClass is the reverse of ClassToString, needed for string parsing.
|
||||||
var StringToClass = reverseInt16(ClassToString)
|
var StringToClass = reverseInt16(ClassToString)
|
||||||
|
|
||||||
// Map of opcodes strings.
|
// Map of opcodes strings.
|
||||||
@ -171,7 +104,7 @@ var StringToOpcode = reverseInt(OpcodeToString)
|
|||||||
// Map of rcodes strings.
|
// Map of rcodes strings.
|
||||||
var StringToRcode = reverseInt(RcodeToString)
|
var StringToRcode = reverseInt(RcodeToString)
|
||||||
|
|
||||||
// Map of strings for each CLASS wire type.
|
// ClassToString is a maps Classes to strings for each CLASS wire type.
|
||||||
var ClassToString = map[uint16]string{
|
var ClassToString = map[uint16]string{
|
||||||
ClassINET: "IN",
|
ClassINET: "IN",
|
||||||
ClassCSNET: "CS",
|
ClassCSNET: "CS",
|
||||||
@ -181,7 +114,7 @@ var ClassToString = map[uint16]string{
|
|||||||
ClassANY: "ANY",
|
ClassANY: "ANY",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map of strings for opcodes.
|
// OpcodeToString maps Opcodes to strings.
|
||||||
var OpcodeToString = map[int]string{
|
var OpcodeToString = map[int]string{
|
||||||
OpcodeQuery: "QUERY",
|
OpcodeQuery: "QUERY",
|
||||||
OpcodeIQuery: "IQUERY",
|
OpcodeIQuery: "IQUERY",
|
||||||
@ -190,7 +123,7 @@ var OpcodeToString = map[int]string{
|
|||||||
OpcodeUpdate: "UPDATE",
|
OpcodeUpdate: "UPDATE",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map of strings for rcodes.
|
// RcodeToString maps Rcodes to strings.
|
||||||
var RcodeToString = map[int]string{
|
var RcodeToString = map[int]string{
|
||||||
RcodeSuccess: "NOERROR",
|
RcodeSuccess: "NOERROR",
|
||||||
RcodeFormatError: "FORMERR",
|
RcodeFormatError: "FORMERR",
|
||||||
@ -225,7 +158,7 @@ var RcodeToString = map[int]string{
|
|||||||
// PackDomainName packs a domain name s into msg[off:].
|
// PackDomainName packs a domain name s into msg[off:].
|
||||||
// If compression is wanted compress must be true and the compression
|
// If compression is wanted compress must be true and the compression
|
||||||
// map needs to hold a mapping between domain names and offsets
|
// map needs to hold a mapping between domain names and offsets
|
||||||
// pointing into msg[].
|
// pointing into msg.
|
||||||
func PackDomainName(s string, msg []byte, off int, compression map[string]int, compress bool) (off1 int, err error) {
|
func PackDomainName(s string, msg []byte, off int, compression map[string]int, compress bool) (off1 int, err error) {
|
||||||
off1, _, err = packDomainName(s, msg, off, compression, compress)
|
off1, _, err = packDomainName(s, msg, off, compression, compress)
|
||||||
return
|
return
|
||||||
@ -264,7 +197,7 @@ func packDomainName(s string, msg []byte, off int, compression map[string]int, c
|
|||||||
// Emit sequence of counted strings, chopping at dots.
|
// Emit sequence of counted strings, chopping at dots.
|
||||||
begin := 0
|
begin := 0
|
||||||
bs := []byte(s)
|
bs := []byte(s)
|
||||||
ro_bs, bs_fresh, escaped_dot := s, true, false
|
roBs, bsFresh, escapedDot := s, true, false
|
||||||
for i := 0; i < ls; i++ {
|
for i := 0; i < ls; i++ {
|
||||||
if bs[i] == '\\' {
|
if bs[i] == '\\' {
|
||||||
for j := i; j < ls-1; j++ {
|
for j := i; j < ls-1; j++ {
|
||||||
@ -288,13 +221,13 @@ func packDomainName(s string, msg []byte, off int, compression map[string]int, c
|
|||||||
} else if bs[i] == 'n' {
|
} else if bs[i] == 'n' {
|
||||||
bs[i] = '\n'
|
bs[i] = '\n'
|
||||||
}
|
}
|
||||||
escaped_dot = bs[i] == '.'
|
escapedDot = bs[i] == '.'
|
||||||
bs_fresh = false
|
bsFresh = false
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if bs[i] == '.' {
|
if bs[i] == '.' {
|
||||||
if i > 0 && bs[i-1] == '.' && !escaped_dot {
|
if i > 0 && bs[i-1] == '.' && !escapedDot {
|
||||||
// two dots back to back is not legal
|
// two dots back to back is not legal
|
||||||
return lenmsg, labels, ErrRdata
|
return lenmsg, labels, ErrRdata
|
||||||
}
|
}
|
||||||
@ -320,16 +253,16 @@ func packDomainName(s string, msg []byte, off int, compression map[string]int, c
|
|||||||
}
|
}
|
||||||
off++
|
off++
|
||||||
}
|
}
|
||||||
if compress && !bs_fresh {
|
if compress && !bsFresh {
|
||||||
ro_bs = string(bs)
|
roBs = string(bs)
|
||||||
bs_fresh = true
|
bsFresh = true
|
||||||
}
|
}
|
||||||
// Dont try to compress '.'
|
// Don't try to compress '.'
|
||||||
if compress && ro_bs[begin:] != "." {
|
if compress && roBs[begin:] != "." {
|
||||||
if p, ok := compression[ro_bs[begin:]]; !ok {
|
if p, ok := compression[roBs[begin:]]; !ok {
|
||||||
// Only offsets smaller than this can be used.
|
// Only offsets smaller than this can be used.
|
||||||
if offset < maxCompressionOffset {
|
if offset < maxCompressionOffset {
|
||||||
compression[ro_bs[begin:]] = offset
|
compression[roBs[begin:]] = offset
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// The first hit is the longest matching dname
|
// The first hit is the longest matching dname
|
||||||
@ -348,7 +281,7 @@ func packDomainName(s string, msg []byte, off int, compression map[string]int, c
|
|||||||
labels++
|
labels++
|
||||||
begin = i + 1
|
begin = i + 1
|
||||||
}
|
}
|
||||||
escaped_dot = false
|
escapedDot = false
|
||||||
}
|
}
|
||||||
// Root label is special
|
// Root label is special
|
||||||
if len(bs) == 1 && bs[0] == '.' {
|
if len(bs) == 1 && bs[0] == '.' {
|
||||||
@ -401,9 +334,6 @@ Loop:
|
|||||||
case 0x00:
|
case 0x00:
|
||||||
if c == 0x00 {
|
if c == 0x00 {
|
||||||
// end of name
|
// end of name
|
||||||
if len(s) == 0 {
|
|
||||||
return ".", off, nil
|
|
||||||
}
|
|
||||||
break Loop
|
break Loop
|
||||||
}
|
}
|
||||||
// literal string
|
// literal string
|
||||||
@ -464,6 +394,9 @@ Loop:
|
|||||||
if ptr == 0 {
|
if ptr == 0 {
|
||||||
off1 = off
|
off1 = off
|
||||||
}
|
}
|
||||||
|
if len(s) == 0 {
|
||||||
|
s = []byte(".")
|
||||||
|
}
|
||||||
return string(s), off1, nil
|
return string(s), off1, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -531,17 +464,46 @@ func packTxtString(s string, msg []byte, offset int, tmp []byte) (int, error) {
|
|||||||
return offset, nil
|
return offset, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func unpackTxt(msg []byte, offset, rdend int) ([]string, int, error) {
|
func packOctetString(s string, msg []byte, offset int, tmp []byte) (int, error) {
|
||||||
var err error
|
if offset >= len(msg) {
|
||||||
var ss []string
|
return offset, ErrBuf
|
||||||
|
}
|
||||||
|
bs := tmp[:len(s)]
|
||||||
|
copy(bs, s)
|
||||||
|
for i := 0; i < len(bs); i++ {
|
||||||
|
if len(msg) <= offset {
|
||||||
|
return offset, ErrBuf
|
||||||
|
}
|
||||||
|
if bs[i] == '\\' {
|
||||||
|
i++
|
||||||
|
if i == len(bs) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// check for \DDD
|
||||||
|
if i+2 < len(bs) && isDigit(bs[i]) && isDigit(bs[i+1]) && isDigit(bs[i+2]) {
|
||||||
|
msg[offset] = dddToByte(bs[i:])
|
||||||
|
i += 2
|
||||||
|
} else {
|
||||||
|
msg[offset] = bs[i]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
msg[offset] = bs[i]
|
||||||
|
}
|
||||||
|
offset++
|
||||||
|
}
|
||||||
|
return offset, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func unpackTxt(msg []byte, off0 int) (ss []string, off int, err error) {
|
||||||
|
off = off0
|
||||||
var s string
|
var s string
|
||||||
for offset < rdend && err == nil {
|
for off < len(msg) && err == nil {
|
||||||
s, offset, err = unpackTxtString(msg, offset)
|
s, off, err = unpackTxtString(msg, off)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
ss = append(ss, s)
|
ss = append(ss, s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ss, offset, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func unpackTxtString(msg []byte, offset int) (string, int, error) {
|
func unpackTxtString(msg []byte, offset int) (string, int, error) {
|
||||||
@ -652,6 +614,12 @@ func packStructValue(val reflect.Value, msg []byte, off int, compression map[str
|
|||||||
off += len(b)
|
off += len(b)
|
||||||
}
|
}
|
||||||
case `dns:"a"`:
|
case `dns:"a"`:
|
||||||
|
if val.Type().String() == "dns.IPSECKEY" {
|
||||||
|
// Field(2) is GatewayType, must be 1
|
||||||
|
if val.Field(2).Uint() != 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
// It must be a slice of 4, even if it is 16, we encode
|
// It must be a slice of 4, even if it is 16, we encode
|
||||||
// only the first 4
|
// only the first 4
|
||||||
if off+net.IPv4len > lenmsg {
|
if off+net.IPv4len > lenmsg {
|
||||||
@ -676,6 +644,12 @@ func packStructValue(val reflect.Value, msg []byte, off int, compression map[str
|
|||||||
return lenmsg, &Error{err: "overflow packing a"}
|
return lenmsg, &Error{err: "overflow packing a"}
|
||||||
}
|
}
|
||||||
case `dns:"aaaa"`:
|
case `dns:"aaaa"`:
|
||||||
|
if val.Type().String() == "dns.IPSECKEY" {
|
||||||
|
// Field(2) is GatewayType, must be 2
|
||||||
|
if val.Field(2).Uint() != 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
if fv.Len() == 0 {
|
if fv.Len() == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -694,58 +668,49 @@ func packStructValue(val reflect.Value, msg []byte, off int, compression map[str
|
|||||||
if val.Field(i).Len() == 0 {
|
if val.Field(i).Len() == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
var bitmapbyte uint16
|
off1 := off
|
||||||
for j := 0; j < val.Field(i).Len(); j++ {
|
for j := 0; j < val.Field(i).Len(); j++ {
|
||||||
serv := uint16((fv.Index(j).Uint()))
|
serv := int(fv.Index(j).Uint())
|
||||||
bitmapbyte = uint16(serv / 8)
|
if off+serv/8+1 > len(msg) {
|
||||||
if int(bitmapbyte) > lenmsg {
|
return len(msg), &Error{err: "overflow packing wks"}
|
||||||
return lenmsg, &Error{err: "overflow packing wks"}
|
}
|
||||||
|
msg[off+serv/8] |= byte(1 << (7 - uint(serv%8)))
|
||||||
|
if off+serv/8+1 > off1 {
|
||||||
|
off1 = off + serv/8 + 1
|
||||||
}
|
}
|
||||||
bit := uint16(serv) - bitmapbyte*8
|
|
||||||
msg[bitmapbyte] = byte(1 << (7 - bit))
|
|
||||||
}
|
}
|
||||||
off += int(bitmapbyte)
|
off = off1
|
||||||
case `dns:"nsec"`: // NSEC/NSEC3
|
case `dns:"nsec"`: // NSEC/NSEC3
|
||||||
// This is the uint16 type bitmap
|
// This is the uint16 type bitmap
|
||||||
if val.Field(i).Len() == 0 {
|
if val.Field(i).Len() == 0 {
|
||||||
// Do absolutely nothing
|
// Do absolutely nothing
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
var lastwindow, lastlength uint16
|
||||||
lastwindow := uint16(0)
|
|
||||||
length := uint16(0)
|
|
||||||
if off+2 > lenmsg {
|
|
||||||
return lenmsg, &Error{err: "overflow packing nsecx"}
|
|
||||||
}
|
|
||||||
for j := 0; j < val.Field(i).Len(); j++ {
|
for j := 0; j < val.Field(i).Len(); j++ {
|
||||||
t := uint16((fv.Index(j).Uint()))
|
t := uint16(fv.Index(j).Uint())
|
||||||
window := uint16(t / 256)
|
window := t / 256
|
||||||
if lastwindow != window {
|
length := (t-window*256)/8 + 1
|
||||||
|
if window > lastwindow && lastlength != 0 {
|
||||||
// New window, jump to the new offset
|
// New window, jump to the new offset
|
||||||
off += int(length) + 3
|
off += int(lastlength) + 2
|
||||||
if off > lenmsg {
|
lastlength = 0
|
||||||
return lenmsg, &Error{err: "overflow packing nsecx bitmap"}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
length = (t - window*256) / 8
|
if window < lastwindow || length < lastlength {
|
||||||
bit := t - (window * 256) - (length * 8)
|
return len(msg), &Error{err: "nsec bits out of order"}
|
||||||
if off+2+int(length) > lenmsg {
|
}
|
||||||
return lenmsg, &Error{err: "overflow packing nsecx bitmap"}
|
if off+2+int(length) > len(msg) {
|
||||||
|
return len(msg), &Error{err: "overflow packing nsec"}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setting the window #
|
// Setting the window #
|
||||||
msg[off] = byte(window)
|
msg[off] = byte(window)
|
||||||
// Setting the octets length
|
// Setting the octets length
|
||||||
msg[off+1] = byte(length + 1)
|
msg[off+1] = byte(length)
|
||||||
// Setting the bit value for the type in the right octet
|
// Setting the bit value for the type in the right octet
|
||||||
msg[off+2+int(length)] |= byte(1 << (7 - bit))
|
msg[off+1+int(length)] |= byte(1 << (7 - (t % 8)))
|
||||||
lastwindow = window
|
lastwindow, lastlength = window, length
|
||||||
}
|
|
||||||
off += 2 + int(length)
|
|
||||||
off++
|
|
||||||
if off > lenmsg {
|
|
||||||
return lenmsg, &Error{err: "overflow packing nsecx bitmap"}
|
|
||||||
}
|
}
|
||||||
|
off += int(lastlength) + 2
|
||||||
}
|
}
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
off, err = packStructValue(fv, msg, off, compression, compress)
|
off, err = packStructValue(fv, msg, off, compression, compress)
|
||||||
@ -821,6 +786,13 @@ func packStructValue(val reflect.Value, msg []byte, off int, compression map[str
|
|||||||
copy(msg[off:off+len(b64)], b64)
|
copy(msg[off:off+len(b64)], b64)
|
||||||
off += len(b64)
|
off += len(b64)
|
||||||
case `dns:"domain-name"`:
|
case `dns:"domain-name"`:
|
||||||
|
if val.Type().String() == "dns.IPSECKEY" {
|
||||||
|
// Field(2) is GatewayType, 1 and 2 or used for addresses
|
||||||
|
x := val.Field(2).Uint()
|
||||||
|
if x == 1 || x == 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
if off, err = PackDomainName(s, msg, off, compression, false && compress); err != nil {
|
if off, err = PackDomainName(s, msg, off, compression, false && compress); err != nil {
|
||||||
return lenmsg, err
|
return lenmsg, err
|
||||||
}
|
}
|
||||||
@ -859,6 +831,12 @@ func packStructValue(val reflect.Value, msg []byte, off int, compression map[str
|
|||||||
// length of string. String is RAW (not encoded in hex, nor base64)
|
// length of string. String is RAW (not encoded in hex, nor base64)
|
||||||
copy(msg[off:off+len(s)], s)
|
copy(msg[off:off+len(s)], s)
|
||||||
off += len(s)
|
off += len(s)
|
||||||
|
case `dns:"octet"`:
|
||||||
|
bytesTmp := make([]byte, 256)
|
||||||
|
off, err = packOctetString(fv.String(), msg, off, bytesTmp)
|
||||||
|
if err != nil {
|
||||||
|
return lenmsg, err
|
||||||
|
}
|
||||||
case `dns:"txt"`:
|
case `dns:"txt"`:
|
||||||
fallthrough
|
fallthrough
|
||||||
case "":
|
case "":
|
||||||
@ -890,17 +868,11 @@ func packStructCompress(any interface{}, msg []byte, off int, compression map[st
|
|||||||
return off, err
|
return off, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(miek): Fix use of rdlength here
|
|
||||||
|
|
||||||
// Unpack a reflect.StructValue from msg.
|
// Unpack a reflect.StructValue from msg.
|
||||||
// Same restrictions as packStructValue.
|
// Same restrictions as packStructValue.
|
||||||
func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err error) {
|
func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err error) {
|
||||||
var lenrd int
|
|
||||||
lenmsg := len(msg)
|
lenmsg := len(msg)
|
||||||
for i := 0; i < val.NumField(); i++ {
|
for i := 0; i < val.NumField(); i++ {
|
||||||
if lenrd != 0 && lenrd == off {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if off > lenmsg {
|
if off > lenmsg {
|
||||||
return lenmsg, &Error{"bad offset unpacking"}
|
return lenmsg, &Error{"bad offset unpacking"}
|
||||||
}
|
}
|
||||||
@ -912,7 +884,7 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err er
|
|||||||
// therefore it's expected that this interface would be PrivateRdata
|
// therefore it's expected that this interface would be PrivateRdata
|
||||||
switch data := fv.Interface().(type) {
|
switch data := fv.Interface().(type) {
|
||||||
case PrivateRdata:
|
case PrivateRdata:
|
||||||
n, err := data.Unpack(msg[off:lenrd])
|
n, err := data.Unpack(msg[off:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return lenmsg, err
|
return lenmsg, err
|
||||||
}
|
}
|
||||||
@ -926,9 +898,9 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err er
|
|||||||
return lenmsg, &Error{"bad tag unpacking slice: " + val.Type().Field(i).Tag.Get("dns")}
|
return lenmsg, &Error{"bad tag unpacking slice: " + val.Type().Field(i).Tag.Get("dns")}
|
||||||
case `dns:"domain-name"`:
|
case `dns:"domain-name"`:
|
||||||
// HIP record slice of name (or none)
|
// HIP record slice of name (or none)
|
||||||
servers := make([]string, 0)
|
var servers []string
|
||||||
var s string
|
var s string
|
||||||
for off < lenrd {
|
for off < lenmsg {
|
||||||
s, off, err = UnpackDomainName(msg, off)
|
s, off, err = UnpackDomainName(msg, off)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return lenmsg, err
|
return lenmsg, err
|
||||||
@ -937,30 +909,30 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err er
|
|||||||
}
|
}
|
||||||
fv.Set(reflect.ValueOf(servers))
|
fv.Set(reflect.ValueOf(servers))
|
||||||
case `dns:"txt"`:
|
case `dns:"txt"`:
|
||||||
if off == lenmsg || lenrd == off {
|
if off == lenmsg {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
var txt []string
|
var txt []string
|
||||||
txt, off, err = unpackTxt(msg, off, lenrd)
|
txt, off, err = unpackTxt(msg, off)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return lenmsg, err
|
return lenmsg, err
|
||||||
}
|
}
|
||||||
fv.Set(reflect.ValueOf(txt))
|
fv.Set(reflect.ValueOf(txt))
|
||||||
case `dns:"opt"`: // edns0
|
case `dns:"opt"`: // edns0
|
||||||
if off == lenrd {
|
if off == lenmsg {
|
||||||
// This is an EDNS0 (OPT Record) with no rdata
|
// This is an EDNS0 (OPT Record) with no rdata
|
||||||
// We can safely return here.
|
// We can safely return here.
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
edns := make([]EDNS0, 0)
|
var edns []EDNS0
|
||||||
Option:
|
Option:
|
||||||
code := uint16(0)
|
code := uint16(0)
|
||||||
if off+2 > lenmsg {
|
if off+4 > lenmsg {
|
||||||
return lenmsg, &Error{err: "overflow unpacking opt"}
|
return lenmsg, &Error{err: "overflow unpacking opt"}
|
||||||
}
|
}
|
||||||
code, off = unpackUint16(msg, off)
|
code, off = unpackUint16(msg, off)
|
||||||
optlen, off1 := unpackUint16(msg, off)
|
optlen, off1 := unpackUint16(msg, off)
|
||||||
if off1+int(optlen) > lenrd {
|
if off1+int(optlen) > lenmsg {
|
||||||
return lenmsg, &Error{err: "overflow unpacking opt"}
|
return lenmsg, &Error{err: "overflow unpacking opt"}
|
||||||
}
|
}
|
||||||
switch code {
|
switch code {
|
||||||
@ -1017,27 +989,44 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err er
|
|||||||
edns = append(edns, e)
|
edns = append(edns, e)
|
||||||
off = off1 + int(optlen)
|
off = off1 + int(optlen)
|
||||||
default:
|
default:
|
||||||
// do nothing?
|
e := new(EDNS0_LOCAL)
|
||||||
|
e.Code = code
|
||||||
|
if err := e.unpack(msg[off1 : off1+int(optlen)]); err != nil {
|
||||||
|
return lenmsg, err
|
||||||
|
}
|
||||||
|
edns = append(edns, e)
|
||||||
off = off1 + int(optlen)
|
off = off1 + int(optlen)
|
||||||
}
|
}
|
||||||
if off < lenrd {
|
if off < lenmsg {
|
||||||
goto Option
|
goto Option
|
||||||
}
|
}
|
||||||
fv.Set(reflect.ValueOf(edns))
|
fv.Set(reflect.ValueOf(edns))
|
||||||
case `dns:"a"`:
|
case `dns:"a"`:
|
||||||
if off == lenrd {
|
if val.Type().String() == "dns.IPSECKEY" {
|
||||||
|
// Field(2) is GatewayType, must be 1
|
||||||
|
if val.Field(2).Uint() != 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if off == lenmsg {
|
||||||
break // dyn. update
|
break // dyn. update
|
||||||
}
|
}
|
||||||
if off+net.IPv4len > lenrd || off+net.IPv4len > lenmsg {
|
if off+net.IPv4len > lenmsg {
|
||||||
return lenmsg, &Error{err: "overflow unpacking a"}
|
return lenmsg, &Error{err: "overflow unpacking a"}
|
||||||
}
|
}
|
||||||
fv.Set(reflect.ValueOf(net.IPv4(msg[off], msg[off+1], msg[off+2], msg[off+3])))
|
fv.Set(reflect.ValueOf(net.IPv4(msg[off], msg[off+1], msg[off+2], msg[off+3])))
|
||||||
off += net.IPv4len
|
off += net.IPv4len
|
||||||
case `dns:"aaaa"`:
|
case `dns:"aaaa"`:
|
||||||
if off == lenrd {
|
if val.Type().String() == "dns.IPSECKEY" {
|
||||||
|
// Field(2) is GatewayType, must be 2
|
||||||
|
if val.Field(2).Uint() != 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if off == lenmsg {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if off+net.IPv6len > lenrd || off+net.IPv6len > lenmsg {
|
if off+net.IPv6len > lenmsg {
|
||||||
return lenmsg, &Error{err: "overflow unpacking aaaa"}
|
return lenmsg, &Error{err: "overflow unpacking aaaa"}
|
||||||
}
|
}
|
||||||
fv.Set(reflect.ValueOf(net.IP{msg[off], msg[off+1], msg[off+2], msg[off+3], msg[off+4],
|
fv.Set(reflect.ValueOf(net.IP{msg[off], msg[off+1], msg[off+2], msg[off+3], msg[off+4],
|
||||||
@ -1046,9 +1035,9 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err er
|
|||||||
off += net.IPv6len
|
off += net.IPv6len
|
||||||
case `dns:"wks"`:
|
case `dns:"wks"`:
|
||||||
// Rest of the record is the bitmap
|
// Rest of the record is the bitmap
|
||||||
serv := make([]uint16, 0)
|
var serv []uint16
|
||||||
j := 0
|
j := 0
|
||||||
for off < lenrd {
|
for off < lenmsg {
|
||||||
if off+1 > lenmsg {
|
if off+1 > lenmsg {
|
||||||
return lenmsg, &Error{err: "overflow unpacking wks"}
|
return lenmsg, &Error{err: "overflow unpacking wks"}
|
||||||
}
|
}
|
||||||
@ -1083,36 +1072,39 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err er
|
|||||||
}
|
}
|
||||||
fv.Set(reflect.ValueOf(serv))
|
fv.Set(reflect.ValueOf(serv))
|
||||||
case `dns:"nsec"`: // NSEC/NSEC3
|
case `dns:"nsec"`: // NSEC/NSEC3
|
||||||
if off == lenrd {
|
if off == len(msg) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// Rest of the record is the type bitmap
|
// Rest of the record is the type bitmap
|
||||||
if off+2 > lenrd || off+2 > lenmsg {
|
var nsec []uint16
|
||||||
return lenmsg, &Error{err: "overflow unpacking nsecx"}
|
|
||||||
}
|
|
||||||
nsec := make([]uint16, 0)
|
|
||||||
length := 0
|
length := 0
|
||||||
window := 0
|
window := 0
|
||||||
for off+2 < lenrd {
|
lastwindow := -1
|
||||||
|
for off < len(msg) {
|
||||||
|
if off+2 > len(msg) {
|
||||||
|
return len(msg), &Error{err: "overflow unpacking nsecx"}
|
||||||
|
}
|
||||||
window = int(msg[off])
|
window = int(msg[off])
|
||||||
length = int(msg[off+1])
|
length = int(msg[off+1])
|
||||||
//println("off, windows, length, end", off, window, length, endrr)
|
off += 2
|
||||||
|
if window <= lastwindow {
|
||||||
|
// RFC 4034: Blocks are present in the NSEC RR RDATA in
|
||||||
|
// increasing numerical order.
|
||||||
|
return len(msg), &Error{err: "out of order NSEC block"}
|
||||||
|
}
|
||||||
if length == 0 {
|
if length == 0 {
|
||||||
// A length window of zero is strange. If there
|
// RFC 4034: Blocks with no types present MUST NOT be included.
|
||||||
// the window should not have been specified. Bail out
|
return len(msg), &Error{err: "empty NSEC block"}
|
||||||
// println("dns: length == 0 when unpacking NSEC")
|
|
||||||
return lenmsg, &Error{err: "overflow unpacking nsecx"}
|
|
||||||
}
|
}
|
||||||
if length > 32 {
|
if length > 32 {
|
||||||
return lenmsg, &Error{err: "overflow unpacking nsecx"}
|
return len(msg), &Error{err: "NSEC block too long"}
|
||||||
|
}
|
||||||
|
if off+length > len(msg) {
|
||||||
|
return len(msg), &Error{err: "overflowing NSEC block"}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Walk the bytes in the window - and check the bit settings...
|
// Walk the bytes in the window and extract the type bits
|
||||||
off += 2
|
|
||||||
for j := 0; j < length; j++ {
|
for j := 0; j < length; j++ {
|
||||||
if off+j+1 > lenmsg {
|
|
||||||
return lenmsg, &Error{err: "overflow unpacking nsecx"}
|
|
||||||
}
|
|
||||||
b := msg[off+j]
|
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 {
|
||||||
@ -1141,6 +1133,7 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err er
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
off += length
|
off += length
|
||||||
|
lastwindow = window
|
||||||
}
|
}
|
||||||
fv.Set(reflect.ValueOf(nsec))
|
fv.Set(reflect.ValueOf(nsec))
|
||||||
}
|
}
|
||||||
@ -1150,7 +1143,12 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err er
|
|||||||
return lenmsg, err
|
return lenmsg, err
|
||||||
}
|
}
|
||||||
if val.Type().Field(i).Name == "Hdr" {
|
if val.Type().Field(i).Name == "Hdr" {
|
||||||
lenrd = off + int(val.FieldByName("Hdr").FieldByName("Rdlength").Uint())
|
lenrd := off + int(val.FieldByName("Hdr").FieldByName("Rdlength").Uint())
|
||||||
|
if lenrd > lenmsg {
|
||||||
|
return lenmsg, &Error{err: "overflowing header size"}
|
||||||
|
}
|
||||||
|
msg = msg[:lenrd]
|
||||||
|
lenmsg = len(msg)
|
||||||
}
|
}
|
||||||
case reflect.Uint8:
|
case reflect.Uint8:
|
||||||
if off == lenmsg {
|
if off == lenmsg {
|
||||||
@ -1181,6 +1179,9 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err er
|
|||||||
fv.SetUint(uint64(uint32(msg[off])<<24 | uint32(msg[off+1])<<16 | uint32(msg[off+2])<<8 | uint32(msg[off+3])))
|
fv.SetUint(uint64(uint32(msg[off])<<24 | uint32(msg[off+1])<<16 | uint32(msg[off+2])<<8 | uint32(msg[off+3])))
|
||||||
off += 4
|
off += 4
|
||||||
case reflect.Uint64:
|
case reflect.Uint64:
|
||||||
|
if off == lenmsg {
|
||||||
|
break
|
||||||
|
}
|
||||||
switch val.Type().Field(i).Tag {
|
switch val.Type().Field(i).Tag {
|
||||||
default:
|
default:
|
||||||
if off+8 > lenmsg {
|
if off+8 > lenmsg {
|
||||||
@ -1206,32 +1207,42 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err er
|
|||||||
switch val.Type().Field(i).Tag {
|
switch val.Type().Field(i).Tag {
|
||||||
default:
|
default:
|
||||||
return lenmsg, &Error{"bad tag unpacking string: " + val.Type().Field(i).Tag.Get("dns")}
|
return lenmsg, &Error{"bad tag unpacking string: " + val.Type().Field(i).Tag.Get("dns")}
|
||||||
|
case `dns:"octet"`:
|
||||||
|
s = string(msg[off:])
|
||||||
|
off = lenmsg
|
||||||
case `dns:"hex"`:
|
case `dns:"hex"`:
|
||||||
hexend := lenrd
|
hexend := lenmsg
|
||||||
if val.FieldByName("Hdr").FieldByName("Rrtype").Uint() == uint64(TypeHIP) {
|
if val.FieldByName("Hdr").FieldByName("Rrtype").Uint() == uint64(TypeHIP) {
|
||||||
hexend = off + int(val.FieldByName("HitLength").Uint())
|
hexend = off + int(val.FieldByName("HitLength").Uint())
|
||||||
}
|
}
|
||||||
if hexend > lenrd || hexend > lenmsg {
|
if hexend > lenmsg {
|
||||||
return lenmsg, &Error{err: "overflow unpacking hex"}
|
return lenmsg, &Error{err: "overflow unpacking HIP hex"}
|
||||||
}
|
}
|
||||||
s = hex.EncodeToString(msg[off:hexend])
|
s = hex.EncodeToString(msg[off:hexend])
|
||||||
off = hexend
|
off = hexend
|
||||||
case `dns:"base64"`:
|
case `dns:"base64"`:
|
||||||
// Rest of the RR is base64 encoded value
|
// Rest of the RR is base64 encoded value
|
||||||
b64end := lenrd
|
b64end := lenmsg
|
||||||
if val.FieldByName("Hdr").FieldByName("Rrtype").Uint() == uint64(TypeHIP) {
|
if val.FieldByName("Hdr").FieldByName("Rrtype").Uint() == uint64(TypeHIP) {
|
||||||
b64end = off + int(val.FieldByName("PublicKeyLength").Uint())
|
b64end = off + int(val.FieldByName("PublicKeyLength").Uint())
|
||||||
}
|
}
|
||||||
if b64end > lenrd || b64end > lenmsg {
|
if b64end > lenmsg {
|
||||||
return lenmsg, &Error{err: "overflow unpacking base64"}
|
return lenmsg, &Error{err: "overflow unpacking HIP base64"}
|
||||||
}
|
}
|
||||||
s = toBase64(msg[off:b64end])
|
s = toBase64(msg[off:b64end])
|
||||||
off = b64end
|
off = b64end
|
||||||
case `dns:"cdomain-name"`:
|
case `dns:"cdomain-name"`:
|
||||||
fallthrough
|
fallthrough
|
||||||
case `dns:"domain-name"`:
|
case `dns:"domain-name"`:
|
||||||
if off == lenmsg {
|
if val.Type().String() == "dns.IPSECKEY" {
|
||||||
// zero rdata foo, OK for dyn. updates
|
// Field(2) is GatewayType, 1 and 2 or used for addresses
|
||||||
|
x := val.Field(2).Uint()
|
||||||
|
if x == 1 || x == 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if off == lenmsg && int(val.FieldByName("Hdr").FieldByName("Rdlength").Uint()) == 0 {
|
||||||
|
// zero rdata is ok for dyn updates, but only if rdlength is 0
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
s, off, err = UnpackDomainName(msg, off)
|
s, off, err = UnpackDomainName(msg, off)
|
||||||
@ -1375,7 +1386,7 @@ func UnpackRR(msg []byte, off int) (rr RR, off1 int, err error) {
|
|||||||
}
|
}
|
||||||
end := off + int(h.Rdlength)
|
end := off + int(h.Rdlength)
|
||||||
// make an rr of that type and re-unpack.
|
// make an rr of that type and re-unpack.
|
||||||
mk, known := typeToRR[h.Rrtype]
|
mk, known := TypeToRR[h.Rrtype]
|
||||||
if !known {
|
if !known {
|
||||||
rr = new(RFC3597)
|
rr = new(RFC3597)
|
||||||
} else {
|
} else {
|
||||||
@ -1388,6 +1399,32 @@ func UnpackRR(msg []byte, off int) (rr RR, off1 int, err error) {
|
|||||||
return rr, off, err
|
return rr, off, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// unpackRRslice unpacks msg[off:] into an []RR.
|
||||||
|
// If we cannot unpack the whole array, then it will return nil
|
||||||
|
func unpackRRslice(l int, msg []byte, off int) (dst1 []RR, off1 int, err error) {
|
||||||
|
var r RR
|
||||||
|
// Optimistically make dst be the length that was sent
|
||||||
|
dst := make([]RR, 0, l)
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
off1 := off
|
||||||
|
r, off, err = UnpackRR(msg, off)
|
||||||
|
if err != nil {
|
||||||
|
off = len(msg)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// If offset does not increase anymore, l is a lie
|
||||||
|
if off1 == off {
|
||||||
|
l = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
dst = append(dst, r)
|
||||||
|
}
|
||||||
|
if err != nil && off == len(msg) {
|
||||||
|
dst = nil
|
||||||
|
}
|
||||||
|
return dst, off, err
|
||||||
|
}
|
||||||
|
|
||||||
// Reverse a map
|
// Reverse a map
|
||||||
func reverseInt8(m map[uint8]string) map[string]uint8 {
|
func reverseInt8(m map[uint8]string) map[string]uint8 {
|
||||||
n := make(map[string]uint8)
|
n := make(map[string]uint8)
|
||||||
@ -1586,52 +1623,48 @@ func (dns *Msg) Unpack(msg []byte) (err error) {
|
|||||||
dns.CheckingDisabled = (dh.Bits & _CD) != 0
|
dns.CheckingDisabled = (dh.Bits & _CD) != 0
|
||||||
dns.Rcode = int(dh.Bits & 0xF)
|
dns.Rcode = int(dh.Bits & 0xF)
|
||||||
|
|
||||||
// Arrays.
|
// Optimistically use the count given to us in the header
|
||||||
dns.Question = make([]Question, dh.Qdcount)
|
dns.Question = make([]Question, 0, int(dh.Qdcount))
|
||||||
dns.Answer = make([]RR, dh.Ancount)
|
|
||||||
dns.Ns = make([]RR, dh.Nscount)
|
|
||||||
dns.Extra = make([]RR, dh.Arcount)
|
|
||||||
|
|
||||||
for i := 0; i < len(dns.Question); i++ {
|
var q Question
|
||||||
off, err = UnpackStruct(&dns.Question[i], msg, off)
|
for i := 0; i < int(dh.Qdcount); i++ {
|
||||||
|
off1 := off
|
||||||
|
off, err = UnpackStruct(&q, msg, off)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// Even if Truncated is set, we only will set ErrTruncated if we
|
||||||
|
// actually got the questions
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
if off1 == off { // Offset does not increase anymore, dh.Qdcount is a lie!
|
||||||
// If we see a TC bit being set we return here, without
|
dh.Qdcount = uint16(i)
|
||||||
// an error, because technically it isn't an error. So return
|
break
|
||||||
// without parsing the potentially corrupt packet and hitting an error.
|
|
||||||
// TODO(miek): this isn't the best strategy!
|
|
||||||
if dns.Truncated {
|
|
||||||
dns.Answer = nil
|
|
||||||
dns.Ns = nil
|
|
||||||
dns.Extra = nil
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
for i := 0; i < len(dns.Answer); i++ {
|
|
||||||
dns.Answer[i], off, err = UnpackRR(msg, off)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
dns.Question = append(dns.Question, q)
|
||||||
}
|
}
|
||||||
for i := 0; i < len(dns.Ns); i++ {
|
|
||||||
dns.Ns[i], off, err = UnpackRR(msg, off)
|
dns.Answer, off, err = unpackRRslice(int(dh.Ancount), msg, off)
|
||||||
if err != nil {
|
// The header counts might have been wrong so we need to update it
|
||||||
return err
|
dh.Ancount = uint16(len(dns.Answer))
|
||||||
}
|
if err == nil {
|
||||||
|
dns.Ns, off, err = unpackRRslice(int(dh.Nscount), msg, off)
|
||||||
}
|
}
|
||||||
for i := 0; i < len(dns.Extra); i++ {
|
// The header counts might have been wrong so we need to update it
|
||||||
dns.Extra[i], off, err = UnpackRR(msg, off)
|
dh.Nscount = uint16(len(dns.Ns))
|
||||||
if err != nil {
|
if err == nil {
|
||||||
return err
|
dns.Extra, off, err = unpackRRslice(int(dh.Arcount), msg, off)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// The header counts might have been wrong so we need to update it
|
||||||
|
dh.Arcount = uint16(len(dns.Extra))
|
||||||
if off != len(msg) {
|
if off != len(msg) {
|
||||||
// TODO(miek) make this an error?
|
// TODO(miek) make this an error?
|
||||||
// use PackOpt to let people tell how detailed the error reporting should be?
|
// use PackOpt to let people tell how detailed the error reporting should be?
|
||||||
// println("dns: extra bytes in dns packet", off, "<", len(msg))
|
// println("dns: extra bytes in dns packet", off, "<", len(msg))
|
||||||
|
} else if dns.Truncated {
|
||||||
|
// Whether we ran into a an error or not, we want to return that it
|
||||||
|
// was truncated
|
||||||
|
err = ErrTruncated
|
||||||
}
|
}
|
||||||
return nil
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert a complete message to a string with dig-like output.
|
// Convert a complete message to a string with dig-like output.
|
||||||
@ -1863,9 +1896,18 @@ func Copy(r RR) RR {
|
|||||||
return r1
|
return r1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Len returns the length (in octets) of the uncompressed RR in wire format.
|
||||||
|
func Len(r RR) int {
|
||||||
|
return r.len()
|
||||||
|
}
|
||||||
|
|
||||||
// Copy returns a new *Msg which is a deep-copy of dns.
|
// Copy returns a new *Msg which is a deep-copy of dns.
|
||||||
func (dns *Msg) Copy() *Msg {
|
func (dns *Msg) Copy() *Msg {
|
||||||
r1 := new(Msg)
|
return dns.CopyTo(new(Msg))
|
||||||
|
}
|
||||||
|
|
||||||
|
// CopyTo copies the contents to the provided message using a deep-copy and returns the copy.
|
||||||
|
func (dns *Msg) CopyTo(r1 *Msg) *Msg {
|
||||||
r1.MsgHdr = dns.MsgHdr
|
r1.MsgHdr = dns.MsgHdr
|
||||||
r1.Compress = dns.Compress
|
r1.Compress = dns.Compress
|
||||||
|
|
||||||
@ -1874,25 +1916,34 @@ func (dns *Msg) Copy() *Msg {
|
|||||||
copy(r1.Question, dns.Question) // TODO(miek): Question is an immutable value, ok to do a shallow-copy
|
copy(r1.Question, dns.Question) // TODO(miek): Question is an immutable value, ok to do a shallow-copy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rrArr := make([]RR, len(dns.Answer)+len(dns.Ns)+len(dns.Extra))
|
||||||
|
var rri int
|
||||||
|
|
||||||
if len(dns.Answer) > 0 {
|
if len(dns.Answer) > 0 {
|
||||||
r1.Answer = make([]RR, len(dns.Answer))
|
rrbegin := rri
|
||||||
for i := 0; i < len(dns.Answer); i++ {
|
for i := 0; i < len(dns.Answer); i++ {
|
||||||
r1.Answer[i] = dns.Answer[i].copy()
|
rrArr[rri] = dns.Answer[i].copy()
|
||||||
|
rri++
|
||||||
}
|
}
|
||||||
|
r1.Answer = rrArr[rrbegin:rri:rri]
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(dns.Ns) > 0 {
|
if len(dns.Ns) > 0 {
|
||||||
r1.Ns = make([]RR, len(dns.Ns))
|
rrbegin := rri
|
||||||
for i := 0; i < len(dns.Ns); i++ {
|
for i := 0; i < len(dns.Ns); i++ {
|
||||||
r1.Ns[i] = dns.Ns[i].copy()
|
rrArr[rri] = dns.Ns[i].copy()
|
||||||
|
rri++
|
||||||
}
|
}
|
||||||
|
r1.Ns = rrArr[rrbegin:rri:rri]
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(dns.Extra) > 0 {
|
if len(dns.Extra) > 0 {
|
||||||
r1.Extra = make([]RR, len(dns.Extra))
|
rrbegin := rri
|
||||||
for i := 0; i < len(dns.Extra); i++ {
|
for i := 0; i < len(dns.Extra); i++ {
|
||||||
r1.Extra[i] = dns.Extra[i].copy()
|
rrArr[rri] = dns.Extra[i].copy()
|
||||||
|
rri++
|
||||||
}
|
}
|
||||||
|
r1.Extra = rrArr[rrbegin:rri:rri]
|
||||||
}
|
}
|
||||||
|
|
||||||
return r1
|
return r1
|
||||||
|
2
vendor/github.com/miekg/dns/nsecx.go
generated
vendored
2
vendor/github.com/miekg/dns/nsecx.go
generated
vendored
@ -50,6 +50,8 @@ func HashName(label string, ha uint8, iter uint16, salt string) string {
|
|||||||
return toBase32(nsec3)
|
return toBase32(nsec3)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Denialer is an interface that should be implemented by types that are used to denial
|
||||||
|
// answers in DNSSEC.
|
||||||
type Denialer interface {
|
type Denialer interface {
|
||||||
// Cover will check if the (unhashed) name is being covered by this NSEC or NSEC3.
|
// Cover will check if the (unhashed) name is being covered by this NSEC or NSEC3.
|
||||||
Cover(name string) bool
|
Cover(name string) bool
|
||||||
|
23
vendor/github.com/miekg/dns/privaterr.go
generated
vendored
23
vendor/github.com/miekg/dns/privaterr.go
generated
vendored
@ -1,10 +1,3 @@
|
|||||||
/*
|
|
||||||
PRIVATE RR
|
|
||||||
|
|
||||||
RFC 6895 sets aside a range of type codes for private use. This range
|
|
||||||
is 65,280 - 65,534 (0xFF00 - 0xFFFE). When experimenting with new Resource Records these
|
|
||||||
can be used, before requesting an official type code from IANA.
|
|
||||||
*/
|
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -40,7 +33,7 @@ type PrivateRR struct {
|
|||||||
|
|
||||||
func mkPrivateRR(rrtype uint16) *PrivateRR {
|
func mkPrivateRR(rrtype uint16) *PrivateRR {
|
||||||
// Panics if RR is not an instance of PrivateRR.
|
// Panics if RR is not an instance of PrivateRR.
|
||||||
rrfunc, ok := typeToRR[rrtype]
|
rrfunc, ok := TypeToRR[rrtype]
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("dns: invalid operation with Private RR type %d", rrtype))
|
panic(fmt.Sprintf("dns: invalid operation with Private RR type %d", rrtype))
|
||||||
}
|
}
|
||||||
@ -50,11 +43,13 @@ func mkPrivateRR(rrtype uint16) *PrivateRR {
|
|||||||
case *PrivateRR:
|
case *PrivateRR:
|
||||||
return rr
|
return rr
|
||||||
}
|
}
|
||||||
panic(fmt.Sprintf("dns: RR is not a PrivateRR, typeToRR[%d] generator returned %T", rrtype, anyrr))
|
panic(fmt.Sprintf("dns: RR is not a PrivateRR, TypeToRR[%d] generator returned %T", rrtype, anyrr))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Header return the RR header of r.
|
||||||
func (r *PrivateRR) Header() *RR_Header { return &r.Hdr }
|
func (r *PrivateRR) Header() *RR_Header { return &r.Hdr }
|
||||||
func (r *PrivateRR) String() string { return r.Hdr.String() + r.Data.String() }
|
|
||||||
|
func (r *PrivateRR) String() string { return r.Hdr.String() + r.Data.String() }
|
||||||
|
|
||||||
// Private len and copy parts to satisfy RR interface.
|
// Private len and copy parts to satisfy RR interface.
|
||||||
func (r *PrivateRR) len() int { return r.Hdr.len() + r.Data.Len() }
|
func (r *PrivateRR) len() int { return r.Hdr.len() + r.Data.Len() }
|
||||||
@ -76,7 +71,7 @@ func (r *PrivateRR) copy() RR {
|
|||||||
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()} }
|
||||||
TypeToString[rtype] = rtypestr
|
TypeToString[rtype] = rtypestr
|
||||||
StringToType[rtypestr] = rtype
|
StringToType[rtypestr] = rtype
|
||||||
|
|
||||||
@ -91,9 +86,9 @@ func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata)
|
|||||||
// TODO(miek): we could also be returning _QUOTE, this might or might not
|
// TODO(miek): we could also be returning _QUOTE, this might or might not
|
||||||
// be an issue (basically parsing TXT becomes hard)
|
// be an issue (basically parsing TXT becomes hard)
|
||||||
switch l = <-c; l.value {
|
switch l = <-c; l.value {
|
||||||
case _NEWLINE, _EOF:
|
case zNewline, zEOF:
|
||||||
break FETCH
|
break FETCH
|
||||||
case _STRING:
|
case zString:
|
||||||
text = append(text, l.token)
|
text = append(text, l.token)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -113,7 +108,7 @@ func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata)
|
|||||||
func PrivateHandleRemove(rtype uint16) {
|
func PrivateHandleRemove(rtype uint16) {
|
||||||
rtypestr, ok := TypeToString[rtype]
|
rtypestr, ok := TypeToString[rtype]
|
||||||
if ok {
|
if ok {
|
||||||
delete(typeToRR, rtype)
|
delete(TypeToRR, rtype)
|
||||||
delete(TypeToString, rtype)
|
delete(TypeToString, rtype)
|
||||||
delete(typeToparserFunc, rtype)
|
delete(typeToparserFunc, rtype)
|
||||||
delete(StringToType, rtypestr)
|
delete(StringToType, rtypestr)
|
||||||
|
6
vendor/github.com/miekg/dns/rawmsg.go
generated
vendored
6
vendor/github.com/miekg/dns/rawmsg.go
generated
vendored
@ -21,7 +21,7 @@ func rawSetQuestionLen(msg []byte, i uint16) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// rawSetAnswerLen sets the lenght of the answer section.
|
// rawSetAnswerLen sets the length of the answer section.
|
||||||
func rawSetAnswerLen(msg []byte, i uint16) bool {
|
func rawSetAnswerLen(msg []byte, i uint16) bool {
|
||||||
if len(msg) < 8 {
|
if len(msg) < 8 {
|
||||||
return false
|
return false
|
||||||
@ -30,7 +30,7 @@ func rawSetAnswerLen(msg []byte, i uint16) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// rawSetsNsLen sets the lenght of the authority section.
|
// rawSetsNsLen sets the length of the authority section.
|
||||||
func rawSetNsLen(msg []byte, i uint16) bool {
|
func rawSetNsLen(msg []byte, i uint16) bool {
|
||||||
if len(msg) < 10 {
|
if len(msg) < 10 {
|
||||||
return false
|
return false
|
||||||
@ -39,7 +39,7 @@ func rawSetNsLen(msg []byte, i uint16) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// rawSetExtraLen sets the lenght of the additional section.
|
// rawSetExtraLen sets the length of the additional section.
|
||||||
func rawSetExtraLen(msg []byte, i uint16) bool {
|
func rawSetExtraLen(msg []byte, i uint16) bool {
|
||||||
if len(msg) < 12 {
|
if len(msg) < 12 {
|
||||||
return false
|
return false
|
||||||
|
84
vendor/github.com/miekg/dns/sanitize.go
generated
vendored
Normal file
84
vendor/github.com/miekg/dns/sanitize.go
generated
vendored
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
package dns
|
||||||
|
|
||||||
|
// Dedup removes identical RRs from rrs. It preserves the original ordering.
|
||||||
|
// The lowest TTL of any duplicates is used in the remaining one. Dedup modifies
|
||||||
|
// rrs.
|
||||||
|
// m is used to store the RRs temporay. If it is nil a new map will be allocated.
|
||||||
|
func Dedup(rrs []RR, m map[string]RR) []RR {
|
||||||
|
if m == nil {
|
||||||
|
m = make(map[string]RR)
|
||||||
|
}
|
||||||
|
// Save the keys, so we don't have to call normalizedString twice.
|
||||||
|
keys := make([]*string, 0, len(rrs))
|
||||||
|
|
||||||
|
for _, r := range rrs {
|
||||||
|
key := normalizedString(r)
|
||||||
|
keys = append(keys, &key)
|
||||||
|
if _, ok := m[key]; ok {
|
||||||
|
// Shortest TTL wins.
|
||||||
|
if m[key].Header().Ttl > r.Header().Ttl {
|
||||||
|
m[key].Header().Ttl = r.Header().Ttl
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
m[key] = r
|
||||||
|
}
|
||||||
|
// If the length of the result map equals the amount of RRs we got,
|
||||||
|
// it means they were all different. We can then just return the original rrset.
|
||||||
|
if len(m) == len(rrs) {
|
||||||
|
return rrs
|
||||||
|
}
|
||||||
|
|
||||||
|
j := 0
|
||||||
|
for i, r := range rrs {
|
||||||
|
// If keys[i] lives in the map, we should copy and remove it.
|
||||||
|
if _, ok := m[*keys[i]]; ok {
|
||||||
|
delete(m, *keys[i])
|
||||||
|
rrs[j] = r
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(m) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rrs[:j]
|
||||||
|
}
|
||||||
|
|
||||||
|
// normalizedString returns a normalized string from r. The TTL
|
||||||
|
// is removed and the domain name is lowercased. We go from this:
|
||||||
|
// DomainName<TAB>TTL<TAB>CLASS<TAB>TYPE<TAB>RDATA to:
|
||||||
|
// lowercasename<TAB>CLASS<TAB>TYPE...
|
||||||
|
func normalizedString(r RR) string {
|
||||||
|
// A string Go DNS makes has: domainname<TAB>TTL<TAB>...
|
||||||
|
b := []byte(r.String())
|
||||||
|
|
||||||
|
// find the first non-escaped tab, then another, so we capture where the TTL lives.
|
||||||
|
esc := false
|
||||||
|
ttlStart, ttlEnd := 0, 0
|
||||||
|
for i := 0; i < len(b) && ttlEnd == 0; i++ {
|
||||||
|
switch {
|
||||||
|
case b[i] == '\\':
|
||||||
|
esc = !esc
|
||||||
|
case b[i] == '\t' && !esc:
|
||||||
|
if ttlStart == 0 {
|
||||||
|
ttlStart = i
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if ttlEnd == 0 {
|
||||||
|
ttlEnd = i
|
||||||
|
}
|
||||||
|
case b[i] >= 'A' && b[i] <= 'Z' && !esc:
|
||||||
|
b[i] += 32
|
||||||
|
default:
|
||||||
|
esc = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove TTL.
|
||||||
|
copy(b[ttlStart:], b[ttlEnd:])
|
||||||
|
cut := ttlEnd - ttlStart
|
||||||
|
return string(b[:len(b)-cut])
|
||||||
|
}
|
311
vendor/github.com/miekg/dns/server.go
generated
vendored
311
vendor/github.com/miekg/dns/server.go
generated
vendored
@ -4,12 +4,17 @@ package dns
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/tls"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Maximum number of TCP queries before we close the socket.
|
||||||
|
const maxTCPQueries = 128
|
||||||
|
|
||||||
|
// Handler is implemented by any value that implements ServeDNS.
|
||||||
type Handler interface {
|
type Handler interface {
|
||||||
ServeDNS(w ResponseWriter, r *Msg)
|
ServeDNS(w ResponseWriter, r *Msg)
|
||||||
}
|
}
|
||||||
@ -43,9 +48,10 @@ type response struct {
|
|||||||
tsigRequestMAC string
|
tsigRequestMAC string
|
||||||
tsigSecret map[string]string // the tsig secrets
|
tsigSecret map[string]string // the tsig secrets
|
||||||
udp *net.UDPConn // i/o connection if UDP was used
|
udp *net.UDPConn // i/o connection if UDP was used
|
||||||
tcp *net.TCPConn // i/o connection if TCP was used
|
tcp net.Conn // i/o connection if TCP was used
|
||||||
udpSession *sessionUDP // oob data to get egress interface right
|
udpSession *SessionUDP // oob data to get egress interface right
|
||||||
remoteAddr net.Addr // address of the client
|
remoteAddr net.Addr // address of the client
|
||||||
|
writer Writer // writer to output the raw DNS bits
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServeMux is an DNS request multiplexer. It matches the
|
// ServeMux is an DNS request multiplexer. It matches the
|
||||||
@ -72,12 +78,12 @@ var DefaultServeMux = NewServeMux()
|
|||||||
// Handler object that calls f.
|
// Handler object that calls f.
|
||||||
type HandlerFunc func(ResponseWriter, *Msg)
|
type HandlerFunc func(ResponseWriter, *Msg)
|
||||||
|
|
||||||
// ServerDNS calls f(w, r)
|
// ServeDNS calls f(w, r).
|
||||||
func (f HandlerFunc) ServeDNS(w ResponseWriter, r *Msg) {
|
func (f HandlerFunc) ServeDNS(w ResponseWriter, r *Msg) {
|
||||||
f(w, r)
|
f(w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FailedHandler returns a HandlerFunc that returns SERVFAIL for every request it gets.
|
// HandleFailed returns a HandlerFunc that returns SERVFAIL for every request it gets.
|
||||||
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)
|
||||||
@ -87,13 +93,35 @@ func HandleFailed(w ResponseWriter, r *Msg) {
|
|||||||
|
|
||||||
func failedHandler() Handler { return HandlerFunc(HandleFailed) }
|
func failedHandler() Handler { return HandlerFunc(HandleFailed) }
|
||||||
|
|
||||||
// ListenAndServe Starts a server on addresss and network speficied. Invoke handler
|
// ListenAndServe Starts a server on address and network specified Invoke handler
|
||||||
// for incoming queries.
|
// for incoming queries.
|
||||||
func ListenAndServe(addr string, network string, handler Handler) error {
|
func ListenAndServe(addr string, network string, handler Handler) error {
|
||||||
server := &Server{Addr: addr, Net: network, Handler: handler}
|
server := &Server{Addr: addr, Net: network, Handler: handler}
|
||||||
return server.ListenAndServe()
|
return server.ListenAndServe()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListenAndServeTLS acts like http.ListenAndServeTLS, more information in
|
||||||
|
// http://golang.org/pkg/net/http/#ListenAndServeTLS
|
||||||
|
func ListenAndServeTLS(addr, certFile, keyFile string, handler Handler) error {
|
||||||
|
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
config := tls.Config{
|
||||||
|
Certificates: []tls.Certificate{cert},
|
||||||
|
}
|
||||||
|
|
||||||
|
server := &Server{
|
||||||
|
Addr: addr,
|
||||||
|
Net: "tcp-tls",
|
||||||
|
TLSConfig: &config,
|
||||||
|
Handler: handler,
|
||||||
|
}
|
||||||
|
|
||||||
|
return server.ListenAndServe()
|
||||||
|
}
|
||||||
|
|
||||||
// ActivateAndServe activates a server with a listener from systemd,
|
// ActivateAndServe activates a server with a listener from systemd,
|
||||||
// l and p should not both be non-nil.
|
// l and p should not both be non-nil.
|
||||||
// If both l and p are not nil only p will be used.
|
// If both l and p are not nil only p will be used.
|
||||||
@ -121,10 +149,9 @@ func (mux *ServeMux) match(q string, t uint16) Handler {
|
|||||||
if h, ok := mux.z[string(b[:l])]; ok { // 'causes garbage, might want to change the map key
|
if h, ok := mux.z[string(b[:l])]; ok { // 'causes garbage, might want to change the map key
|
||||||
if t != TypeDS {
|
if t != TypeDS {
|
||||||
return h
|
return h
|
||||||
} else {
|
|
||||||
// Continue for DS to see if we have a parent too, if so delegeate to the parent
|
|
||||||
handler = h
|
|
||||||
}
|
}
|
||||||
|
// Continue for DS to see if we have a parent too, if so delegeate to the parent
|
||||||
|
handler = h
|
||||||
}
|
}
|
||||||
off, end = NextLabel(q, off)
|
off, end = NextLabel(q, off)
|
||||||
if end {
|
if end {
|
||||||
@ -148,7 +175,7 @@ func (mux *ServeMux) Handle(pattern string, handler Handler) {
|
|||||||
mux.m.Unlock()
|
mux.m.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle adds a handler to the ServeMux for pattern.
|
// HandleFunc adds a handler function to the ServeMux for pattern.
|
||||||
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) {
|
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) {
|
||||||
mux.Handle(pattern, HandlerFunc(handler))
|
mux.Handle(pattern, HandlerFunc(handler))
|
||||||
}
|
}
|
||||||
@ -158,9 +185,9 @@ func (mux *ServeMux) HandleRemove(pattern string) {
|
|||||||
if pattern == "" {
|
if pattern == "" {
|
||||||
panic("dns: invalid pattern " + pattern)
|
panic("dns: invalid pattern " + pattern)
|
||||||
}
|
}
|
||||||
// don't need a mutex here, because deleting is OK, even if the
|
mux.m.Lock()
|
||||||
// entry is note there.
|
|
||||||
delete(mux.z, Fqdn(pattern))
|
delete(mux.z, Fqdn(pattern))
|
||||||
|
mux.m.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServeDNS dispatches the request to the handler whose
|
// ServeDNS dispatches the request to the handler whose
|
||||||
@ -197,14 +224,53 @@ func HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) {
|
|||||||
DefaultServeMux.HandleFunc(pattern, handler)
|
DefaultServeMux.HandleFunc(pattern, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Writer writes raw DNS messages; each call to Write should send an entire message.
|
||||||
|
type Writer interface {
|
||||||
|
io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reader reads raw DNS messages; each call to ReadTCP or ReadUDP should return an entire message.
|
||||||
|
type Reader interface {
|
||||||
|
// ReadTCP reads a raw message from a TCP connection. Implementations may alter
|
||||||
|
// connection properties, for example the read-deadline.
|
||||||
|
ReadTCP(conn net.Conn, timeout time.Duration) ([]byte, error)
|
||||||
|
// ReadUDP reads a raw message from a UDP connection. Implementations may alter
|
||||||
|
// connection properties, for example the read-deadline.
|
||||||
|
ReadUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// defaultReader is an adapter for the Server struct that implements the Reader interface
|
||||||
|
// using the readTCP and readUDP func of the embedded Server.
|
||||||
|
type defaultReader struct {
|
||||||
|
*Server
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dr *defaultReader) ReadTCP(conn net.Conn, timeout time.Duration) ([]byte, error) {
|
||||||
|
return dr.readTCP(conn, timeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dr *defaultReader) ReadUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error) {
|
||||||
|
return dr.readUDP(conn, timeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecorateReader is a decorator hook for extending or supplanting the functionality of a Reader.
|
||||||
|
// Implementations should never return a nil Reader.
|
||||||
|
type DecorateReader func(Reader) Reader
|
||||||
|
|
||||||
|
// DecorateWriter is a decorator hook for extending or supplanting the functionality of a Writer.
|
||||||
|
// Implementations should never return a nil Writer.
|
||||||
|
type DecorateWriter func(Writer) Writer
|
||||||
|
|
||||||
// A Server defines parameters for running an DNS server.
|
// A Server defines parameters for running an DNS server.
|
||||||
type Server struct {
|
type Server struct {
|
||||||
// Address to listen on, ":dns" if empty.
|
// Address to listen on, ":dns" if empty.
|
||||||
Addr string
|
Addr string
|
||||||
// if "tcp" it will invoke a TCP listener, otherwise an UDP one.
|
// if "tcp" or "tcp-tls" (DNS over TLS) it will invoke a TCP listener, otherwise an UDP one
|
||||||
Net string
|
Net string
|
||||||
// TCP Listener to use, this is to aid in systemd's socket activation.
|
// TCP Listener to use, this is to aid in systemd's socket activation.
|
||||||
Listener net.Listener
|
Listener net.Listener
|
||||||
|
// TLS connection configuration
|
||||||
|
TLSConfig *tls.Config
|
||||||
// UDP "Listener" to use, this is to aid in systemd's socket activation.
|
// UDP "Listener" to use, this is to aid in systemd's socket activation.
|
||||||
PacketConn net.PacketConn
|
PacketConn net.PacketConn
|
||||||
// Handler to invoke, dns.DefaultServeMux if nil.
|
// Handler to invoke, dns.DefaultServeMux if nil.
|
||||||
@ -221,31 +287,30 @@ type Server struct {
|
|||||||
// Secret(s) for Tsig map[<zonename>]<base64 secret>.
|
// Secret(s) for Tsig map[<zonename>]<base64 secret>.
|
||||||
TsigSecret map[string]string
|
TsigSecret map[string]string
|
||||||
// Unsafe instructs the server to disregard any sanity checks and directly hand the message to
|
// Unsafe instructs the server to disregard any sanity checks and directly hand the message to
|
||||||
// the handler. It will specfically not check if the query has the QR bit not set.
|
// the handler. It will specifically not check if the query has the QR bit not set.
|
||||||
Unsafe bool
|
Unsafe bool
|
||||||
// If NotifyStartedFunc is set is is called, once the server has started listening.
|
// If NotifyStartedFunc is set it is called once the server has started listening.
|
||||||
NotifyStartedFunc func()
|
NotifyStartedFunc func()
|
||||||
|
// DecorateReader is optional, allows customization of the process that reads raw DNS messages.
|
||||||
|
DecorateReader DecorateReader
|
||||||
|
// DecorateWriter is optional, allows customization of the process that writes raw DNS messages.
|
||||||
|
DecorateWriter DecorateWriter
|
||||||
|
|
||||||
// For graceful shutdown.
|
// Graceful shutdown handling
|
||||||
stopUDP chan bool
|
|
||||||
stopTCP chan bool
|
|
||||||
wgUDP sync.WaitGroup
|
|
||||||
wgTCP sync.WaitGroup
|
|
||||||
|
|
||||||
// make start/shutdown not racy
|
inFlight sync.WaitGroup
|
||||||
lock sync.Mutex
|
|
||||||
|
lock sync.RWMutex
|
||||||
started bool
|
started bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenAndServe starts a nameserver on the configured address in *Server.
|
// ListenAndServe starts a nameserver on the configured address in *Server.
|
||||||
func (srv *Server) ListenAndServe() error {
|
func (srv *Server) ListenAndServe() error {
|
||||||
srv.lock.Lock()
|
srv.lock.Lock()
|
||||||
|
defer srv.lock.Unlock()
|
||||||
if srv.started {
|
if srv.started {
|
||||||
return &Error{err: "server already started"}
|
return &Error{err: "server already started"}
|
||||||
}
|
}
|
||||||
srv.stopUDP, srv.stopTCP = make(chan bool), make(chan bool)
|
|
||||||
srv.started = true
|
|
||||||
srv.lock.Unlock()
|
|
||||||
addr := srv.Addr
|
addr := srv.Addr
|
||||||
if addr == "" {
|
if addr == "" {
|
||||||
addr = ":domain"
|
addr = ":domain"
|
||||||
@ -263,7 +328,30 @@ func (srv *Server) ListenAndServe() error {
|
|||||||
if e != nil {
|
if e != nil {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
return srv.serveTCP(l)
|
srv.Listener = l
|
||||||
|
srv.started = true
|
||||||
|
srv.lock.Unlock()
|
||||||
|
e = srv.serveTCP(l)
|
||||||
|
srv.lock.Lock() // to satisfy the defer at the top
|
||||||
|
return e
|
||||||
|
case "tcp-tls", "tcp4-tls", "tcp6-tls":
|
||||||
|
network := "tcp"
|
||||||
|
if srv.Net == "tcp4-tls" {
|
||||||
|
network = "tcp4"
|
||||||
|
} else if srv.Net == "tcp6" {
|
||||||
|
network = "tcp6"
|
||||||
|
}
|
||||||
|
|
||||||
|
l, e := tls.Listen(network, addr, srv.TLSConfig)
|
||||||
|
if e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
srv.Listener = l
|
||||||
|
srv.started = true
|
||||||
|
srv.lock.Unlock()
|
||||||
|
e = srv.serveTCP(l)
|
||||||
|
srv.lock.Lock() // to satisfy the defer at the top
|
||||||
|
return e
|
||||||
case "udp", "udp4", "udp6":
|
case "udp", "udp4", "udp6":
|
||||||
a, e := net.ResolveUDPAddr(srv.Net, addr)
|
a, e := net.ResolveUDPAddr(srv.Net, addr)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
@ -276,7 +364,12 @@ func (srv *Server) ListenAndServe() error {
|
|||||||
if e := setUDPSocketOptions(l); e != nil {
|
if e := setUDPSocketOptions(l); e != nil {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
return srv.serveUDP(l)
|
srv.PacketConn = l
|
||||||
|
srv.started = true
|
||||||
|
srv.lock.Unlock()
|
||||||
|
e = srv.serveUDP(l)
|
||||||
|
srv.lock.Lock() // to satisfy the defer at the top
|
||||||
|
return e
|
||||||
}
|
}
|
||||||
return &Error{err: "bad network"}
|
return &Error{err: "bad network"}
|
||||||
}
|
}
|
||||||
@ -285,71 +378,62 @@ func (srv *Server) ListenAndServe() error {
|
|||||||
// configured in *Server. Its main use is to start a server from systemd.
|
// configured in *Server. Its main use is to start a server from systemd.
|
||||||
func (srv *Server) ActivateAndServe() error {
|
func (srv *Server) ActivateAndServe() error {
|
||||||
srv.lock.Lock()
|
srv.lock.Lock()
|
||||||
|
defer srv.lock.Unlock()
|
||||||
if srv.started {
|
if srv.started {
|
||||||
return &Error{err: "server already started"}
|
return &Error{err: "server already started"}
|
||||||
}
|
}
|
||||||
srv.stopUDP, srv.stopTCP = make(chan bool), make(chan bool)
|
pConn := srv.PacketConn
|
||||||
srv.started = true
|
l := srv.Listener
|
||||||
srv.lock.Unlock()
|
if pConn != nil {
|
||||||
if srv.PacketConn != nil {
|
|
||||||
if srv.UDPSize == 0 {
|
if srv.UDPSize == 0 {
|
||||||
srv.UDPSize = MinMsgSize
|
srv.UDPSize = MinMsgSize
|
||||||
}
|
}
|
||||||
if t, ok := srv.PacketConn.(*net.UDPConn); ok {
|
if t, ok := pConn.(*net.UDPConn); ok {
|
||||||
if e := setUDPSocketOptions(t); e != nil {
|
if e := setUDPSocketOptions(t); e != nil {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
return srv.serveUDP(t)
|
srv.started = true
|
||||||
|
srv.lock.Unlock()
|
||||||
|
e := srv.serveUDP(t)
|
||||||
|
srv.lock.Lock() // to satisfy the defer at the top
|
||||||
|
return e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if srv.Listener != nil {
|
if l != nil {
|
||||||
if t, ok := srv.Listener.(*net.TCPListener); ok {
|
srv.started = true
|
||||||
return srv.serveTCP(t)
|
srv.lock.Unlock()
|
||||||
}
|
e := srv.serveTCP(l)
|
||||||
|
srv.lock.Lock() // to satisfy the defer at the top
|
||||||
|
return e
|
||||||
}
|
}
|
||||||
return &Error{err: "bad listeners"}
|
return &Error{err: "bad listeners"}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown gracefully shuts down a server. After a call to Shutdown, ListenAndServe and
|
// Shutdown gracefully shuts down a server. After a call to Shutdown, ListenAndServe and
|
||||||
// ActivateAndServe will return. All in progress queries are completed before the server
|
// ActivateAndServe will return. All in progress queries are completed before the server
|
||||||
// is taken down. If the Shutdown is taking longer than the reading timeout and error
|
// is taken down. If the Shutdown is taking longer than the reading timeout an error
|
||||||
// is returned.
|
// is returned.
|
||||||
func (srv *Server) Shutdown() error {
|
func (srv *Server) Shutdown() error {
|
||||||
srv.lock.Lock()
|
srv.lock.Lock()
|
||||||
if !srv.started {
|
if !srv.started {
|
||||||
|
srv.lock.Unlock()
|
||||||
return &Error{err: "server not started"}
|
return &Error{err: "server not started"}
|
||||||
}
|
}
|
||||||
srv.started = false
|
srv.started = false
|
||||||
srv.lock.Unlock()
|
srv.lock.Unlock()
|
||||||
net, addr := srv.Net, srv.Addr
|
|
||||||
switch {
|
if srv.PacketConn != nil {
|
||||||
case srv.Listener != nil:
|
srv.PacketConn.Close()
|
||||||
a := srv.Listener.Addr()
|
}
|
||||||
net, addr = a.Network(), a.String()
|
if srv.Listener != nil {
|
||||||
case srv.PacketConn != nil:
|
srv.Listener.Close()
|
||||||
a := srv.PacketConn.LocalAddr()
|
|
||||||
net, addr = a.Network(), a.String()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fin := make(chan bool)
|
fin := make(chan bool)
|
||||||
switch net {
|
go func() {
|
||||||
case "tcp", "tcp4", "tcp6":
|
srv.inFlight.Wait()
|
||||||
go func() {
|
fin <- true
|
||||||
srv.stopTCP <- true
|
}()
|
||||||
srv.wgTCP.Wait()
|
|
||||||
fin <- true
|
|
||||||
}()
|
|
||||||
|
|
||||||
case "udp", "udp4", "udp6":
|
|
||||||
go func() {
|
|
||||||
srv.stopUDP <- true
|
|
||||||
srv.wgUDP.Wait()
|
|
||||||
fin <- true
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
c := &Client{Net: net}
|
|
||||||
go c.Exchange(new(Msg), addr) // extra query to help ReadXXX loop to pass
|
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-time.After(srv.getReadTimeout()):
|
case <-time.After(srv.getReadTimeout()):
|
||||||
@ -369,14 +453,19 @@ func (srv *Server) getReadTimeout() time.Duration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// serveTCP starts a TCP listener for the server.
|
// serveTCP starts a TCP listener for the server.
|
||||||
// Each request is handled in a seperate goroutine.
|
// Each request is handled in a separate goroutine.
|
||||||
func (srv *Server) serveTCP(l *net.TCPListener) error {
|
func (srv *Server) serveTCP(l net.Listener) error {
|
||||||
defer l.Close()
|
defer l.Close()
|
||||||
|
|
||||||
if srv.NotifyStartedFunc != nil {
|
if srv.NotifyStartedFunc != nil {
|
||||||
srv.NotifyStartedFunc()
|
srv.NotifyStartedFunc()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reader := Reader(&defaultReader{srv})
|
||||||
|
if srv.DecorateReader != nil {
|
||||||
|
reader = srv.DecorateReader(reader)
|
||||||
|
}
|
||||||
|
|
||||||
handler := srv.Handler
|
handler := srv.Handler
|
||||||
if handler == nil {
|
if handler == nil {
|
||||||
handler = DefaultServeMux
|
handler = DefaultServeMux
|
||||||
@ -384,27 +473,30 @@ func (srv *Server) serveTCP(l *net.TCPListener) error {
|
|||||||
rtimeout := srv.getReadTimeout()
|
rtimeout := srv.getReadTimeout()
|
||||||
// deadline is not used here
|
// deadline is not used here
|
||||||
for {
|
for {
|
||||||
rw, e := l.AcceptTCP()
|
rw, e := l.Accept()
|
||||||
if e != nil {
|
if e != nil {
|
||||||
continue
|
if neterr, ok := e.(net.Error); ok && neterr.Temporary() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return e
|
||||||
}
|
}
|
||||||
m, e := srv.readTCP(rw, rtimeout)
|
m, e := reader.ReadTCP(rw, rtimeout)
|
||||||
select {
|
srv.lock.RLock()
|
||||||
case <-srv.stopTCP:
|
if !srv.started {
|
||||||
|
srv.lock.RUnlock()
|
||||||
return nil
|
return nil
|
||||||
default:
|
|
||||||
}
|
}
|
||||||
|
srv.lock.RUnlock()
|
||||||
if e != nil {
|
if e != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
srv.wgTCP.Add(1)
|
srv.inFlight.Add(1)
|
||||||
go srv.serve(rw.RemoteAddr(), handler, m, nil, nil, rw)
|
go srv.serve(rw.RemoteAddr(), handler, m, nil, nil, rw)
|
||||||
}
|
}
|
||||||
panic("dns: not reached")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// serveUDP starts a UDP listener for the server.
|
// serveUDP starts a UDP listener for the server.
|
||||||
// Each request is handled in a seperate goroutine.
|
// Each request is handled in a separate goroutine.
|
||||||
func (srv *Server) serveUDP(l *net.UDPConn) error {
|
func (srv *Server) serveUDP(l *net.UDPConn) error {
|
||||||
defer l.Close()
|
defer l.Close()
|
||||||
|
|
||||||
@ -412,6 +504,11 @@ func (srv *Server) serveUDP(l *net.UDPConn) error {
|
|||||||
srv.NotifyStartedFunc()
|
srv.NotifyStartedFunc()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reader := Reader(&defaultReader{srv})
|
||||||
|
if srv.DecorateReader != nil {
|
||||||
|
reader = srv.DecorateReader(reader)
|
||||||
|
}
|
||||||
|
|
||||||
handler := srv.Handler
|
handler := srv.Handler
|
||||||
if handler == nil {
|
if handler == nil {
|
||||||
handler = DefaultServeMux
|
handler = DefaultServeMux
|
||||||
@ -419,35 +516,39 @@ 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 {
|
for {
|
||||||
m, s, e := srv.readUDP(l, rtimeout)
|
m, s, e := reader.ReadUDP(l, rtimeout)
|
||||||
select {
|
srv.lock.RLock()
|
||||||
case <-srv.stopUDP:
|
if !srv.started {
|
||||||
|
srv.lock.RUnlock()
|
||||||
return nil
|
return nil
|
||||||
default:
|
|
||||||
}
|
}
|
||||||
|
srv.lock.RUnlock()
|
||||||
if e != nil {
|
if e != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
srv.wgUDP.Add(1)
|
srv.inFlight.Add(1)
|
||||||
go srv.serve(s.RemoteAddr(), handler, m, l, s, nil)
|
go srv.serve(s.RemoteAddr(), handler, m, l, s, nil)
|
||||||
}
|
}
|
||||||
panic("dns: not reached")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serve a new connection.
|
// Serve a new connection.
|
||||||
func (srv *Server) serve(a net.Addr, h Handler, m []byte, u *net.UDPConn, s *sessionUDP, t *net.TCPConn) {
|
func (srv *Server) serve(a net.Addr, h Handler, m []byte, u *net.UDPConn, s *SessionUDP, t net.Conn) {
|
||||||
|
defer srv.inFlight.Done()
|
||||||
|
|
||||||
w := &response{tsigSecret: srv.TsigSecret, udp: u, tcp: t, remoteAddr: a, udpSession: s}
|
w := &response{tsigSecret: srv.TsigSecret, udp: u, tcp: t, remoteAddr: a, udpSession: s}
|
||||||
q := 0
|
if srv.DecorateWriter != nil {
|
||||||
defer func() {
|
w.writer = srv.DecorateWriter(w)
|
||||||
if u != nil {
|
} else {
|
||||||
srv.wgUDP.Done()
|
w.writer = w
|
||||||
}
|
}
|
||||||
if t != nil {
|
|
||||||
srv.wgTCP.Done()
|
q := 0 // counter for the amount of TCP queries we get
|
||||||
}
|
|
||||||
}()
|
reader := Reader(&defaultReader{srv})
|
||||||
|
if srv.DecorateReader != nil {
|
||||||
|
reader = srv.DecorateReader(reader)
|
||||||
|
}
|
||||||
Redo:
|
Redo:
|
||||||
// Ideally we want use isMsg here before we allocate memory to actually parse the packet.
|
|
||||||
req := new(Msg)
|
req := new(Msg)
|
||||||
err := req.Unpack(m)
|
err := req.Unpack(m)
|
||||||
if err != nil { // Send a FormatError back
|
if err != nil { // Send a FormatError back
|
||||||
@ -475,6 +576,15 @@ Redo:
|
|||||||
h.ServeDNS(w, req) // Writes back to the client
|
h.ServeDNS(w, req) // Writes back to the client
|
||||||
|
|
||||||
Exit:
|
Exit:
|
||||||
|
if w.tcp == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// TODO(miek): make this number configurable?
|
||||||
|
if q > maxTCPQueries { // close socket after this many queries
|
||||||
|
w.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if w.hijacked {
|
if w.hijacked {
|
||||||
return // client calls Close()
|
return // client calls Close()
|
||||||
}
|
}
|
||||||
@ -486,21 +596,16 @@ Exit:
|
|||||||
if srv.IdleTimeout != nil {
|
if srv.IdleTimeout != nil {
|
||||||
idleTimeout = srv.IdleTimeout()
|
idleTimeout = srv.IdleTimeout()
|
||||||
}
|
}
|
||||||
m, e := srv.readTCP(w.tcp, idleTimeout)
|
m, e := reader.ReadTCP(w.tcp, idleTimeout)
|
||||||
if e == nil {
|
if e == nil {
|
||||||
q++
|
q++
|
||||||
// TODO(miek): make this number configurable?
|
|
||||||
if q > 128 { // close socket after this many queries
|
|
||||||
w.Close()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
goto Redo
|
goto Redo
|
||||||
}
|
}
|
||||||
w.Close()
|
w.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (srv *Server) readTCP(conn *net.TCPConn, timeout time.Duration) ([]byte, error) {
|
func (srv *Server) readTCP(conn net.Conn, timeout time.Duration) ([]byte, error) {
|
||||||
conn.SetReadDeadline(time.Now().Add(timeout))
|
conn.SetReadDeadline(time.Now().Add(timeout))
|
||||||
l := make([]byte, 2)
|
l := make([]byte, 2)
|
||||||
n, err := conn.Read(l)
|
n, err := conn.Read(l)
|
||||||
@ -535,10 +640,10 @@ func (srv *Server) readTCP(conn *net.TCPConn, timeout time.Duration) ([]byte, er
|
|||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (srv *Server) readUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *sessionUDP, error) {
|
func (srv *Server) readUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error) {
|
||||||
conn.SetReadDeadline(time.Now().Add(timeout))
|
conn.SetReadDeadline(time.Now().Add(timeout))
|
||||||
m := make([]byte, srv.UDPSize)
|
m := make([]byte, srv.UDPSize)
|
||||||
n, s, e := readFromSessionUDP(conn, m)
|
n, s, e := ReadFromSessionUDP(conn, m)
|
||||||
if e != nil || n == 0 {
|
if e != nil || n == 0 {
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return nil, nil, e
|
return nil, nil, e
|
||||||
@ -558,7 +663,7 @@ func (w *response) WriteMsg(m *Msg) (err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = w.Write(data)
|
_, err = w.writer.Write(data)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -566,7 +671,7 @@ func (w *response) WriteMsg(m *Msg) (err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = w.Write(data)
|
_, err = w.writer.Write(data)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -574,7 +679,7 @@ func (w *response) WriteMsg(m *Msg) (err error) {
|
|||||||
func (w *response) Write(m []byte) (int, error) {
|
func (w *response) Write(m []byte) (int, error) {
|
||||||
switch {
|
switch {
|
||||||
case w.udp != nil:
|
case w.udp != nil:
|
||||||
n, err := writeToSessionUDP(w.udp, m, w.udpSession)
|
n, err := WriteToSessionUDP(w.udp, m, w.udpSession)
|
||||||
return n, err
|
return n, err
|
||||||
case w.tcp != nil:
|
case w.tcp != nil:
|
||||||
lm := len(m)
|
lm := len(m)
|
||||||
|
74
vendor/github.com/miekg/dns/sig0.go
generated
vendored
74
vendor/github.com/miekg/dns/sig0.go
generated
vendored
@ -1,25 +1,9 @@
|
|||||||
// SIG(0)
|
|
||||||
//
|
|
||||||
// From RFC 2931:
|
|
||||||
//
|
|
||||||
// SIG(0) provides protection for DNS transactions and requests ....
|
|
||||||
// ... protection for glue records, DNS requests, protection for message headers
|
|
||||||
// on requests and responses, and protection of the overall integrity of a response.
|
|
||||||
//
|
|
||||||
// It works like TSIG, except that SIG(0) uses public key cryptography, instead of the shared
|
|
||||||
// secret approach in TSIG.
|
|
||||||
// Supported algorithms: DSA, ECDSAP256SHA256, ECDSAP384SHA384, RSASHA1, RSASHA256 and
|
|
||||||
// RSASHA512.
|
|
||||||
//
|
|
||||||
// Signing subsequent messages in multi-message sessions is not implemented.
|
|
||||||
//
|
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto"
|
"crypto"
|
||||||
"crypto/dsa"
|
"crypto/dsa"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"crypto/rand"
|
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
"math/big"
|
"math/big"
|
||||||
"strings"
|
"strings"
|
||||||
@ -29,7 +13,7 @@ import (
|
|||||||
// Sign signs a dns.Msg. It fills the signature with the appropriate data.
|
// Sign signs a dns.Msg. It fills the signature with the appropriate data.
|
||||||
// The SIG record should have the SignerName, KeyTag, Algorithm, Inception
|
// The SIG record should have the SignerName, KeyTag, Algorithm, Inception
|
||||||
// and Expiration set.
|
// and Expiration set.
|
||||||
func (rr *SIG) Sign(k PrivateKey, m *Msg) ([]byte, error) {
|
func (rr *SIG) Sign(k crypto.Signer, m *Msg) ([]byte, error) {
|
||||||
if k == nil {
|
if k == nil {
|
||||||
return nil, ErrPrivKey
|
return nil, ErrPrivKey
|
||||||
}
|
}
|
||||||
@ -57,56 +41,26 @@ func (rr *SIG) Sign(k PrivateKey, m *Msg) ([]byte, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
buf = buf[:off:cap(buf)]
|
buf = buf[:off:cap(buf)]
|
||||||
var hash crypto.Hash
|
|
||||||
var intlen int
|
hash, ok := AlgorithmToHash[rr.Algorithm]
|
||||||
switch rr.Algorithm {
|
if !ok {
|
||||||
case DSA, RSASHA1:
|
|
||||||
hash = crypto.SHA1
|
|
||||||
case RSASHA256, ECDSAP256SHA256:
|
|
||||||
hash = crypto.SHA256
|
|
||||||
intlen = 32
|
|
||||||
case ECDSAP384SHA384:
|
|
||||||
hash = crypto.SHA384
|
|
||||||
intlen = 48
|
|
||||||
case RSASHA512:
|
|
||||||
hash = crypto.SHA512
|
|
||||||
default:
|
|
||||||
return nil, ErrAlg
|
return nil, ErrAlg
|
||||||
}
|
}
|
||||||
|
|
||||||
hasher := hash.New()
|
hasher := hash.New()
|
||||||
// Write SIG rdata
|
// Write SIG rdata
|
||||||
hasher.Write(buf[len(mbuf)+1+2+2+4+2:])
|
hasher.Write(buf[len(mbuf)+1+2+2+4+2:])
|
||||||
// Write message
|
// Write message
|
||||||
hasher.Write(buf[:len(mbuf)])
|
hasher.Write(buf[:len(mbuf)])
|
||||||
hashed := hasher.Sum(nil)
|
|
||||||
|
|
||||||
var sig []byte
|
signature, err := sign(k, hasher.Sum(nil), hash, rr.Algorithm)
|
||||||
switch p := k.(type) {
|
if err != nil {
|
||||||
case *dsa.PrivateKey:
|
return nil, err
|
||||||
t := divRoundUp(divRoundUp(p.PublicKey.Y.BitLen(), 8)-64, 8)
|
|
||||||
r1, s1, err := dsa.Sign(rand.Reader, p, hashed)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
sig = append(sig, byte(t))
|
|
||||||
sig = append(sig, intToBytes(r1, 20)...)
|
|
||||||
sig = append(sig, intToBytes(s1, 20)...)
|
|
||||||
case *rsa.PrivateKey:
|
|
||||||
sig, err = rsa.SignPKCS1v15(rand.Reader, p, hash, hashed)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
case *ecdsa.PrivateKey:
|
|
||||||
r1, s1, err := ecdsa.Sign(rand.Reader, p, hashed)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
sig = intToBytes(r1, intlen)
|
|
||||||
sig = append(sig, intToBytes(s1, intlen)...)
|
|
||||||
default:
|
|
||||||
return nil, ErrAlg
|
|
||||||
}
|
}
|
||||||
rr.Signature = toBase64(sig)
|
|
||||||
|
rr.Signature = toBase64(signature)
|
||||||
|
sig := string(signature)
|
||||||
|
|
||||||
buf = append(buf, sig...)
|
buf = append(buf, sig...)
|
||||||
if len(buf) > int(^uint16(0)) {
|
if len(buf) > int(^uint16(0)) {
|
||||||
return nil, ErrBuf
|
return nil, ErrBuf
|
||||||
@ -118,7 +72,7 @@ func (rr *SIG) Sign(k PrivateKey, m *Msg) ([]byte, error) {
|
|||||||
buf[rdoff], buf[rdoff+1] = packUint16(rdlen)
|
buf[rdoff], buf[rdoff+1] = packUint16(rdlen)
|
||||||
// Adjust additional count
|
// Adjust additional count
|
||||||
adc, _ := unpackUint16(buf, 10)
|
adc, _ := unpackUint16(buf, 10)
|
||||||
adc += 1
|
adc++
|
||||||
buf[10], buf[11] = packUint16(adc)
|
buf[10], buf[11] = packUint16(adc)
|
||||||
return buf, nil
|
return buf, nil
|
||||||
}
|
}
|
||||||
@ -246,7 +200,7 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
|
|||||||
return rsa.VerifyPKCS1v15(pk, hash, hashed, sig)
|
return rsa.VerifyPKCS1v15(pk, hash, hashed, sig)
|
||||||
}
|
}
|
||||||
case ECDSAP256SHA256, ECDSAP384SHA384:
|
case ECDSAP256SHA256, ECDSAP384SHA384:
|
||||||
pk := k.publicKeyCurve()
|
pk := k.publicKeyECDSA()
|
||||||
r := big.NewInt(0)
|
r := big.NewInt(0)
|
||||||
r.SetBytes(sig[:len(sig)/2])
|
r.SetBytes(sig[:len(sig)/2])
|
||||||
s := big.NewInt(0)
|
s := big.NewInt(0)
|
||||||
|
8
vendor/github.com/miekg/dns/tlsa.go
generated
vendored
8
vendor/github.com/miekg/dns/tlsa.go
generated
vendored
@ -25,7 +25,8 @@ func CertificateToDANE(selector, matchingType uint8, cert *x509.Certificate) (st
|
|||||||
h := sha256.New()
|
h := sha256.New()
|
||||||
switch selector {
|
switch selector {
|
||||||
case 0:
|
case 0:
|
||||||
return hex.EncodeToString(cert.Raw), nil
|
io.WriteString(h, string(cert.Raw))
|
||||||
|
return hex.EncodeToString(h.Sum(nil)), nil
|
||||||
case 1:
|
case 1:
|
||||||
io.WriteString(h, string(cert.RawSubjectPublicKeyInfo))
|
io.WriteString(h, string(cert.RawSubjectPublicKeyInfo))
|
||||||
return hex.EncodeToString(h.Sum(nil)), nil
|
return hex.EncodeToString(h.Sum(nil)), nil
|
||||||
@ -34,7 +35,8 @@ func CertificateToDANE(selector, matchingType uint8, cert *x509.Certificate) (st
|
|||||||
h := sha512.New()
|
h := sha512.New()
|
||||||
switch selector {
|
switch selector {
|
||||||
case 0:
|
case 0:
|
||||||
return hex.EncodeToString(cert.Raw), nil
|
io.WriteString(h, string(cert.Raw))
|
||||||
|
return hex.EncodeToString(h.Sum(nil)), nil
|
||||||
case 1:
|
case 1:
|
||||||
io.WriteString(h, string(cert.RawSubjectPublicKeyInfo))
|
io.WriteString(h, string(cert.RawSubjectPublicKeyInfo))
|
||||||
return hex.EncodeToString(h.Sum(nil)), nil
|
return hex.EncodeToString(h.Sum(nil)), nil
|
||||||
@ -80,5 +82,5 @@ func TLSAName(name, service, network string) (string, error) {
|
|||||||
if e != nil {
|
if e != nil {
|
||||||
return "", e
|
return "", e
|
||||||
}
|
}
|
||||||
return "_" + strconv.Itoa(p) + "_" + network + "." + name, nil
|
return "_" + strconv.Itoa(p) + "._" + network + "." + name, nil
|
||||||
}
|
}
|
||||||
|
78
vendor/github.com/miekg/dns/tsig.go
generated
vendored
78
vendor/github.com/miekg/dns/tsig.go
generated
vendored
@ -1,56 +1,3 @@
|
|||||||
// TRANSACTION SIGNATURE
|
|
||||||
//
|
|
||||||
// An TSIG or transaction signature adds a HMAC TSIG record to each message sent.
|
|
||||||
// The supported algorithms include: HmacMD5, HmacSHA1 and HmacSHA256.
|
|
||||||
//
|
|
||||||
// Basic use pattern when querying with a TSIG name "axfr." (note that these key names
|
|
||||||
// must be fully qualified - as they are domain names) and the base64 secret
|
|
||||||
// "so6ZGir4GPAqINNh9U5c3A==":
|
|
||||||
//
|
|
||||||
// c := new(dns.Client)
|
|
||||||
// c.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="}
|
|
||||||
// m := new(dns.Msg)
|
|
||||||
// m.SetQuestion("miek.nl.", dns.TypeMX)
|
|
||||||
// m.SetTsig("axfr.", dns.HmacMD5, 300, time.Now().Unix())
|
|
||||||
// ...
|
|
||||||
// // When sending the TSIG RR is calculated and filled in before sending
|
|
||||||
//
|
|
||||||
// When requesting an zone transfer (almost all TSIG usage is when requesting zone transfers), with
|
|
||||||
// TSIG, this is the basic use pattern. In this example we request an AXFR for
|
|
||||||
// miek.nl. with TSIG key named "axfr." and secret "so6ZGir4GPAqINNh9U5c3A=="
|
|
||||||
// and using the server 176.58.119.54:
|
|
||||||
//
|
|
||||||
// t := new(dns.Transfer)
|
|
||||||
// m := new(dns.Msg)
|
|
||||||
// t.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="}
|
|
||||||
// m.SetAxfr("miek.nl.")
|
|
||||||
// m.SetTsig("axfr.", dns.HmacMD5, 300, time.Now().Unix())
|
|
||||||
// c, err := t.In(m, "176.58.119.54:53")
|
|
||||||
// for r := range c { /* r.RR */ }
|
|
||||||
//
|
|
||||||
// You can now read the records from the transfer as they come in. Each envelope is checked with TSIG.
|
|
||||||
// If something is not correct an error is returned.
|
|
||||||
//
|
|
||||||
// Basic use pattern validating and replying to a message that has TSIG set.
|
|
||||||
//
|
|
||||||
// server := &dns.Server{Addr: ":53", Net: "udp"}
|
|
||||||
// server.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="}
|
|
||||||
// go server.ListenAndServe()
|
|
||||||
// dns.HandleFunc(".", handleRequest)
|
|
||||||
//
|
|
||||||
// func handleRequest(w dns.ResponseWriter, r *dns.Msg) {
|
|
||||||
// m := new(Msg)
|
|
||||||
// m.SetReply(r)
|
|
||||||
// if r.IsTsig() {
|
|
||||||
// if w.TsigStatus() == nil {
|
|
||||||
// // *Msg r has an TSIG record and it was validated
|
|
||||||
// m.SetTsig("axfr.", dns.HmacMD5, 300, time.Now().Unix())
|
|
||||||
// } else {
|
|
||||||
// // *Msg r has an TSIG records and it was not valided
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// w.WriteMsg(m)
|
|
||||||
// }
|
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -58,6 +5,7 @@ import (
|
|||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
|
"crypto/sha512"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"hash"
|
"hash"
|
||||||
"io"
|
"io"
|
||||||
@ -71,8 +19,11 @@ const (
|
|||||||
HmacMD5 = "hmac-md5.sig-alg.reg.int."
|
HmacMD5 = "hmac-md5.sig-alg.reg.int."
|
||||||
HmacSHA1 = "hmac-sha1."
|
HmacSHA1 = "hmac-sha1."
|
||||||
HmacSHA256 = "hmac-sha256."
|
HmacSHA256 = "hmac-sha256."
|
||||||
|
HmacSHA512 = "hmac-sha512."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TSIG is the RR the holds the transaction signature of a message.
|
||||||
|
// See RFC 2845 and RFC 4635.
|
||||||
type TSIG struct {
|
type TSIG struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
Algorithm string `dns:"domain-name"`
|
Algorithm string `dns:"domain-name"`
|
||||||
@ -86,10 +37,6 @@ type TSIG struct {
|
|||||||
OtherData string `dns:"size-hex"`
|
OtherData string `dns:"size-hex"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rr *TSIG) Header() *RR_Header {
|
|
||||||
return &rr.Hdr
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 {
|
||||||
@ -107,15 +54,6 @@ func (rr *TSIG) String() string {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rr *TSIG) len() int {
|
|
||||||
return rr.Hdr.len() + len(rr.Algorithm) + 1 + 6 +
|
|
||||||
4 + len(rr.MAC)/2 + 1 + 6 + len(rr.OtherData)/2 + 1
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rr *TSIG) copy() RR {
|
|
||||||
return &TSIG{*rr.Hdr.copyHeader(), rr.Algorithm, rr.TimeSigned, rr.Fudge, rr.MACSize, rr.MAC, rr.OrigId, rr.Error, rr.OtherLen, rr.OtherData}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The following values must be put in wireformat, so that the MAC can be calculated.
|
// The following values must be put in wireformat, so that the MAC can be calculated.
|
||||||
// RFC 2845, section 3.4.2. TSIG Variables.
|
// RFC 2845, section 3.4.2. TSIG Variables.
|
||||||
type tsigWireFmt struct {
|
type tsigWireFmt struct {
|
||||||
@ -174,13 +112,15 @@ func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, s
|
|||||||
|
|
||||||
t := new(TSIG)
|
t := new(TSIG)
|
||||||
var h hash.Hash
|
var h hash.Hash
|
||||||
switch rr.Algorithm {
|
switch strings.ToLower(rr.Algorithm) {
|
||||||
case HmacMD5:
|
case HmacMD5:
|
||||||
h = hmac.New(md5.New, []byte(rawsecret))
|
h = hmac.New(md5.New, []byte(rawsecret))
|
||||||
case HmacSHA1:
|
case HmacSHA1:
|
||||||
h = hmac.New(sha1.New, []byte(rawsecret))
|
h = hmac.New(sha1.New, []byte(rawsecret))
|
||||||
case HmacSHA256:
|
case HmacSHA256:
|
||||||
h = hmac.New(sha256.New, []byte(rawsecret))
|
h = hmac.New(sha256.New, []byte(rawsecret))
|
||||||
|
case HmacSHA512:
|
||||||
|
h = hmac.New(sha512.New, []byte(rawsecret))
|
||||||
default:
|
default:
|
||||||
return nil, "", ErrKeyAlg
|
return nil, "", ErrKeyAlg
|
||||||
}
|
}
|
||||||
@ -238,13 +178,15 @@ func TsigVerify(msg []byte, secret, requestMAC string, timersOnly bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var h hash.Hash
|
var h hash.Hash
|
||||||
switch tsig.Algorithm {
|
switch strings.ToLower(tsig.Algorithm) {
|
||||||
case HmacMD5:
|
case HmacMD5:
|
||||||
h = hmac.New(md5.New, rawsecret)
|
h = hmac.New(md5.New, rawsecret)
|
||||||
case HmacSHA1:
|
case HmacSHA1:
|
||||||
h = hmac.New(sha1.New, rawsecret)
|
h = hmac.New(sha1.New, rawsecret)
|
||||||
case HmacSHA256:
|
case HmacSHA256:
|
||||||
h = hmac.New(sha256.New, rawsecret)
|
h = hmac.New(sha256.New, rawsecret)
|
||||||
|
case HmacSHA512:
|
||||||
|
h = hmac.New(sha512.New, rawsecret)
|
||||||
default:
|
default:
|
||||||
return ErrKeyAlg
|
return ErrKeyAlg
|
||||||
}
|
}
|
||||||
|
643
vendor/github.com/miekg/dns/types.go
generated
vendored
643
vendor/github.com/miekg/dns/types.go
generated
vendored
File diff suppressed because it is too large
Load Diff
266
vendor/github.com/miekg/dns/types_generate.go
generated
vendored
Normal file
266
vendor/github.com/miekg/dns/types_generate.go
generated
vendored
Normal file
@ -0,0 +1,266 @@
|
|||||||
|
//+build ignore
|
||||||
|
|
||||||
|
// types_generate.go is meant to run with go generate. It will use
|
||||||
|
// go/{importer,types} to track down all the RR struct types. Then for each type
|
||||||
|
// it will generate conversion tables (TypeToRR and TypeToString) and banal
|
||||||
|
// methods (len, Header, copy) based on the struct tags. The generated source is
|
||||||
|
// written to ztypes.go, and is meant to be checked into git.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"go/format"
|
||||||
|
"go/importer"
|
||||||
|
"go/types"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
var skipLen = map[string]struct{}{
|
||||||
|
"NSEC": {},
|
||||||
|
"NSEC3": {},
|
||||||
|
"OPT": {},
|
||||||
|
"WKS": {},
|
||||||
|
"IPSECKEY": {},
|
||||||
|
}
|
||||||
|
|
||||||
|
var packageHdr = `
|
||||||
|
// *** DO NOT MODIFY ***
|
||||||
|
// AUTOGENERATED BY go generate
|
||||||
|
|
||||||
|
package dns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
`
|
||||||
|
|
||||||
|
var TypeToRR = template.Must(template.New("TypeToRR").Parse(`
|
||||||
|
// TypeToRR is a map of constructors for each RR type.
|
||||||
|
var TypeToRR = map[uint16]func() RR{
|
||||||
|
{{range .}}{{if ne . "RFC3597"}} Type{{.}}: func() RR { return new({{.}}) },
|
||||||
|
{{end}}{{end}} }
|
||||||
|
|
||||||
|
`))
|
||||||
|
|
||||||
|
var typeToString = template.Must(template.New("typeToString").Parse(`
|
||||||
|
// TypeToString is a map of strings for each RR type.
|
||||||
|
var TypeToString = map[uint16]string{
|
||||||
|
{{range .}}{{if ne . "NSAPPTR"}} Type{{.}}: "{{.}}",
|
||||||
|
{{end}}{{end}} TypeNSAPPTR: "NSAP-PTR",
|
||||||
|
}
|
||||||
|
|
||||||
|
`))
|
||||||
|
|
||||||
|
var headerFunc = template.Must(template.New("headerFunc").Parse(`
|
||||||
|
// Header() functions
|
||||||
|
{{range .}} func (rr *{{.}}) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
`))
|
||||||
|
|
||||||
|
// getTypeStruct will take a type and the package scope, and return the
|
||||||
|
// (innermost) struct if the type is considered a RR type (currently defined as
|
||||||
|
// those structs beginning with a RR_Header, could be redefined as implementing
|
||||||
|
// the RR interface). The bool return value indicates if embedded structs were
|
||||||
|
// resolved.
|
||||||
|
func getTypeStruct(t types.Type, scope *types.Scope) (*types.Struct, bool) {
|
||||||
|
st, ok := t.Underlying().(*types.Struct)
|
||||||
|
if !ok {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
if st.Field(0).Type() == scope.Lookup("RR_Header").Type() {
|
||||||
|
return st, false
|
||||||
|
}
|
||||||
|
if st.Field(0).Anonymous() {
|
||||||
|
st, _ := getTypeStruct(st.Field(0).Type(), scope)
|
||||||
|
return st, true
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Import and type-check the package
|
||||||
|
pkg, err := importer.Default().Import("github.com/miekg/dns")
|
||||||
|
fatalIfErr(err)
|
||||||
|
scope := pkg.Scope()
|
||||||
|
|
||||||
|
// Collect constants like TypeX
|
||||||
|
var numberedTypes []string
|
||||||
|
for _, name := range scope.Names() {
|
||||||
|
o := scope.Lookup(name)
|
||||||
|
if o == nil || !o.Exported() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
b, ok := o.Type().(*types.Basic)
|
||||||
|
if !ok || b.Kind() != types.Uint16 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !strings.HasPrefix(o.Name(), "Type") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
name := strings.TrimPrefix(o.Name(), "Type")
|
||||||
|
if name == "PrivateRR" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
numberedTypes = append(numberedTypes, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect actual types (*X)
|
||||||
|
var namedTypes []string
|
||||||
|
for _, name := range scope.Names() {
|
||||||
|
o := scope.Lookup(name)
|
||||||
|
if o == nil || !o.Exported() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if st, _ := getTypeStruct(o.Type(), scope); st == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if name == "PrivateRR" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if corresponding TypeX exists
|
||||||
|
if scope.Lookup("Type"+o.Name()) == nil && o.Name() != "RFC3597" {
|
||||||
|
log.Fatalf("Constant Type%s does not exist.", o.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
namedTypes = append(namedTypes, o.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
b := &bytes.Buffer{}
|
||||||
|
b.WriteString(packageHdr)
|
||||||
|
|
||||||
|
// Generate TypeToRR
|
||||||
|
fatalIfErr(TypeToRR.Execute(b, namedTypes))
|
||||||
|
|
||||||
|
// Generate typeToString
|
||||||
|
fatalIfErr(typeToString.Execute(b, numberedTypes))
|
||||||
|
|
||||||
|
// Generate headerFunc
|
||||||
|
fatalIfErr(headerFunc.Execute(b, namedTypes))
|
||||||
|
|
||||||
|
// Generate len()
|
||||||
|
fmt.Fprint(b, "// len() functions\n")
|
||||||
|
for _, name := range namedTypes {
|
||||||
|
if _, ok := skipLen[name]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
o := scope.Lookup(name)
|
||||||
|
st, isEmbedded := getTypeStruct(o.Type(), scope)
|
||||||
|
if isEmbedded {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Fprintf(b, "func (rr *%s) len() int {\n", name)
|
||||||
|
fmt.Fprintf(b, "l := rr.Hdr.len()\n")
|
||||||
|
for i := 1; i < st.NumFields(); i++ {
|
||||||
|
o := func(s string) { fmt.Fprintf(b, s, st.Field(i).Name()) }
|
||||||
|
|
||||||
|
if _, ok := st.Field(i).Type().(*types.Slice); ok {
|
||||||
|
switch st.Tag(i) {
|
||||||
|
case `dns:"-"`:
|
||||||
|
// ignored
|
||||||
|
case `dns:"cdomain-name"`, `dns:"domain-name"`, `dns:"txt"`:
|
||||||
|
o("for _, x := range rr.%s { l += len(x) + 1 }\n")
|
||||||
|
default:
|
||||||
|
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
switch st.Tag(i) {
|
||||||
|
case `dns:"-"`:
|
||||||
|
// ignored
|
||||||
|
case `dns:"cdomain-name"`, `dns:"domain-name"`:
|
||||||
|
o("l += len(rr.%s) + 1\n")
|
||||||
|
case `dns:"octet"`:
|
||||||
|
o("l += len(rr.%s)\n")
|
||||||
|
case `dns:"base64"`:
|
||||||
|
o("l += base64.StdEncoding.DecodedLen(len(rr.%s))\n")
|
||||||
|
case `dns:"size-hex"`, `dns:"hex"`:
|
||||||
|
o("l += len(rr.%s)/2 + 1\n")
|
||||||
|
case `dns:"a"`:
|
||||||
|
o("l += net.IPv4len // %s\n")
|
||||||
|
case `dns:"aaaa"`:
|
||||||
|
o("l += net.IPv6len // %s\n")
|
||||||
|
case `dns:"txt"`:
|
||||||
|
o("for _, t := range rr.%s { l += len(t) + 1 }\n")
|
||||||
|
case `dns:"uint48"`:
|
||||||
|
o("l += 6 // %s\n")
|
||||||
|
case "":
|
||||||
|
switch st.Field(i).Type().(*types.Basic).Kind() {
|
||||||
|
case types.Uint8:
|
||||||
|
o("l += 1 // %s\n")
|
||||||
|
case types.Uint16:
|
||||||
|
o("l += 2 // %s\n")
|
||||||
|
case types.Uint32:
|
||||||
|
o("l += 4 // %s\n")
|
||||||
|
case types.Uint64:
|
||||||
|
o("l += 8 // %s\n")
|
||||||
|
case types.String:
|
||||||
|
o("l += len(rr.%s) + 1\n")
|
||||||
|
default:
|
||||||
|
log.Fatalln(name, st.Field(i).Name())
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Fprintf(b, "return l }\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate copy()
|
||||||
|
fmt.Fprint(b, "// copy() functions\n")
|
||||||
|
for _, name := range namedTypes {
|
||||||
|
o := scope.Lookup(name)
|
||||||
|
st, isEmbedded := getTypeStruct(o.Type(), scope)
|
||||||
|
if isEmbedded {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Fprintf(b, "func (rr *%s) copy() RR {\n", name)
|
||||||
|
fields := []string{"*rr.Hdr.copyHeader()"}
|
||||||
|
for i := 1; i < st.NumFields(); i++ {
|
||||||
|
f := st.Field(i).Name()
|
||||||
|
if sl, ok := st.Field(i).Type().(*types.Slice); ok {
|
||||||
|
t := sl.Underlying().String()
|
||||||
|
t = strings.TrimPrefix(t, "[]")
|
||||||
|
t = strings.TrimPrefix(t, "github.com/miekg/dns.")
|
||||||
|
fmt.Fprintf(b, "%s := make([]%s, len(rr.%s)); copy(%s, rr.%s)\n",
|
||||||
|
f, t, f, f, f)
|
||||||
|
fields = append(fields, f)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if st.Field(i).Type().String() == "net.IP" {
|
||||||
|
fields = append(fields, "copyIP(rr."+f+")")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fields = append(fields, "rr."+f)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(b, "return &%s{%s}\n", name, strings.Join(fields, ","))
|
||||||
|
fmt.Fprintf(b, "}\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// gofmt
|
||||||
|
res, err := format.Source(b.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
b.WriteTo(os.Stderr)
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// write result
|
||||||
|
f, err := os.Create("ztypes.go")
|
||||||
|
fatalIfErr(err)
|
||||||
|
defer f.Close()
|
||||||
|
f.Write(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func fatalIfErr(err error) {
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
19
vendor/github.com/miekg/dns/udp.go
generated
vendored
19
vendor/github.com/miekg/dns/udp.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// +build !windows
|
// +build !windows,!plan9
|
||||||
|
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
@ -7,12 +7,15 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
type sessionUDP struct {
|
// SessionUDP holds the remote address and the associated
|
||||||
|
// out-of-band data.
|
||||||
|
type SessionUDP struct {
|
||||||
raddr *net.UDPAddr
|
raddr *net.UDPAddr
|
||||||
context []byte
|
context []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sessionUDP) RemoteAddr() net.Addr { return s.raddr }
|
// RemoteAddr returns the remote network address.
|
||||||
|
func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
|
||||||
|
|
||||||
// setUDPSocketOptions sets the UDP socket options.
|
// setUDPSocketOptions sets the UDP socket options.
|
||||||
// This function is implemented on a per platform basis. See udp_*.go for more details
|
// This function is implemented on a per platform basis. See udp_*.go for more details
|
||||||
@ -37,19 +40,19 @@ func setUDPSocketOptions(conn *net.UDPConn) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// readFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
|
// ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
|
||||||
// net.UDPAddr.
|
// net.UDPAddr.
|
||||||
func readFromSessionUDP(conn *net.UDPConn, b []byte) (int, *sessionUDP, error) {
|
func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
|
||||||
oob := make([]byte, 40)
|
oob := make([]byte, 40)
|
||||||
n, oobn, _, raddr, err := conn.ReadMsgUDP(b, oob)
|
n, oobn, _, raddr, err := conn.ReadMsgUDP(b, oob)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return n, nil, err
|
return n, nil, err
|
||||||
}
|
}
|
||||||
return n, &sessionUDP{raddr, oob[:oobn]}, err
|
return n, &SessionUDP{raddr, oob[:oobn]}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeToSessionUDP acts just like net.UDPConn.WritetTo(), but uses a *sessionUDP instead of a net.Addr.
|
// WriteToSessionUDP acts just like net.UDPConn.WritetTo(), but uses a *SessionUDP instead of a net.Addr.
|
||||||
func writeToSessionUDP(conn *net.UDPConn, b []byte, session *sessionUDP) (int, error) {
|
func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
|
||||||
n, _, err := conn.WriteMsgUDP(b, session.context, session.raddr)
|
n, _, err := conn.WriteMsgUDP(b, session.context, session.raddr)
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
10
vendor/github.com/miekg/dns/udp_linux.go
generated
vendored
10
vendor/github.com/miekg/dns/udp_linux.go
generated
vendored
@ -24,6 +24,12 @@ func setUDPSocketOptions4(conn *net.UDPConn) error {
|
|||||||
if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IP, syscall.IP_PKTINFO, 1); err != nil {
|
if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IP, syscall.IP_PKTINFO, 1); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// Calling File() above results in the connection becoming blocking, we must fix that.
|
||||||
|
// See https://github.com/miekg/dns/issues/279
|
||||||
|
err = syscall.SetNonblock(int(file.Fd()), true)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,6 +42,10 @@ func setUDPSocketOptions6(conn *net.UDPConn) error {
|
|||||||
if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_RECVPKTINFO, 1); err != nil {
|
if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_RECVPKTINFO, 1); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
err = syscall.SetNonblock(int(file.Fd()), true)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
vendor/github.com/miekg/dns/udp_other.go
generated
vendored
2
vendor/github.com/miekg/dns/udp_other.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// +build !linux
|
// +build !linux,!plan9
|
||||||
|
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
|
34
vendor/github.com/miekg/dns/udp_plan9.go
generated
vendored
Normal file
34
vendor/github.com/miekg/dns/udp_plan9.go
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package dns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
func setUDPSocketOptions(conn *net.UDPConn) error { return nil }
|
||||||
|
|
||||||
|
// SessionUDP holds the remote address and the associated
|
||||||
|
// out-of-band data.
|
||||||
|
type SessionUDP struct {
|
||||||
|
raddr *net.UDPAddr
|
||||||
|
context []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoteAddr returns the remote network address.
|
||||||
|
func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
|
||||||
|
|
||||||
|
// ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
|
||||||
|
// net.UDPAddr.
|
||||||
|
func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
|
||||||
|
oob := make([]byte, 40)
|
||||||
|
n, oobn, _, raddr, err := conn.ReadMsgUDP(b, oob)
|
||||||
|
if err != nil {
|
||||||
|
return n, nil, err
|
||||||
|
}
|
||||||
|
return n, &SessionUDP{raddr, oob[:oobn]}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteToSessionUDP acts just like net.UDPConn.WritetTo(), but uses a *SessionUDP instead of a net.Addr.
|
||||||
|
func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
|
||||||
|
n, _, err := conn.WriteMsgUDP(b, session.context, session.raddr)
|
||||||
|
return n, err
|
||||||
|
}
|
14
vendor/github.com/miekg/dns/udp_windows.go
generated
vendored
14
vendor/github.com/miekg/dns/udp_windows.go
generated
vendored
@ -4,28 +4,28 @@ package dns
|
|||||||
|
|
||||||
import "net"
|
import "net"
|
||||||
|
|
||||||
type sessionUDP struct {
|
type SessionUDP struct {
|
||||||
raddr *net.UDPAddr
|
raddr *net.UDPAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
// readFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
|
// ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
|
||||||
// net.UDPAddr.
|
// net.UDPAddr.
|
||||||
func readFromSessionUDP(conn *net.UDPConn, b []byte) (int, *sessionUDP, error) {
|
func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
|
||||||
n, raddr, err := conn.ReadFrom(b)
|
n, raddr, err := conn.ReadFrom(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return n, nil, err
|
return n, nil, err
|
||||||
}
|
}
|
||||||
session := &sessionUDP{raddr.(*net.UDPAddr)}
|
session := &SessionUDP{raddr.(*net.UDPAddr)}
|
||||||
return n, session, err
|
return n, session, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeToSessionUDP acts just like net.UDPConn.WritetTo(), but uses a *sessionUDP instead of a net.Addr.
|
// WriteToSessionUDP acts just like net.UDPConn.WritetTo(), but uses a *SessionUDP instead of a net.Addr.
|
||||||
func writeToSessionUDP(conn *net.UDPConn, b []byte, session *sessionUDP) (int, error) {
|
func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
|
||||||
n, err := conn.WriteTo(b, session.raddr)
|
n, err := conn.WriteTo(b, session.raddr)
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sessionUDP) RemoteAddr() net.Addr { return s.raddr }
|
func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
|
||||||
|
|
||||||
// setUDPSocketOptions sets the UDP socket options.
|
// setUDPSocketOptions sets the UDP socket options.
|
||||||
// This function is implemented on a per platform basis. See udp_*.go for more details
|
// This function is implemented on a per platform basis. See udp_*.go for more details
|
||||||
|
130
vendor/github.com/miekg/dns/update.go
generated
vendored
130
vendor/github.com/miekg/dns/update.go
generated
vendored
@ -1,55 +1,24 @@
|
|||||||
// DYNAMIC UPDATES
|
|
||||||
//
|
|
||||||
// Dynamic updates reuses the DNS message format, but renames three of
|
|
||||||
// the sections. Question is Zone, Answer is Prerequisite, Authority is
|
|
||||||
// Update, only the Additional is not renamed. See RFC 2136 for the gory details.
|
|
||||||
//
|
|
||||||
// You can set a rather complex set of rules for the existence of absence of
|
|
||||||
// certain resource records or names in a zone to specify if resource records
|
|
||||||
// should be added or removed. The table from RFC 2136 supplemented with the Go
|
|
||||||
// DNS function shows which functions exist to specify the prerequisites.
|
|
||||||
//
|
|
||||||
// 3.2.4 - Table Of Metavalues Used In Prerequisite Section
|
|
||||||
//
|
|
||||||
// CLASS TYPE RDATA Meaning Function
|
|
||||||
// --------------------------------------------------------------
|
|
||||||
// ANY ANY empty Name is in use dns.NameUsed
|
|
||||||
// ANY rrset empty RRset exists (value indep) dns.RRsetUsed
|
|
||||||
// NONE ANY empty Name is not in use dns.NameNotUsed
|
|
||||||
// NONE rrset empty RRset does not exist dns.RRsetNotUsed
|
|
||||||
// zone rrset rr RRset exists (value dep) dns.Used
|
|
||||||
//
|
|
||||||
// The prerequisite section can also be left empty.
|
|
||||||
// If you have decided on the prerequisites you can tell what RRs should
|
|
||||||
// be added or deleted. The next table shows the options you have and
|
|
||||||
// what functions to call.
|
|
||||||
//
|
|
||||||
// 3.4.2.6 - Table Of Metavalues Used In Update Section
|
|
||||||
//
|
|
||||||
// CLASS TYPE RDATA Meaning Function
|
|
||||||
// ---------------------------------------------------------------
|
|
||||||
// ANY ANY empty Delete all RRsets from name dns.RemoveName
|
|
||||||
// ANY rrset empty Delete an RRset dns.RemoveRRset
|
|
||||||
// NONE rrset rr Delete an RR from RRset dns.Remove
|
|
||||||
// zone rrset rr Add to an RRset dns.Insert
|
|
||||||
//
|
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
// NameUsed sets the RRs in the prereq section to
|
// NameUsed sets the RRs in the prereq section to
|
||||||
// "Name is in use" RRs. RFC 2136 section 2.4.4.
|
// "Name is in use" RRs. RFC 2136 section 2.4.4.
|
||||||
func (u *Msg) NameUsed(rr []RR) {
|
func (u *Msg) NameUsed(rr []RR) {
|
||||||
u.Answer = make([]RR, len(rr))
|
if u.Answer == nil {
|
||||||
for i, r := range rr {
|
u.Answer = make([]RR, 0, len(rr))
|
||||||
u.Answer[i] = &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassANY}}
|
}
|
||||||
|
for _, r := range rr {
|
||||||
|
u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassANY}})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NameNotUsed sets the RRs in the prereq section to
|
// NameNotUsed sets the RRs in the prereq section to
|
||||||
// "Name is in not use" RRs. RFC 2136 section 2.4.5.
|
// "Name is in not use" RRs. RFC 2136 section 2.4.5.
|
||||||
func (u *Msg) NameNotUsed(rr []RR) {
|
func (u *Msg) NameNotUsed(rr []RR) {
|
||||||
u.Answer = make([]RR, len(rr))
|
if u.Answer == nil {
|
||||||
for i, r := range rr {
|
u.Answer = make([]RR, 0, len(rr))
|
||||||
u.Answer[i] = &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassNONE}}
|
}
|
||||||
|
for _, r := range rr {
|
||||||
|
u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassNONE}})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,34 +28,34 @@ func (u *Msg) Used(rr []RR) {
|
|||||||
if len(u.Question) == 0 {
|
if len(u.Question) == 0 {
|
||||||
panic("dns: empty question section")
|
panic("dns: empty question section")
|
||||||
}
|
}
|
||||||
u.Answer = make([]RR, len(rr))
|
if u.Answer == nil {
|
||||||
for i, r := range rr {
|
u.Answer = make([]RR, 0, len(rr))
|
||||||
u.Answer[i] = r
|
}
|
||||||
u.Answer[i].Header().Class = u.Question[0].Qclass
|
for _, r := range rr {
|
||||||
|
r.Header().Class = u.Question[0].Qclass
|
||||||
|
u.Answer = append(u.Answer, r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RRsetUsed sets the RRs in the prereq section to
|
// RRsetUsed sets the RRs in the prereq section to
|
||||||
// "RRset exists (value independent -- no rdata)" RRs. RFC 2136 section 2.4.1.
|
// "RRset exists (value independent -- no rdata)" RRs. RFC 2136 section 2.4.1.
|
||||||
func (u *Msg) RRsetUsed(rr []RR) {
|
func (u *Msg) RRsetUsed(rr []RR) {
|
||||||
u.Answer = make([]RR, len(rr))
|
if u.Answer == nil {
|
||||||
for i, r := range rr {
|
u.Answer = make([]RR, 0, len(rr))
|
||||||
u.Answer[i] = r
|
}
|
||||||
u.Answer[i].Header().Class = ClassANY
|
for _, r := range rr {
|
||||||
u.Answer[i].Header().Ttl = 0
|
u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: r.Header().Rrtype, Class: ClassANY}})
|
||||||
u.Answer[i].Header().Rdlength = 0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RRsetNotUsed sets the RRs in the prereq section to
|
// RRsetNotUsed sets the RRs in the prereq section to
|
||||||
// "RRset does not exist" RRs. RFC 2136 section 2.4.3.
|
// "RRset does not exist" RRs. RFC 2136 section 2.4.3.
|
||||||
func (u *Msg) RRsetNotUsed(rr []RR) {
|
func (u *Msg) RRsetNotUsed(rr []RR) {
|
||||||
u.Answer = make([]RR, len(rr))
|
if u.Answer == nil {
|
||||||
for i, r := range rr {
|
u.Answer = make([]RR, 0, len(rr))
|
||||||
u.Answer[i] = r
|
}
|
||||||
u.Answer[i].Header().Class = ClassNONE
|
for _, r := range rr {
|
||||||
u.Answer[i].Header().Rdlength = 0
|
u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: r.Header().Rrtype, Class: ClassNONE}})
|
||||||
u.Answer[i].Header().Ttl = 0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,44 +64,43 @@ func (u *Msg) Insert(rr []RR) {
|
|||||||
if len(u.Question) == 0 {
|
if len(u.Question) == 0 {
|
||||||
panic("dns: empty question section")
|
panic("dns: empty question section")
|
||||||
}
|
}
|
||||||
u.Ns = make([]RR, len(rr))
|
if u.Ns == nil {
|
||||||
for i, r := range rr {
|
u.Ns = make([]RR, 0, len(rr))
|
||||||
u.Ns[i] = r
|
}
|
||||||
u.Ns[i].Header().Class = u.Question[0].Qclass
|
for _, r := range rr {
|
||||||
|
r.Header().Class = u.Question[0].Qclass
|
||||||
|
u.Ns = append(u.Ns, r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveRRset creates a dynamic update packet that deletes an RRset, see RFC 2136 section 2.5.2.
|
// RemoveRRset creates a dynamic update packet that deletes an RRset, see RFC 2136 section 2.5.2.
|
||||||
func (u *Msg) RemoveRRset(rr []RR) {
|
func (u *Msg) RemoveRRset(rr []RR) {
|
||||||
m := make(map[RR_Header]struct{})
|
if u.Ns == nil {
|
||||||
u.Ns = make([]RR, 0, len(rr))
|
u.Ns = make([]RR, 0, len(rr))
|
||||||
|
}
|
||||||
for _, r := range rr {
|
for _, r := range rr {
|
||||||
h := *r.Header().copyHeader()
|
u.Ns = append(u.Ns, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: r.Header().Rrtype, Class: ClassANY}})
|
||||||
h.Class = ClassANY
|
|
||||||
h.Ttl = 0
|
|
||||||
h.Rdlength = 0
|
|
||||||
if _, ok := m[h]; ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
m[h] = struct{}{}
|
|
||||||
u.Ns = append(u.Ns, &ANY{h})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveName creates a dynamic update packet that deletes all RRsets of a name, see RFC 2136 section 2.5.3
|
// RemoveName creates a dynamic update packet that deletes all RRsets of a name, see RFC 2136 section 2.5.3
|
||||||
func (u *Msg) RemoveName(rr []RR) {
|
func (u *Msg) RemoveName(rr []RR) {
|
||||||
u.Ns = make([]RR, len(rr))
|
if u.Ns == nil {
|
||||||
for i, r := range rr {
|
u.Ns = make([]RR, 0, len(rr))
|
||||||
u.Ns[i] = &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassANY}}
|
}
|
||||||
|
for _, r := range rr {
|
||||||
|
u.Ns = append(u.Ns, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassANY}})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove creates a dynamic update packet deletes RR from the RRSset, see RFC 2136 section 2.5.4
|
// Remove creates a dynamic update packet deletes RR from a RRSset, see RFC 2136 section 2.5.4
|
||||||
func (u *Msg) Remove(rr []RR) {
|
func (u *Msg) Remove(rr []RR) {
|
||||||
u.Ns = make([]RR, len(rr))
|
if u.Ns == nil {
|
||||||
for i, r := range rr {
|
u.Ns = make([]RR, 0, len(rr))
|
||||||
u.Ns[i] = r
|
}
|
||||||
u.Ns[i].Header().Class = ClassNONE
|
for _, r := range rr {
|
||||||
u.Ns[i].Header().Ttl = 0
|
r.Header().Class = ClassNONE
|
||||||
|
r.Header().Ttl = 0
|
||||||
|
u.Ns = append(u.Ns, r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
54
vendor/github.com/miekg/dns/xfr.go
generated
vendored
54
vendor/github.com/miekg/dns/xfr.go
generated
vendored
@ -13,9 +13,9 @@ type Envelope struct {
|
|||||||
// A Transfer defines parameters that are used during a zone transfer.
|
// A Transfer defines parameters that are used during a zone transfer.
|
||||||
type Transfer struct {
|
type Transfer struct {
|
||||||
*Conn
|
*Conn
|
||||||
DialTimeout time.Duration // net.DialTimeout (ns), defaults to 2 * 1e9
|
DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds
|
||||||
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections (ns), defaults to 2 * 1e9
|
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds
|
||||||
WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections (ns), defaults to 2 * 1e9
|
WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds
|
||||||
TsigSecret map[string]string // Secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified
|
TsigSecret map[string]string // Secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified
|
||||||
tsigTimersOnly bool
|
tsigTimersOnly bool
|
||||||
}
|
}
|
||||||
@ -23,14 +23,26 @@ type Transfer struct {
|
|||||||
// Think we need to away to stop the transfer
|
// Think we need to away to stop the transfer
|
||||||
|
|
||||||
// In performs an incoming transfer with the server in a.
|
// In performs an incoming transfer with the server in a.
|
||||||
|
// If you would like to set the source IP, or some other attribute
|
||||||
|
// of a Dialer for a Transfer, you can do so by specifying the attributes
|
||||||
|
// in the Transfer.Conn:
|
||||||
|
//
|
||||||
|
// d := net.Dialer{LocalAddr: transfer_source}
|
||||||
|
// con, err := d.Dial("tcp", master)
|
||||||
|
// dnscon := &dns.Conn{Conn:con}
|
||||||
|
// transfer = &dns.Transfer{Conn: dnscon}
|
||||||
|
// channel, err := transfer.In(message, master)
|
||||||
|
//
|
||||||
func (t *Transfer) In(q *Msg, a string) (env chan *Envelope, err error) {
|
func (t *Transfer) In(q *Msg, a string) (env chan *Envelope, err error) {
|
||||||
timeout := dnsTimeout
|
timeout := dnsTimeout
|
||||||
if t.DialTimeout != 0 {
|
if t.DialTimeout != 0 {
|
||||||
timeout = t.DialTimeout
|
timeout = t.DialTimeout
|
||||||
}
|
}
|
||||||
t.Conn, err = DialTimeout("tcp", a, timeout)
|
if t.Conn == nil {
|
||||||
if err != nil {
|
t.Conn, err = DialTimeout("tcp", a, timeout)
|
||||||
return nil, err
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if err := t.WriteMsg(q); err != nil {
|
if err := t.WriteMsg(q); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -91,7 +103,6 @@ func (t *Transfer) inAxfr(id uint16, c chan *Envelope) {
|
|||||||
c <- &Envelope{in.Answer, nil}
|
c <- &Envelope{in.Answer, nil}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panic("dns: not reached")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transfer) inIxfr(id uint16, c chan *Envelope) {
|
func (t *Transfer) inIxfr(id uint16, c chan *Envelope) {
|
||||||
@ -107,7 +118,7 @@ func (t *Transfer) inIxfr(id uint16, c chan *Envelope) {
|
|||||||
t.SetReadDeadline(time.Now().Add(timeout))
|
t.SetReadDeadline(time.Now().Add(timeout))
|
||||||
in, err := t.ReadMsg()
|
in, err := t.ReadMsg()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c <- &Envelope{in.Answer, err}
|
c <- &Envelope{nil, err}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if id != in.Id {
|
if id != in.Id {
|
||||||
@ -160,22 +171,18 @@ func (t *Transfer) inIxfr(id uint16, c chan *Envelope) {
|
|||||||
// 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 {
|
||||||
r := new(Msg)
|
for x := range ch {
|
||||||
// Compress?
|
r := new(Msg)
|
||||||
r.SetReply(q)
|
// Compress?
|
||||||
r.Authoritative = true
|
r.SetReply(q)
|
||||||
|
r.Authoritative = true
|
||||||
go func() {
|
// assume it fits TODO(miek): fix
|
||||||
for x := range ch {
|
r.Answer = append(r.Answer, x.RR...)
|
||||||
// assume it fits TODO(miek): fix
|
if err := w.WriteMsg(r); err != nil {
|
||||||
r.Answer = append(r.Answer, x.RR...)
|
return err
|
||||||
if err := w.WriteMsg(r); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
w.TsigTimersOnly(true)
|
}
|
||||||
r.Answer = nil
|
w.TsigTimersOnly(true)
|
||||||
}()
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,6 +204,7 @@ func (t *Transfer) ReadMsg() (*Msg, error) {
|
|||||||
}
|
}
|
||||||
// Need to work on the original message p, as that was used to calculate the tsig.
|
// Need to work on the original message p, as that was used to calculate the tsig.
|
||||||
err = TsigVerify(p, t.TsigSecret[ts.Hdr.Name], t.tsigRequestMAC, t.tsigTimersOnly)
|
err = TsigVerify(p, t.TsigSecret[ts.Hdr.Name], t.tsigRequestMAC, t.tsigTimersOnly)
|
||||||
|
t.tsigRequestMAC = ts.MAC
|
||||||
}
|
}
|
||||||
return m, err
|
return m, err
|
||||||
}
|
}
|
||||||
|
33
vendor/github.com/miekg/dns/zgenerate.go
generated
vendored
33
vendor/github.com/miekg/dns/zgenerate.go
generated
vendored
@ -1,6 +1,7 @@
|
|||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -14,7 +15,7 @@ import (
|
|||||||
// * [[ttl][class]]
|
// * [[ttl][class]]
|
||||||
// * type
|
// * type
|
||||||
// * rhs (rdata)
|
// * rhs (rdata)
|
||||||
// But we are lazy here, only the range is parsed *all* occurences
|
// But we are lazy here, only the range is parsed *all* occurrences
|
||||||
// of $ after that are interpreted.
|
// of $ after that are interpreted.
|
||||||
// Any error are returned as a string value, the empty string signals
|
// Any error are returned as a string value, the empty string signals
|
||||||
// "no error".
|
// "no error".
|
||||||
@ -24,13 +25,13 @@ func generate(l lex, c chan lex, t chan *Token, o string) string {
|
|||||||
if i+1 == len(l.token) {
|
if i+1 == len(l.token) {
|
||||||
return "bad step in $GENERATE range"
|
return "bad step in $GENERATE range"
|
||||||
}
|
}
|
||||||
if s, e := strconv.Atoi(l.token[i+1:]); e != nil {
|
if s, e := strconv.Atoi(l.token[i+1:]); e == nil {
|
||||||
return "bad step in $GENERATE range"
|
|
||||||
} else {
|
|
||||||
if s < 0 {
|
if s < 0 {
|
||||||
return "bad step in $GENERATE range"
|
return "bad step in $GENERATE range"
|
||||||
}
|
}
|
||||||
step = s
|
step = s
|
||||||
|
} else {
|
||||||
|
return "bad step in $GENERATE range"
|
||||||
}
|
}
|
||||||
l.token = l.token[:i]
|
l.token = l.token[:i]
|
||||||
}
|
}
|
||||||
@ -46,7 +47,7 @@ func generate(l lex, c chan lex, t chan *Token, o string) string {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "bad stop in $GENERATE range"
|
return "bad stop in $GENERATE range"
|
||||||
}
|
}
|
||||||
if end < 0 || start < 0 || end <= start {
|
if end < 0 || start < 0 || end < start {
|
||||||
return "bad range in $GENERATE range"
|
return "bad range in $GENERATE range"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,14 +56,14 @@ func generate(l lex, c chan lex, t chan *Token, o string) string {
|
|||||||
s := ""
|
s := ""
|
||||||
BuildRR:
|
BuildRR:
|
||||||
l = <-c
|
l = <-c
|
||||||
if l.value != _NEWLINE && l.value != _EOF {
|
if l.value != zNewline && l.value != zEOF {
|
||||||
s += l.token
|
s += l.token
|
||||||
goto BuildRR
|
goto BuildRR
|
||||||
}
|
}
|
||||||
for i := start; i <= end; i += step {
|
for i := start; i <= end; i += step {
|
||||||
var (
|
var (
|
||||||
escape bool
|
escape bool
|
||||||
dom string
|
dom bytes.Buffer
|
||||||
mod string
|
mod string
|
||||||
err string
|
err string
|
||||||
offset int
|
offset int
|
||||||
@ -72,7 +73,7 @@ BuildRR:
|
|||||||
switch s[j] {
|
switch s[j] {
|
||||||
case '\\':
|
case '\\':
|
||||||
if escape {
|
if escape {
|
||||||
dom += "\\"
|
dom.WriteByte('\\')
|
||||||
escape = false
|
escape = false
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -81,17 +82,17 @@ BuildRR:
|
|||||||
mod = "%d"
|
mod = "%d"
|
||||||
offset = 0
|
offset = 0
|
||||||
if escape {
|
if escape {
|
||||||
dom += "$"
|
dom.WriteByte('$')
|
||||||
escape = false
|
escape = false
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
escape = false
|
escape = false
|
||||||
if j+1 >= len(s) { // End of the string
|
if j+1 >= len(s) { // End of the string
|
||||||
dom += fmt.Sprintf(mod, i+offset)
|
dom.WriteString(fmt.Sprintf(mod, i+offset))
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
if s[j+1] == '$' {
|
if s[j+1] == '$' {
|
||||||
dom += "$"
|
dom.WriteByte('$')
|
||||||
j++
|
j++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -108,17 +109,17 @@ BuildRR:
|
|||||||
}
|
}
|
||||||
j += 2 + sep // Jump to it
|
j += 2 + sep // Jump to it
|
||||||
}
|
}
|
||||||
dom += fmt.Sprintf(mod, i+offset)
|
dom.WriteString(fmt.Sprintf(mod, i+offset))
|
||||||
default:
|
default:
|
||||||
if escape { // Pretty useless here
|
if escape { // Pretty useless here
|
||||||
escape = false
|
escape = false
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
dom += string(s[j])
|
dom.WriteByte(s[j])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Re-parse the RR and send it on the current channel t
|
// Re-parse the RR and send it on the current channel t
|
||||||
rx, e := NewRR("$ORIGIN " + o + "\n" + dom)
|
rx, e := NewRR("$ORIGIN " + o + "\n" + dom.String())
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return e.(*ParseError).err
|
return e.(*ParseError).err
|
||||||
}
|
}
|
||||||
@ -140,11 +141,11 @@ func modToPrintf(s string) (string, int, string) {
|
|||||||
return "", 0, "bad base in $GENERATE"
|
return "", 0, "bad base in $GENERATE"
|
||||||
}
|
}
|
||||||
offset, err := strconv.Atoi(xs[0])
|
offset, err := strconv.Atoi(xs[0])
|
||||||
if err != nil {
|
if err != nil || offset > 255 {
|
||||||
return "", 0, "bad offset in $GENERATE"
|
return "", 0, "bad offset in $GENERATE"
|
||||||
}
|
}
|
||||||
width, err := strconv.Atoi(xs[1])
|
width, err := strconv.Atoi(xs[1])
|
||||||
if err != nil {
|
if err != nil || width > 255 {
|
||||||
return "", offset, "bad width in $GENERATE"
|
return "", offset, "bad width in $GENERATE"
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
|
398
vendor/github.com/miekg/dns/zscan.go
generated
vendored
398
vendor/github.com/miekg/dns/zscan.go
generated
vendored
@ -29,45 +29,45 @@ const maxUint16 = 1<<16 - 1
|
|||||||
// * Handle braces - anywhere.
|
// * Handle braces - anywhere.
|
||||||
const (
|
const (
|
||||||
// Zonefile
|
// Zonefile
|
||||||
_EOF = iota
|
zEOF = iota
|
||||||
_STRING
|
zString
|
||||||
_BLANK
|
zBlank
|
||||||
_QUOTE
|
zQuote
|
||||||
_NEWLINE
|
zNewline
|
||||||
_RRTYPE
|
zRrtpe
|
||||||
_OWNER
|
zOwner
|
||||||
_CLASS
|
zClass
|
||||||
_DIRORIGIN // $ORIGIN
|
zDirOrigin // $ORIGIN
|
||||||
_DIRTTL // $TTL
|
zDirTtl // $TTL
|
||||||
_DIRINCLUDE // $INCLUDE
|
zDirInclude // $INCLUDE
|
||||||
_DIRGENERATE // $GENERATE
|
zDirGenerate // $GENERATE
|
||||||
|
|
||||||
// Privatekey file
|
// Privatekey file
|
||||||
_VALUE
|
zValue
|
||||||
_KEY
|
zKey
|
||||||
|
|
||||||
_EXPECT_OWNER_DIR // Ownername
|
zExpectOwnerDir // Ownername
|
||||||
_EXPECT_OWNER_BL // Whitespace after the ownername
|
zExpectOwnerBl // Whitespace after the ownername
|
||||||
_EXPECT_ANY // Expect rrtype, ttl or class
|
zExpectAny // Expect rrtype, ttl or class
|
||||||
_EXPECT_ANY_NOCLASS // Expect rrtype or ttl
|
zExpectAnyNoClass // Expect rrtype or ttl
|
||||||
_EXPECT_ANY_NOCLASS_BL // The whitespace after _EXPECT_ANY_NOCLASS
|
zExpectAnyNoClassBl // The whitespace after _EXPECT_ANY_NOCLASS
|
||||||
_EXPECT_ANY_NOTTL // Expect rrtype or class
|
zExpectAnyNoTtl // Expect rrtype or class
|
||||||
_EXPECT_ANY_NOTTL_BL // Whitespace after _EXPECT_ANY_NOTTL
|
zExpectAnyNoTtlBl // Whitespace after _EXPECT_ANY_NOTTL
|
||||||
_EXPECT_RRTYPE // Expect rrtype
|
zExpectRrtype // Expect rrtype
|
||||||
_EXPECT_RRTYPE_BL // Whitespace BEFORE rrtype
|
zExpectRrtypeBl // Whitespace BEFORE rrtype
|
||||||
_EXPECT_RDATA // The first element of the rdata
|
zExpectRdata // The first element of the rdata
|
||||||
_EXPECT_DIRTTL_BL // Space after directive $TTL
|
zExpectDirTtlBl // Space after directive $TTL
|
||||||
_EXPECT_DIRTTL // Directive $TTL
|
zExpectDirTtl // Directive $TTL
|
||||||
_EXPECT_DIRORIGIN_BL // Space after directive $ORIGIN
|
zExpectDirOriginBl // Space after directive $ORIGIN
|
||||||
_EXPECT_DIRORIGIN // Directive $ORIGIN
|
zExpectDirOrigin // Directive $ORIGIN
|
||||||
_EXPECT_DIRINCLUDE_BL // Space after directive $INCLUDE
|
zExpectDirIncludeBl // Space after directive $INCLUDE
|
||||||
_EXPECT_DIRINCLUDE // Directive $INCLUDE
|
zExpectDirInclude // Directive $INCLUDE
|
||||||
_EXPECT_DIRGENERATE // Directive $GENERATE
|
zExpectDirGenerate // Directive $GENERATE
|
||||||
_EXPECT_DIRGENERATE_BL // Space after directive $GENERATE
|
zExpectDirGenerateBl // Space after directive $GENERATE
|
||||||
)
|
)
|
||||||
|
|
||||||
// ParseError is a parsing error. It contains the parse error and the location in the io.Reader
|
// ParseError is a parsing error. It contains the parse error and the location in the io.Reader
|
||||||
// where the error occured.
|
// where the error occurred.
|
||||||
type ParseError struct {
|
type ParseError struct {
|
||||||
file string
|
file string
|
||||||
err string
|
err string
|
||||||
@ -86,28 +86,32 @@ func (e *ParseError) Error() (s string) {
|
|||||||
type lex struct {
|
type lex struct {
|
||||||
token string // text of the token
|
token string // text of the token
|
||||||
tokenUpper string // uppercase text of the token
|
tokenUpper string // uppercase text of the token
|
||||||
length int // lenght of the token
|
length int // length of the token
|
||||||
err bool // when true, token text has lexer error
|
err bool // when true, token text has lexer error
|
||||||
value uint8 // value: _STRING, _BLANK, etc.
|
value uint8 // value: zString, _BLANK, etc.
|
||||||
line int // line in the file
|
line int // line in the file
|
||||||
column int // column in the file
|
column int // column in the file
|
||||||
torc uint16 // type or class as parsed in the lexer, we only need to look this up in the grammar
|
torc uint16 // type or class as parsed in the lexer, we only need to look this up in the grammar
|
||||||
comment string // any comment text seen
|
comment string // any comment text seen
|
||||||
}
|
}
|
||||||
|
|
||||||
// *Tokens are returned when a zone file is parsed.
|
// Token holds the token that are returned when a zone file is parsed.
|
||||||
type Token struct {
|
type Token struct {
|
||||||
RR // the scanned resource record when error is not nil
|
// The scanned resource record when error is not nil.
|
||||||
Error *ParseError // when an error occured, this has the error specifics
|
RR
|
||||||
Comment string // a potential comment positioned after the RR and on the same line
|
// 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
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRR reads the RR contained in the string s. Only the first RR is returned.
|
// NewRR reads the RR contained in the string s. Only the first RR is
|
||||||
// The class defaults to IN and TTL defaults to 3600. The full zone file
|
// returned. If s contains no RR, return nil with no error. The class
|
||||||
// syntax like $TTL, $ORIGIN, etc. is supported.
|
// defaults to IN and TTL defaults to 3600. The full zone file syntax
|
||||||
// All fields of the returned RR are set, except RR.Header().Rdlength which is set to 0.
|
// like $TTL, $ORIGIN, etc. is supported. All fields of the returned
|
||||||
|
// RR are set, except RR.Header().Rdlength which is set to 0.
|
||||||
func NewRR(s string) (RR, error) {
|
func NewRR(s string) (RR, error) {
|
||||||
if 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"), "")
|
||||||
}
|
}
|
||||||
return ReadRR(strings.NewReader(s), "")
|
return ReadRR(strings.NewReader(s), "")
|
||||||
@ -117,17 +121,21 @@ func NewRR(s string) (RR, error) {
|
|||||||
// See NewRR for more documentation.
|
// See NewRR for more documentation.
|
||||||
func ReadRR(q io.Reader, filename string) (RR, error) {
|
func ReadRR(q io.Reader, filename string) (RR, error) {
|
||||||
r := <-parseZoneHelper(q, ".", filename, 1)
|
r := <-parseZoneHelper(q, ".", filename, 1)
|
||||||
|
if r == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
if r.Error != nil {
|
if r.Error != nil {
|
||||||
return nil, r.Error
|
return nil, r.Error
|
||||||
}
|
}
|
||||||
return r.RR, nil
|
return r.RR, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseZone reads a RFC 1035 style one from r. It returns *Tokens on the
|
// ParseZone reads a RFC 1035 style zonefile from r. It returns *Tokens on the
|
||||||
// returned channel, which consist out the parsed RR, a potential comment or an error.
|
// returned channel, which consist out the parsed RR, a potential comment or an error.
|
||||||
// If there is an error the RR is nil. The string file is only used
|
// If there is an error the RR is nil. The string file is only used
|
||||||
// in error reporting. The string origin is used as the initial origin, as
|
// in error reporting. The string origin is used as the initial origin, as
|
||||||
// if the file would start with: $ORIGIN origin .
|
// if the file would start with: $ORIGIN origin .
|
||||||
// The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are supported.
|
// The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are supported.
|
||||||
// The channel t is closed by ParseZone when the end of r is reached.
|
// The channel t is closed by ParseZone when the end of r is reached.
|
||||||
//
|
//
|
||||||
@ -136,15 +144,17 @@ func ReadRR(q io.Reader, filename string) (RR, error) {
|
|||||||
//
|
//
|
||||||
// for x := range dns.ParseZone(strings.NewReader(z), "", "") {
|
// for x := range dns.ParseZone(strings.NewReader(z), "", "") {
|
||||||
// if x.Error != nil {
|
// if x.Error != nil {
|
||||||
// // Do something with x.RR
|
// // log.Println(x.Error)
|
||||||
// }
|
// } else {
|
||||||
|
// // Do something with x.RR
|
||||||
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// Comments specified after an RR (and on the same line!) are returned too:
|
// Comments specified after an RR (and on the same line!) are returned too:
|
||||||
//
|
//
|
||||||
// foo. IN A 10.0.0.1 ; this is a comment
|
// foo. IN A 10.0.0.1 ; this is a comment
|
||||||
//
|
//
|
||||||
// The text "; this is comment" is returned in Token.Comment . Comments inside the
|
// The text "; this is comment" is returned in Token.Comment. Comments inside the
|
||||||
// RR are discarded. Comments on a line by themselves are discarded too.
|
// RR are discarded. Comments on a line by themselves are discarded too.
|
||||||
func ParseZone(r io.Reader, origin, file string) chan *Token {
|
func ParseZone(r io.Reader, origin, file string) chan *Token {
|
||||||
return parseZoneHelper(r, origin, file, 10000)
|
return parseZoneHelper(r, origin, file, 10000)
|
||||||
@ -163,17 +173,17 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
s := scanInit(r)
|
s := scanInit(r)
|
||||||
c := make(chan lex, 1000)
|
c := make(chan lex)
|
||||||
// Start the lexer
|
// Start the lexer
|
||||||
go zlexer(s, c)
|
go zlexer(s, c)
|
||||||
// 6 possible beginnings of a line, _ is a space
|
// 6 possible beginnings of a line, _ is a space
|
||||||
// 0. _RRTYPE -> all omitted until the rrtype
|
// 0. zRRTYPE -> all omitted until the rrtype
|
||||||
// 1. _OWNER _ _RRTYPE -> class/ttl omitted
|
// 1. zOwner _ zRrtype -> class/ttl omitted
|
||||||
// 2. _OWNER _ _STRING _ _RRTYPE -> class omitted
|
// 2. zOwner _ zString _ zRrtype -> class omitted
|
||||||
// 3. _OWNER _ _STRING _ _CLASS _ _RRTYPE -> ttl/class
|
// 3. zOwner _ zString _ zClass _ zRrtype -> ttl/class
|
||||||
// 4. _OWNER _ _CLASS _ _RRTYPE -> ttl omitted
|
// 4. zOwner _ zClass _ zRrtype -> ttl omitted
|
||||||
// 5. _OWNER _ _CLASS _ _STRING _ _RRTYPE -> class/ttl (reversed)
|
// 5. zOwner _ zClass _ zString _ zRrtype -> class/ttl (reversed)
|
||||||
// After detecting these, we know the _RRTYPE so we can jump to functions
|
// After detecting these, we know the zRrtype so we can jump to functions
|
||||||
// handling the rdata for each of these types.
|
// handling the rdata for each of these types.
|
||||||
|
|
||||||
if origin == "" {
|
if origin == "" {
|
||||||
@ -185,7 +195,7 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
st := _EXPECT_OWNER_DIR // initial state
|
st := zExpectOwnerDir // initial state
|
||||||
var h RR_Header
|
var h RR_Header
|
||||||
var defttl uint32 = defaultTtl
|
var defttl uint32 = defaultTtl
|
||||||
var prevName string
|
var prevName string
|
||||||
@ -197,19 +207,19 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
switch st {
|
switch st {
|
||||||
case _EXPECT_OWNER_DIR:
|
case zExpectOwnerDir:
|
||||||
// We can also expect a directive, like $TTL or $ORIGIN
|
// We can also expect a directive, like $TTL or $ORIGIN
|
||||||
h.Ttl = defttl
|
h.Ttl = defttl
|
||||||
h.Class = ClassINET
|
h.Class = ClassINET
|
||||||
switch l.value {
|
switch l.value {
|
||||||
case _NEWLINE: // Empty line
|
case zNewline:
|
||||||
st = _EXPECT_OWNER_DIR
|
st = zExpectOwnerDir
|
||||||
case _OWNER:
|
case zOwner:
|
||||||
h.Name = l.token
|
h.Name = l.token
|
||||||
if l.token[0] == '@' {
|
if l.token[0] == '@' {
|
||||||
h.Name = origin
|
h.Name = origin
|
||||||
prevName = h.Name
|
prevName = h.Name
|
||||||
st = _EXPECT_OWNER_BL
|
st = zExpectOwnerBl
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if h.Name[l.length-1] != '.' {
|
if h.Name[l.length-1] != '.' {
|
||||||
@ -221,59 +231,59 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
prevName = h.Name
|
prevName = h.Name
|
||||||
st = _EXPECT_OWNER_BL
|
st = zExpectOwnerBl
|
||||||
case _DIRTTL:
|
case zDirTtl:
|
||||||
st = _EXPECT_DIRTTL_BL
|
st = zExpectDirTtlBl
|
||||||
case _DIRORIGIN:
|
case zDirOrigin:
|
||||||
st = _EXPECT_DIRORIGIN_BL
|
st = zExpectDirOriginBl
|
||||||
case _DIRINCLUDE:
|
case zDirInclude:
|
||||||
st = _EXPECT_DIRINCLUDE_BL
|
st = zExpectDirIncludeBl
|
||||||
case _DIRGENERATE:
|
case zDirGenerate:
|
||||||
st = _EXPECT_DIRGENERATE_BL
|
st = zExpectDirGenerateBl
|
||||||
case _RRTYPE: // Everthing has been omitted, this is the first thing on the line
|
case zRrtpe:
|
||||||
h.Name = prevName
|
h.Name = prevName
|
||||||
h.Rrtype = l.torc
|
h.Rrtype = l.torc
|
||||||
st = _EXPECT_RDATA
|
st = zExpectRdata
|
||||||
case _CLASS: // First thing on the line is the class
|
case zClass:
|
||||||
h.Name = prevName
|
h.Name = prevName
|
||||||
h.Class = l.torc
|
h.Class = l.torc
|
||||||
st = _EXPECT_ANY_NOCLASS_BL
|
st = zExpectAnyNoClassBl
|
||||||
case _BLANK:
|
case zBlank:
|
||||||
// Discard, can happen when there is nothing on the
|
// Discard, can happen when there is nothing on the
|
||||||
// line except the RR type
|
// line except the RR type
|
||||||
case _STRING: // First thing on the is the ttl
|
case zString:
|
||||||
if ttl, ok := stringToTtl(l.token); !ok {
|
ttl, ok := stringToTtl(l.token)
|
||||||
|
if !ok {
|
||||||
t <- &Token{Error: &ParseError{f, "not a TTL", l}}
|
t <- &Token{Error: &ParseError{f, "not a TTL", l}}
|
||||||
return
|
return
|
||||||
} else {
|
|
||||||
h.Ttl = ttl
|
|
||||||
// Don't about the defttl, we should take the $TTL value
|
|
||||||
// defttl = ttl
|
|
||||||
}
|
}
|
||||||
st = _EXPECT_ANY_NOTTL_BL
|
h.Ttl = ttl
|
||||||
|
// Don't about the defttl, we should take the $TTL value
|
||||||
|
// defttl = ttl
|
||||||
|
st = zExpectAnyNoTtlBl
|
||||||
|
|
||||||
default:
|
default:
|
||||||
t <- &Token{Error: &ParseError{f, "syntax error at beginning", l}}
|
t <- &Token{Error: &ParseError{f, "syntax error at beginning", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case _EXPECT_DIRINCLUDE_BL:
|
case zExpectDirIncludeBl:
|
||||||
if l.value != _BLANK {
|
if l.value != zBlank {
|
||||||
t <- &Token{Error: &ParseError{f, "no blank after $INCLUDE-directive", l}}
|
t <- &Token{Error: &ParseError{f, "no blank after $INCLUDE-directive", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
st = _EXPECT_DIRINCLUDE
|
st = zExpectDirInclude
|
||||||
case _EXPECT_DIRINCLUDE:
|
case zExpectDirInclude:
|
||||||
if l.value != _STRING {
|
if l.value != zString {
|
||||||
t <- &Token{Error: &ParseError{f, "expecting $INCLUDE value, not this...", l}}
|
t <- &Token{Error: &ParseError{f, "expecting $INCLUDE value, not this...", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
neworigin := origin // There may be optionally a new origin set after the filename, if not use current one
|
neworigin := origin // There may be optionally a new origin set after the filename, if not use current one
|
||||||
l := <-c
|
l := <-c
|
||||||
switch l.value {
|
switch l.value {
|
||||||
case _BLANK:
|
case zBlank:
|
||||||
l := <-c
|
l := <-c
|
||||||
if l.value == _STRING {
|
if l.value == zString {
|
||||||
if _, ok := IsDomainName(l.token); !ok {
|
if _, ok := IsDomainName(l.token); !ok || l.length == 0 || l.err {
|
||||||
t <- &Token{Error: &ParseError{f, "bad origin name", l}}
|
t <- &Token{Error: &ParseError{f, "bad origin name", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -288,7 +298,7 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
|||||||
neworigin = l.token
|
neworigin = l.token
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case _NEWLINE, _EOF:
|
case zNewline, zEOF:
|
||||||
// Ok
|
// Ok
|
||||||
default:
|
default:
|
||||||
t <- &Token{Error: &ParseError{f, "garbage after $INCLUDE", l}}
|
t <- &Token{Error: &ParseError{f, "garbage after $INCLUDE", l}}
|
||||||
@ -305,15 +315,15 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
parseZone(r1, l.token, neworigin, t, include+1)
|
parseZone(r1, l.token, neworigin, t, include+1)
|
||||||
st = _EXPECT_OWNER_DIR
|
st = zExpectOwnerDir
|
||||||
case _EXPECT_DIRTTL_BL:
|
case zExpectDirTtlBl:
|
||||||
if l.value != _BLANK {
|
if l.value != zBlank {
|
||||||
t <- &Token{Error: &ParseError{f, "no blank after $TTL-directive", l}}
|
t <- &Token{Error: &ParseError{f, "no blank after $TTL-directive", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
st = _EXPECT_DIRTTL
|
st = zExpectDirTtl
|
||||||
case _EXPECT_DIRTTL:
|
case zExpectDirTtl:
|
||||||
if l.value != _STRING {
|
if l.value != zString {
|
||||||
t <- &Token{Error: &ParseError{f, "expecting $TTL value, not this...", l}}
|
t <- &Token{Error: &ParseError{f, "expecting $TTL value, not this...", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -321,21 +331,21 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
|||||||
t <- &Token{Error: e}
|
t <- &Token{Error: e}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if ttl, ok := stringToTtl(l.token); !ok {
|
ttl, ok := stringToTtl(l.token)
|
||||||
|
if !ok {
|
||||||
t <- &Token{Error: &ParseError{f, "expecting $TTL value, not this...", l}}
|
t <- &Token{Error: &ParseError{f, "expecting $TTL value, not this...", l}}
|
||||||
return
|
return
|
||||||
} else {
|
|
||||||
defttl = ttl
|
|
||||||
}
|
}
|
||||||
st = _EXPECT_OWNER_DIR
|
defttl = ttl
|
||||||
case _EXPECT_DIRORIGIN_BL:
|
st = zExpectOwnerDir
|
||||||
if l.value != _BLANK {
|
case zExpectDirOriginBl:
|
||||||
|
if l.value != zBlank {
|
||||||
t <- &Token{Error: &ParseError{f, "no blank after $ORIGIN-directive", l}}
|
t <- &Token{Error: &ParseError{f, "no blank after $ORIGIN-directive", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
st = _EXPECT_DIRORIGIN
|
st = zExpectDirOrigin
|
||||||
case _EXPECT_DIRORIGIN:
|
case zExpectDirOrigin:
|
||||||
if l.value != _STRING {
|
if l.value != zString {
|
||||||
t <- &Token{Error: &ParseError{f, "expecting $ORIGIN value, not this...", l}}
|
t <- &Token{Error: &ParseError{f, "expecting $ORIGIN value, not this...", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -355,15 +365,15 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
|||||||
} else {
|
} else {
|
||||||
origin = l.token
|
origin = l.token
|
||||||
}
|
}
|
||||||
st = _EXPECT_OWNER_DIR
|
st = zExpectOwnerDir
|
||||||
case _EXPECT_DIRGENERATE_BL:
|
case zExpectDirGenerateBl:
|
||||||
if l.value != _BLANK {
|
if l.value != zBlank {
|
||||||
t <- &Token{Error: &ParseError{f, "no blank after $GENERATE-directive", l}}
|
t <- &Token{Error: &ParseError{f, "no blank after $GENERATE-directive", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
st = _EXPECT_DIRGENERATE
|
st = zExpectDirGenerate
|
||||||
case _EXPECT_DIRGENERATE:
|
case zExpectDirGenerate:
|
||||||
if l.value != _STRING {
|
if l.value != zString {
|
||||||
t <- &Token{Error: &ParseError{f, "expecting $GENERATE value, not this...", l}}
|
t <- &Token{Error: &ParseError{f, "expecting $GENERATE value, not this...", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -371,90 +381,90 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
|||||||
t <- &Token{Error: &ParseError{f, e, l}}
|
t <- &Token{Error: &ParseError{f, e, l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
st = _EXPECT_OWNER_DIR
|
st = zExpectOwnerDir
|
||||||
case _EXPECT_OWNER_BL:
|
case zExpectOwnerBl:
|
||||||
if l.value != _BLANK {
|
if l.value != zBlank {
|
||||||
t <- &Token{Error: &ParseError{f, "no blank after owner", l}}
|
t <- &Token{Error: &ParseError{f, "no blank after owner", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
st = _EXPECT_ANY
|
st = zExpectAny
|
||||||
case _EXPECT_ANY:
|
case zExpectAny:
|
||||||
switch l.value {
|
switch l.value {
|
||||||
case _RRTYPE:
|
case zRrtpe:
|
||||||
h.Rrtype = l.torc
|
h.Rrtype = l.torc
|
||||||
st = _EXPECT_RDATA
|
st = zExpectRdata
|
||||||
case _CLASS:
|
case zClass:
|
||||||
h.Class = l.torc
|
h.Class = l.torc
|
||||||
st = _EXPECT_ANY_NOCLASS_BL
|
st = zExpectAnyNoClassBl
|
||||||
case _STRING: // TTL is this case
|
case zString:
|
||||||
if ttl, ok := stringToTtl(l.token); !ok {
|
ttl, ok := stringToTtl(l.token)
|
||||||
|
if !ok {
|
||||||
t <- &Token{Error: &ParseError{f, "not a TTL", l}}
|
t <- &Token{Error: &ParseError{f, "not a TTL", l}}
|
||||||
return
|
return
|
||||||
} else {
|
|
||||||
h.Ttl = ttl
|
|
||||||
// defttl = ttl // don't set the defttl here
|
|
||||||
}
|
}
|
||||||
st = _EXPECT_ANY_NOTTL_BL
|
h.Ttl = ttl
|
||||||
|
// defttl = ttl // don't set the defttl here
|
||||||
|
st = zExpectAnyNoTtlBl
|
||||||
default:
|
default:
|
||||||
t <- &Token{Error: &ParseError{f, "expecting RR type, TTL or class, not this...", l}}
|
t <- &Token{Error: &ParseError{f, "expecting RR type, TTL or class, not this...", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case _EXPECT_ANY_NOCLASS_BL:
|
case zExpectAnyNoClassBl:
|
||||||
if l.value != _BLANK {
|
if l.value != zBlank {
|
||||||
t <- &Token{Error: &ParseError{f, "no blank before class", l}}
|
t <- &Token{Error: &ParseError{f, "no blank before class", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
st = _EXPECT_ANY_NOCLASS
|
st = zExpectAnyNoClass
|
||||||
case _EXPECT_ANY_NOTTL_BL:
|
case zExpectAnyNoTtlBl:
|
||||||
if l.value != _BLANK {
|
if l.value != zBlank {
|
||||||
t <- &Token{Error: &ParseError{f, "no blank before TTL", l}}
|
t <- &Token{Error: &ParseError{f, "no blank before TTL", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
st = _EXPECT_ANY_NOTTL
|
st = zExpectAnyNoTtl
|
||||||
case _EXPECT_ANY_NOTTL:
|
case zExpectAnyNoTtl:
|
||||||
switch l.value {
|
switch l.value {
|
||||||
case _CLASS:
|
case zClass:
|
||||||
h.Class = l.torc
|
h.Class = l.torc
|
||||||
st = _EXPECT_RRTYPE_BL
|
st = zExpectRrtypeBl
|
||||||
case _RRTYPE:
|
case zRrtpe:
|
||||||
h.Rrtype = l.torc
|
h.Rrtype = l.torc
|
||||||
st = _EXPECT_RDATA
|
st = zExpectRdata
|
||||||
default:
|
default:
|
||||||
t <- &Token{Error: &ParseError{f, "expecting RR type or class, not this...", l}}
|
t <- &Token{Error: &ParseError{f, "expecting RR type or class, not this...", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case _EXPECT_ANY_NOCLASS:
|
case zExpectAnyNoClass:
|
||||||
switch l.value {
|
switch l.value {
|
||||||
case _STRING: // TTL
|
case zString:
|
||||||
if ttl, ok := stringToTtl(l.token); !ok {
|
ttl, ok := stringToTtl(l.token)
|
||||||
|
if !ok {
|
||||||
t <- &Token{Error: &ParseError{f, "not a TTL", l}}
|
t <- &Token{Error: &ParseError{f, "not a TTL", l}}
|
||||||
return
|
return
|
||||||
} else {
|
|
||||||
h.Ttl = ttl
|
|
||||||
// defttl = ttl // don't set the def ttl anymore
|
|
||||||
}
|
}
|
||||||
st = _EXPECT_RRTYPE_BL
|
h.Ttl = ttl
|
||||||
case _RRTYPE:
|
// defttl = ttl // don't set the def ttl anymore
|
||||||
|
st = zExpectRrtypeBl
|
||||||
|
case zRrtpe:
|
||||||
h.Rrtype = l.torc
|
h.Rrtype = l.torc
|
||||||
st = _EXPECT_RDATA
|
st = zExpectRdata
|
||||||
default:
|
default:
|
||||||
t <- &Token{Error: &ParseError{f, "expecting RR type or TTL, not this...", l}}
|
t <- &Token{Error: &ParseError{f, "expecting RR type or TTL, not this...", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case _EXPECT_RRTYPE_BL:
|
case zExpectRrtypeBl:
|
||||||
if l.value != _BLANK {
|
if l.value != zBlank {
|
||||||
t <- &Token{Error: &ParseError{f, "no blank before RR type", l}}
|
t <- &Token{Error: &ParseError{f, "no blank before RR type", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
st = _EXPECT_RRTYPE
|
st = zExpectRrtype
|
||||||
case _EXPECT_RRTYPE:
|
case zExpectRrtype:
|
||||||
if l.value != _RRTYPE {
|
if l.value != zRrtpe {
|
||||||
t <- &Token{Error: &ParseError{f, "unknown RR type", l}}
|
t <- &Token{Error: &ParseError{f, "unknown RR type", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
h.Rrtype = l.torc
|
h.Rrtype = l.torc
|
||||||
st = _EXPECT_RDATA
|
st = zExpectRdata
|
||||||
case _EXPECT_RDATA:
|
case zExpectRdata:
|
||||||
r, e, c1 := setRR(h, c, origin, f)
|
r, e, c1 := setRR(h, c, origin, f)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
// If e.lex is nil than we have encounter a unknown RR type
|
// If e.lex is nil than we have encounter a unknown RR type
|
||||||
@ -466,7 +476,7 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
t <- &Token{RR: r, Comment: c1}
|
t <- &Token{RR: r, Comment: c1}
|
||||||
st = _EXPECT_OWNER_DIR
|
st = zExpectOwnerDir
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If we get here, we and the h.Rrtype is still zero, we haven't parsed anything, this
|
// If we get here, we and the h.Rrtype is still zero, we haven't parsed anything, this
|
||||||
@ -492,14 +502,14 @@ func zlexer(s *scan, c chan lex) {
|
|||||||
for err == nil {
|
for err == nil {
|
||||||
l.column = s.position.Column
|
l.column = s.position.Column
|
||||||
l.line = s.position.Line
|
l.line = s.position.Line
|
||||||
if stri > maxTok {
|
if stri >= maxTok {
|
||||||
l.token = "token length insufficient for parsing"
|
l.token = "token length insufficient for parsing"
|
||||||
l.err = true
|
l.err = true
|
||||||
debug.Printf("[%+v]", l.token)
|
debug.Printf("[%+v]", l.token)
|
||||||
c <- l
|
c <- l
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if comi > maxTok {
|
if comi >= maxTok {
|
||||||
l.token = "comment length insufficient for parsing"
|
l.token = "comment length insufficient for parsing"
|
||||||
l.err = true
|
l.err = true
|
||||||
debug.Printf("[%+v]", l.token)
|
debug.Printf("[%+v]", l.token)
|
||||||
@ -530,60 +540,60 @@ func zlexer(s *scan, c chan lex) {
|
|||||||
// Space directly in the beginning, handled in the grammar
|
// Space directly in the beginning, handled in the grammar
|
||||||
} else if owner {
|
} else if owner {
|
||||||
// If we have a string and its the first, make it an owner
|
// If we have a string and its the first, make it an owner
|
||||||
l.value = _OWNER
|
l.value = zOwner
|
||||||
l.token = string(str[:stri])
|
l.token = string(str[:stri])
|
||||||
l.tokenUpper = strings.ToUpper(l.token)
|
l.tokenUpper = strings.ToUpper(l.token)
|
||||||
l.length = stri
|
l.length = stri
|
||||||
// escape $... start with a \ not a $, so this will work
|
// escape $... start with a \ not a $, so this will work
|
||||||
switch l.tokenUpper {
|
switch l.tokenUpper {
|
||||||
case "$TTL":
|
case "$TTL":
|
||||||
l.value = _DIRTTL
|
l.value = zDirTtl
|
||||||
case "$ORIGIN":
|
case "$ORIGIN":
|
||||||
l.value = _DIRORIGIN
|
l.value = zDirOrigin
|
||||||
case "$INCLUDE":
|
case "$INCLUDE":
|
||||||
l.value = _DIRINCLUDE
|
l.value = zDirInclude
|
||||||
case "$GENERATE":
|
case "$GENERATE":
|
||||||
l.value = _DIRGENERATE
|
l.value = zDirGenerate
|
||||||
}
|
}
|
||||||
debug.Printf("[7 %+v]", l.token)
|
debug.Printf("[7 %+v]", l.token)
|
||||||
c <- l
|
c <- l
|
||||||
} else {
|
} else {
|
||||||
l.value = _STRING
|
l.value = zString
|
||||||
l.token = string(str[:stri])
|
l.token = string(str[:stri])
|
||||||
l.tokenUpper = strings.ToUpper(l.token)
|
l.tokenUpper = strings.ToUpper(l.token)
|
||||||
l.length = stri
|
l.length = stri
|
||||||
if !rrtype {
|
if !rrtype {
|
||||||
if t, ok := StringToType[l.tokenUpper]; ok {
|
if t, ok := StringToType[l.tokenUpper]; ok {
|
||||||
l.value = _RRTYPE
|
l.value = zRrtpe
|
||||||
l.torc = t
|
l.torc = t
|
||||||
rrtype = true
|
rrtype = true
|
||||||
} else {
|
} else {
|
||||||
if strings.HasPrefix(l.tokenUpper, "TYPE") {
|
if strings.HasPrefix(l.tokenUpper, "TYPE") {
|
||||||
if t, ok := typeToInt(l.token); !ok {
|
t, ok := typeToInt(l.token)
|
||||||
|
if !ok {
|
||||||
l.token = "unknown RR type"
|
l.token = "unknown RR type"
|
||||||
l.err = true
|
l.err = true
|
||||||
c <- l
|
c <- l
|
||||||
return
|
return
|
||||||
} else {
|
|
||||||
l.value = _RRTYPE
|
|
||||||
l.torc = t
|
|
||||||
}
|
}
|
||||||
|
l.value = zRrtpe
|
||||||
|
l.torc = t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if t, ok := StringToClass[l.tokenUpper]; ok {
|
if t, ok := StringToClass[l.tokenUpper]; ok {
|
||||||
l.value = _CLASS
|
l.value = zClass
|
||||||
l.torc = t
|
l.torc = t
|
||||||
} else {
|
} else {
|
||||||
if strings.HasPrefix(l.tokenUpper, "CLASS") {
|
if strings.HasPrefix(l.tokenUpper, "CLASS") {
|
||||||
if t, ok := classToInt(l.token); !ok {
|
t, ok := classToInt(l.token)
|
||||||
|
if !ok {
|
||||||
l.token = "unknown class"
|
l.token = "unknown class"
|
||||||
l.err = true
|
l.err = true
|
||||||
c <- l
|
c <- l
|
||||||
return
|
return
|
||||||
} else {
|
|
||||||
l.value = _CLASS
|
|
||||||
l.torc = t
|
|
||||||
}
|
}
|
||||||
|
l.value = zClass
|
||||||
|
l.torc = t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -593,7 +603,7 @@ func zlexer(s *scan, c chan lex) {
|
|||||||
stri = 0
|
stri = 0
|
||||||
// I reverse space stuff here
|
// I reverse space stuff here
|
||||||
if !space && !commt {
|
if !space && !commt {
|
||||||
l.value = _BLANK
|
l.value = zBlank
|
||||||
l.token = " "
|
l.token = " "
|
||||||
l.length = 1
|
l.length = 1
|
||||||
debug.Printf("[5 %+v]", l.token)
|
debug.Printf("[5 %+v]", l.token)
|
||||||
@ -615,7 +625,7 @@ func zlexer(s *scan, c chan lex) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
if stri > 0 {
|
if stri > 0 {
|
||||||
l.value = _STRING
|
l.value = zString
|
||||||
l.token = string(str[:stri])
|
l.token = string(str[:stri])
|
||||||
l.length = stri
|
l.length = stri
|
||||||
debug.Printf("[4 %+v]", l.token)
|
debug.Printf("[4 %+v]", l.token)
|
||||||
@ -651,7 +661,7 @@ func zlexer(s *scan, c chan lex) {
|
|||||||
if brace == 0 {
|
if brace == 0 {
|
||||||
owner = true
|
owner = true
|
||||||
owner = true
|
owner = true
|
||||||
l.value = _NEWLINE
|
l.value = zNewline
|
||||||
l.token = "\n"
|
l.token = "\n"
|
||||||
l.length = 1
|
l.length = 1
|
||||||
l.comment = string(com[:comi])
|
l.comment = string(com[:comi])
|
||||||
@ -669,14 +679,14 @@ func zlexer(s *scan, c chan lex) {
|
|||||||
if brace == 0 {
|
if brace == 0 {
|
||||||
// If there is previous text, we should output it here
|
// If there is previous text, we should output it here
|
||||||
if stri != 0 {
|
if stri != 0 {
|
||||||
l.value = _STRING
|
l.value = zString
|
||||||
l.token = string(str[:stri])
|
l.token = string(str[:stri])
|
||||||
l.tokenUpper = strings.ToUpper(l.token)
|
l.tokenUpper = strings.ToUpper(l.token)
|
||||||
|
|
||||||
l.length = stri
|
l.length = stri
|
||||||
if !rrtype {
|
if !rrtype {
|
||||||
if t, ok := StringToType[l.tokenUpper]; ok {
|
if t, ok := StringToType[l.tokenUpper]; ok {
|
||||||
l.value = _RRTYPE
|
l.value = zRrtpe
|
||||||
l.torc = t
|
l.torc = t
|
||||||
rrtype = true
|
rrtype = true
|
||||||
}
|
}
|
||||||
@ -684,7 +694,7 @@ func zlexer(s *scan, c chan lex) {
|
|||||||
debug.Printf("[2 %+v]", l.token)
|
debug.Printf("[2 %+v]", l.token)
|
||||||
c <- l
|
c <- l
|
||||||
}
|
}
|
||||||
l.value = _NEWLINE
|
l.value = zNewline
|
||||||
l.token = "\n"
|
l.token = "\n"
|
||||||
l.length = 1
|
l.length = 1
|
||||||
debug.Printf("[1 %+v]", l.token)
|
debug.Printf("[1 %+v]", l.token)
|
||||||
@ -728,7 +738,7 @@ func zlexer(s *scan, c chan lex) {
|
|||||||
space = false
|
space = false
|
||||||
// send previous gathered text and the quote
|
// send previous gathered text and the quote
|
||||||
if stri != 0 {
|
if stri != 0 {
|
||||||
l.value = _STRING
|
l.value = zString
|
||||||
l.token = string(str[:stri])
|
l.token = string(str[:stri])
|
||||||
l.length = stri
|
l.length = stri
|
||||||
|
|
||||||
@ -738,7 +748,7 @@ func zlexer(s *scan, c chan lex) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// send quote itself as separate token
|
// send quote itself as separate token
|
||||||
l.value = _QUOTE
|
l.value = zQuote
|
||||||
l.token = "\""
|
l.token = "\""
|
||||||
l.length = 1
|
l.length = 1
|
||||||
c <- l
|
c <- l
|
||||||
@ -790,7 +800,7 @@ func zlexer(s *scan, c chan lex) {
|
|||||||
// Send remainder
|
// Send remainder
|
||||||
l.token = string(str[:stri])
|
l.token = string(str[:stri])
|
||||||
l.length = stri
|
l.length = stri
|
||||||
l.value = _STRING
|
l.value = zString
|
||||||
debug.Printf("[%+v]", l.token)
|
debug.Printf("[%+v]", l.token)
|
||||||
c <- l
|
c <- l
|
||||||
}
|
}
|
||||||
@ -798,7 +808,11 @@ func zlexer(s *scan, c chan lex) {
|
|||||||
|
|
||||||
// Extract the class number from CLASSxx
|
// Extract the class number from CLASSxx
|
||||||
func classToInt(token string) (uint16, bool) {
|
func classToInt(token string) (uint16, bool) {
|
||||||
class, ok := strconv.Atoi(token[5:])
|
offset := 5
|
||||||
|
if len(token) < offset+1 {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
class, ok := strconv.Atoi(token[offset:])
|
||||||
if ok != nil || class > maxUint16 {
|
if ok != nil || class > maxUint16 {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
@ -807,7 +821,11 @@ func classToInt(token string) (uint16, bool) {
|
|||||||
|
|
||||||
// Extract the rr number from TYPExxx
|
// Extract the rr number from TYPExxx
|
||||||
func typeToInt(token string) (uint16, bool) {
|
func typeToInt(token string) (uint16, bool) {
|
||||||
typ, ok := strconv.Atoi(token[4:])
|
offset := 4
|
||||||
|
if len(token) < offset+1 {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
typ, ok := strconv.Atoi(token[offset:])
|
||||||
if ok != nil || typ > maxUint16 {
|
if ok != nil || typ > maxUint16 {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
@ -922,15 +940,15 @@ func slurpRemainder(c chan lex, f string) (*ParseError, string) {
|
|||||||
l := <-c
|
l := <-c
|
||||||
com := ""
|
com := ""
|
||||||
switch l.value {
|
switch l.value {
|
||||||
case _BLANK:
|
case zBlank:
|
||||||
l = <-c
|
l = <-c
|
||||||
com = l.comment
|
com = l.comment
|
||||||
if l.value != _NEWLINE && l.value != _EOF {
|
if l.value != zNewline && l.value != zEOF {
|
||||||
return &ParseError{f, "garbage after rdata", l}, ""
|
return &ParseError{f, "garbage after rdata", l}, ""
|
||||||
}
|
}
|
||||||
case _NEWLINE:
|
case zNewline:
|
||||||
com = l.comment
|
com = l.comment
|
||||||
case _EOF:
|
case zEOF:
|
||||||
default:
|
default:
|
||||||
return &ParseError{f, "garbage after rdata", l}, ""
|
return &ParseError{f, "garbage after rdata", l}, ""
|
||||||
}
|
}
|
||||||
|
1155
vendor/github.com/miekg/dns/zscan_rr.go
generated
vendored
1155
vendor/github.com/miekg/dns/zscan_rr.go
generated
vendored
File diff suppressed because it is too large
Load Diff
842
vendor/github.com/miekg/dns/ztypes.go
generated
vendored
Normal file
842
vendor/github.com/miekg/dns/ztypes.go
generated
vendored
Normal file
@ -0,0 +1,842 @@
|
|||||||
|
// *** DO NOT MODIFY ***
|
||||||
|
// AUTOGENERATED BY go generate
|
||||||
|
|
||||||
|
package dns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TypeToRR is a map of constructors for each RR type.
|
||||||
|
var TypeToRR = map[uint16]func() RR{
|
||||||
|
TypeA: func() RR { return new(A) },
|
||||||
|
TypeAAAA: func() RR { return new(AAAA) },
|
||||||
|
TypeAFSDB: func() RR { return new(AFSDB) },
|
||||||
|
TypeANY: func() RR { return new(ANY) },
|
||||||
|
TypeCAA: func() RR { return new(CAA) },
|
||||||
|
TypeCDNSKEY: func() RR { return new(CDNSKEY) },
|
||||||
|
TypeCDS: func() RR { return new(CDS) },
|
||||||
|
TypeCERT: func() RR { return new(CERT) },
|
||||||
|
TypeCNAME: func() RR { return new(CNAME) },
|
||||||
|
TypeDHCID: func() RR { return new(DHCID) },
|
||||||
|
TypeDLV: func() RR { return new(DLV) },
|
||||||
|
TypeDNAME: func() RR { return new(DNAME) },
|
||||||
|
TypeDNSKEY: func() RR { return new(DNSKEY) },
|
||||||
|
TypeDS: func() RR { return new(DS) },
|
||||||
|
TypeEID: func() RR { return new(EID) },
|
||||||
|
TypeEUI48: func() RR { return new(EUI48) },
|
||||||
|
TypeEUI64: func() RR { return new(EUI64) },
|
||||||
|
TypeGID: func() RR { return new(GID) },
|
||||||
|
TypeGPOS: func() RR { return new(GPOS) },
|
||||||
|
TypeHINFO: func() RR { return new(HINFO) },
|
||||||
|
TypeHIP: func() RR { return new(HIP) },
|
||||||
|
TypeIPSECKEY: func() RR { return new(IPSECKEY) },
|
||||||
|
TypeKEY: func() RR { return new(KEY) },
|
||||||
|
TypeKX: func() RR { return new(KX) },
|
||||||
|
TypeL32: func() RR { return new(L32) },
|
||||||
|
TypeL64: func() RR { return new(L64) },
|
||||||
|
TypeLOC: func() RR { return new(LOC) },
|
||||||
|
TypeLP: func() RR { return new(LP) },
|
||||||
|
TypeMB: func() RR { return new(MB) },
|
||||||
|
TypeMD: func() RR { return new(MD) },
|
||||||
|
TypeMF: func() RR { return new(MF) },
|
||||||
|
TypeMG: func() RR { return new(MG) },
|
||||||
|
TypeMINFO: func() RR { return new(MINFO) },
|
||||||
|
TypeMR: func() RR { return new(MR) },
|
||||||
|
TypeMX: func() RR { return new(MX) },
|
||||||
|
TypeNAPTR: func() RR { return new(NAPTR) },
|
||||||
|
TypeNID: func() RR { return new(NID) },
|
||||||
|
TypeNIMLOC: func() RR { return new(NIMLOC) },
|
||||||
|
TypeNINFO: func() RR { return new(NINFO) },
|
||||||
|
TypeNS: func() RR { return new(NS) },
|
||||||
|
TypeNSAPPTR: func() RR { return new(NSAPPTR) },
|
||||||
|
TypeNSEC: func() RR { return new(NSEC) },
|
||||||
|
TypeNSEC3: func() RR { return new(NSEC3) },
|
||||||
|
TypeNSEC3PARAM: func() RR { return new(NSEC3PARAM) },
|
||||||
|
TypeOPENPGPKEY: func() RR { return new(OPENPGPKEY) },
|
||||||
|
TypeOPT: func() RR { return new(OPT) },
|
||||||
|
TypePTR: func() RR { return new(PTR) },
|
||||||
|
TypePX: func() RR { return new(PX) },
|
||||||
|
TypeRKEY: func() RR { return new(RKEY) },
|
||||||
|
TypeRP: func() RR { return new(RP) },
|
||||||
|
TypeRRSIG: func() RR { return new(RRSIG) },
|
||||||
|
TypeRT: func() RR { return new(RT) },
|
||||||
|
TypeSIG: func() RR { return new(SIG) },
|
||||||
|
TypeSOA: func() RR { return new(SOA) },
|
||||||
|
TypeSPF: func() RR { return new(SPF) },
|
||||||
|
TypeSRV: func() RR { return new(SRV) },
|
||||||
|
TypeSSHFP: func() RR { return new(SSHFP) },
|
||||||
|
TypeTA: func() RR { return new(TA) },
|
||||||
|
TypeTALINK: func() RR { return new(TALINK) },
|
||||||
|
TypeTKEY: func() RR { return new(TKEY) },
|
||||||
|
TypeTLSA: func() RR { return new(TLSA) },
|
||||||
|
TypeTSIG: func() RR { return new(TSIG) },
|
||||||
|
TypeTXT: func() RR { return new(TXT) },
|
||||||
|
TypeUID: func() RR { return new(UID) },
|
||||||
|
TypeUINFO: func() RR { return new(UINFO) },
|
||||||
|
TypeURI: func() RR { return new(URI) },
|
||||||
|
TypeWKS: func() RR { return new(WKS) },
|
||||||
|
TypeX25: func() RR { return new(X25) },
|
||||||
|
}
|
||||||
|
|
||||||
|
// TypeToString is a map of strings for each RR type.
|
||||||
|
var TypeToString = map[uint16]string{
|
||||||
|
TypeA: "A",
|
||||||
|
TypeAAAA: "AAAA",
|
||||||
|
TypeAFSDB: "AFSDB",
|
||||||
|
TypeANY: "ANY",
|
||||||
|
TypeATMA: "ATMA",
|
||||||
|
TypeAXFR: "AXFR",
|
||||||
|
TypeCAA: "CAA",
|
||||||
|
TypeCDNSKEY: "CDNSKEY",
|
||||||
|
TypeCDS: "CDS",
|
||||||
|
TypeCERT: "CERT",
|
||||||
|
TypeCNAME: "CNAME",
|
||||||
|
TypeDHCID: "DHCID",
|
||||||
|
TypeDLV: "DLV",
|
||||||
|
TypeDNAME: "DNAME",
|
||||||
|
TypeDNSKEY: "DNSKEY",
|
||||||
|
TypeDS: "DS",
|
||||||
|
TypeEID: "EID",
|
||||||
|
TypeEUI48: "EUI48",
|
||||||
|
TypeEUI64: "EUI64",
|
||||||
|
TypeGID: "GID",
|
||||||
|
TypeGPOS: "GPOS",
|
||||||
|
TypeHINFO: "HINFO",
|
||||||
|
TypeHIP: "HIP",
|
||||||
|
TypeIPSECKEY: "IPSECKEY",
|
||||||
|
TypeISDN: "ISDN",
|
||||||
|
TypeIXFR: "IXFR",
|
||||||
|
TypeKEY: "KEY",
|
||||||
|
TypeKX: "KX",
|
||||||
|
TypeL32: "L32",
|
||||||
|
TypeL64: "L64",
|
||||||
|
TypeLOC: "LOC",
|
||||||
|
TypeLP: "LP",
|
||||||
|
TypeMAILA: "MAILA",
|
||||||
|
TypeMAILB: "MAILB",
|
||||||
|
TypeMB: "MB",
|
||||||
|
TypeMD: "MD",
|
||||||
|
TypeMF: "MF",
|
||||||
|
TypeMG: "MG",
|
||||||
|
TypeMINFO: "MINFO",
|
||||||
|
TypeMR: "MR",
|
||||||
|
TypeMX: "MX",
|
||||||
|
TypeNAPTR: "NAPTR",
|
||||||
|
TypeNID: "NID",
|
||||||
|
TypeNIMLOC: "NIMLOC",
|
||||||
|
TypeNINFO: "NINFO",
|
||||||
|
TypeNS: "NS",
|
||||||
|
TypeNSEC: "NSEC",
|
||||||
|
TypeNSEC3: "NSEC3",
|
||||||
|
TypeNSEC3PARAM: "NSEC3PARAM",
|
||||||
|
TypeNULL: "NULL",
|
||||||
|
TypeNXT: "NXT",
|
||||||
|
TypeNone: "None",
|
||||||
|
TypeOPENPGPKEY: "OPENPGPKEY",
|
||||||
|
TypeOPT: "OPT",
|
||||||
|
TypePTR: "PTR",
|
||||||
|
TypePX: "PX",
|
||||||
|
TypeRKEY: "RKEY",
|
||||||
|
TypeRP: "RP",
|
||||||
|
TypeRRSIG: "RRSIG",
|
||||||
|
TypeRT: "RT",
|
||||||
|
TypeReserved: "Reserved",
|
||||||
|
TypeSIG: "SIG",
|
||||||
|
TypeSOA: "SOA",
|
||||||
|
TypeSPF: "SPF",
|
||||||
|
TypeSRV: "SRV",
|
||||||
|
TypeSSHFP: "SSHFP",
|
||||||
|
TypeTA: "TA",
|
||||||
|
TypeTALINK: "TALINK",
|
||||||
|
TypeTKEY: "TKEY",
|
||||||
|
TypeTLSA: "TLSA",
|
||||||
|
TypeTSIG: "TSIG",
|
||||||
|
TypeTXT: "TXT",
|
||||||
|
TypeUID: "UID",
|
||||||
|
TypeUINFO: "UINFO",
|
||||||
|
TypeUNSPEC: "UNSPEC",
|
||||||
|
TypeURI: "URI",
|
||||||
|
TypeWKS: "WKS",
|
||||||
|
TypeX25: "X25",
|
||||||
|
TypeNSAPPTR: "NSAP-PTR",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Header() functions
|
||||||
|
func (rr *A) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *AAAA) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *AFSDB) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *ANY) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *CAA) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *CDNSKEY) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *CDS) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *CERT) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *CNAME) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *DHCID) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *DLV) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *DNAME) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *DNSKEY) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *DS) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *EID) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *EUI48) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *EUI64) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *GID) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *GPOS) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *HINFO) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *HIP) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *IPSECKEY) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *KEY) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *KX) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *L32) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *L64) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *LOC) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *LP) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *MB) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *MD) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *MF) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *MG) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *MINFO) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *MR) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *MX) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *NAPTR) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *NID) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *NIMLOC) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *NINFO) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *NS) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *NSAPPTR) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *NSEC) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *NSEC3) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *NSEC3PARAM) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *OPENPGPKEY) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *OPT) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *PTR) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *PX) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *RFC3597) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *RKEY) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *RP) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *RRSIG) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *RT) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *SIG) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *SOA) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *SPF) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *SRV) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *SSHFP) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *TA) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *TALINK) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *TKEY) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *TLSA) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *TSIG) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *TXT) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *UID) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *UINFO) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *URI) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *WKS) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *X25) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
|
||||||
|
// len() functions
|
||||||
|
func (rr *A) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += net.IPv4len // A
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *AAAA) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += net.IPv6len // AAAA
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *AFSDB) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += 2 // Subtype
|
||||||
|
l += len(rr.Hostname) + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *ANY) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *CAA) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += 1 // Flag
|
||||||
|
l += len(rr.Tag) + 1
|
||||||
|
l += len(rr.Value)
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *CERT) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += 2 // Type
|
||||||
|
l += 2 // KeyTag
|
||||||
|
l += 1 // Algorithm
|
||||||
|
l += base64.StdEncoding.DecodedLen(len(rr.Certificate))
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *CNAME) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += len(rr.Target) + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *DHCID) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += base64.StdEncoding.DecodedLen(len(rr.Digest))
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *DNAME) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += len(rr.Target) + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *DNSKEY) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += 2 // Flags
|
||||||
|
l += 1 // Protocol
|
||||||
|
l += 1 // Algorithm
|
||||||
|
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *DS) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += 2 // KeyTag
|
||||||
|
l += 1 // Algorithm
|
||||||
|
l += 1 // DigestType
|
||||||
|
l += len(rr.Digest)/2 + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *EID) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += len(rr.Endpoint)/2 + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *EUI48) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += 6 // Address
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *EUI64) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += 8 // Address
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *GID) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += 4 // Gid
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *GPOS) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += len(rr.Longitude) + 1
|
||||||
|
l += len(rr.Latitude) + 1
|
||||||
|
l += len(rr.Altitude) + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *HINFO) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += len(rr.Cpu) + 1
|
||||||
|
l += len(rr.Os) + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *HIP) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += 1 // HitLength
|
||||||
|
l += 1 // PublicKeyAlgorithm
|
||||||
|
l += 2 // PublicKeyLength
|
||||||
|
l += len(rr.Hit)/2 + 1
|
||||||
|
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
|
||||||
|
for _, x := range rr.RendezvousServers {
|
||||||
|
l += len(x) + 1
|
||||||
|
}
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *KX) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += 2 // Preference
|
||||||
|
l += len(rr.Exchanger) + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *L32) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += 2 // Preference
|
||||||
|
l += net.IPv4len // Locator32
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *L64) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += 2 // Preference
|
||||||
|
l += 8 // Locator64
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *LOC) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += 1 // Version
|
||||||
|
l += 1 // Size
|
||||||
|
l += 1 // HorizPre
|
||||||
|
l += 1 // VertPre
|
||||||
|
l += 4 // Latitude
|
||||||
|
l += 4 // Longitude
|
||||||
|
l += 4 // Altitude
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *LP) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += 2 // Preference
|
||||||
|
l += len(rr.Fqdn) + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *MB) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += len(rr.Mb) + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *MD) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += len(rr.Md) + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *MF) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += len(rr.Mf) + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *MG) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += len(rr.Mg) + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *MINFO) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += len(rr.Rmail) + 1
|
||||||
|
l += len(rr.Email) + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *MR) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += len(rr.Mr) + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *MX) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += 2 // Preference
|
||||||
|
l += len(rr.Mx) + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *NAPTR) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += 2 // Order
|
||||||
|
l += 2 // Preference
|
||||||
|
l += len(rr.Flags) + 1
|
||||||
|
l += len(rr.Service) + 1
|
||||||
|
l += len(rr.Regexp) + 1
|
||||||
|
l += len(rr.Replacement) + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *NID) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += 2 // Preference
|
||||||
|
l += 8 // NodeID
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *NIMLOC) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += len(rr.Locator)/2 + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *NINFO) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
for _, x := range rr.ZSData {
|
||||||
|
l += len(x) + 1
|
||||||
|
}
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *NS) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += len(rr.Ns) + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *NSAPPTR) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += len(rr.Ptr) + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *NSEC3PARAM) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += 1 // Hash
|
||||||
|
l += 1 // Flags
|
||||||
|
l += 2 // Iterations
|
||||||
|
l += 1 // SaltLength
|
||||||
|
l += len(rr.Salt)/2 + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *OPENPGPKEY) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *PTR) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += len(rr.Ptr) + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *PX) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += 2 // Preference
|
||||||
|
l += len(rr.Map822) + 1
|
||||||
|
l += len(rr.Mapx400) + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *RFC3597) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += len(rr.Rdata)/2 + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *RKEY) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += 2 // Flags
|
||||||
|
l += 1 // Protocol
|
||||||
|
l += 1 // Algorithm
|
||||||
|
l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *RP) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += len(rr.Mbox) + 1
|
||||||
|
l += len(rr.Txt) + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *RRSIG) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += 2 // TypeCovered
|
||||||
|
l += 1 // Algorithm
|
||||||
|
l += 1 // Labels
|
||||||
|
l += 4 // OrigTtl
|
||||||
|
l += 4 // Expiration
|
||||||
|
l += 4 // Inception
|
||||||
|
l += 2 // KeyTag
|
||||||
|
l += len(rr.SignerName) + 1
|
||||||
|
l += base64.StdEncoding.DecodedLen(len(rr.Signature))
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *RT) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += 2 // Preference
|
||||||
|
l += len(rr.Host) + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *SOA) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += len(rr.Ns) + 1
|
||||||
|
l += len(rr.Mbox) + 1
|
||||||
|
l += 4 // Serial
|
||||||
|
l += 4 // Refresh
|
||||||
|
l += 4 // Retry
|
||||||
|
l += 4 // Expire
|
||||||
|
l += 4 // Minttl
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *SPF) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
for _, x := range rr.Txt {
|
||||||
|
l += len(x) + 1
|
||||||
|
}
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *SRV) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += 2 // Priority
|
||||||
|
l += 2 // Weight
|
||||||
|
l += 2 // Port
|
||||||
|
l += len(rr.Target) + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *SSHFP) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += 1 // Algorithm
|
||||||
|
l += 1 // Type
|
||||||
|
l += len(rr.FingerPrint)/2 + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *TA) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += 2 // KeyTag
|
||||||
|
l += 1 // Algorithm
|
||||||
|
l += 1 // DigestType
|
||||||
|
l += len(rr.Digest)/2 + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *TALINK) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += len(rr.PreviousName) + 1
|
||||||
|
l += len(rr.NextName) + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *TKEY) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += len(rr.Algorithm) + 1
|
||||||
|
l += 4 // Inception
|
||||||
|
l += 4 // Expiration
|
||||||
|
l += 2 // Mode
|
||||||
|
l += 2 // Error
|
||||||
|
l += 2 // KeySize
|
||||||
|
l += len(rr.Key) + 1
|
||||||
|
l += 2 // OtherLen
|
||||||
|
l += len(rr.OtherData) + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *TLSA) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += 1 // Usage
|
||||||
|
l += 1 // Selector
|
||||||
|
l += 1 // MatchingType
|
||||||
|
l += len(rr.Certificate)/2 + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *TSIG) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += len(rr.Algorithm) + 1
|
||||||
|
l += 6 // TimeSigned
|
||||||
|
l += 2 // Fudge
|
||||||
|
l += 2 // MACSize
|
||||||
|
l += len(rr.MAC)/2 + 1
|
||||||
|
l += 2 // OrigId
|
||||||
|
l += 2 // Error
|
||||||
|
l += 2 // OtherLen
|
||||||
|
l += len(rr.OtherData)/2 + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *TXT) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
for _, x := range rr.Txt {
|
||||||
|
l += len(x) + 1
|
||||||
|
}
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *UID) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += 4 // Uid
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *UINFO) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += len(rr.Uinfo) + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *URI) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += 2 // Priority
|
||||||
|
l += 2 // Weight
|
||||||
|
l += len(rr.Target)
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
func (rr *X25) len() int {
|
||||||
|
l := rr.Hdr.len()
|
||||||
|
l += len(rr.PSDNAddress) + 1
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy() functions
|
||||||
|
func (rr *A) copy() RR {
|
||||||
|
return &A{*rr.Hdr.copyHeader(), copyIP(rr.A)}
|
||||||
|
}
|
||||||
|
func (rr *AAAA) copy() RR {
|
||||||
|
return &AAAA{*rr.Hdr.copyHeader(), copyIP(rr.AAAA)}
|
||||||
|
}
|
||||||
|
func (rr *AFSDB) copy() RR {
|
||||||
|
return &AFSDB{*rr.Hdr.copyHeader(), rr.Subtype, rr.Hostname}
|
||||||
|
}
|
||||||
|
func (rr *ANY) copy() RR {
|
||||||
|
return &ANY{*rr.Hdr.copyHeader()}
|
||||||
|
}
|
||||||
|
func (rr *CAA) copy() RR {
|
||||||
|
return &CAA{*rr.Hdr.copyHeader(), rr.Flag, rr.Tag, rr.Value}
|
||||||
|
}
|
||||||
|
func (rr *CERT) copy() RR {
|
||||||
|
return &CERT{*rr.Hdr.copyHeader(), rr.Type, rr.KeyTag, rr.Algorithm, rr.Certificate}
|
||||||
|
}
|
||||||
|
func (rr *CNAME) copy() RR {
|
||||||
|
return &CNAME{*rr.Hdr.copyHeader(), rr.Target}
|
||||||
|
}
|
||||||
|
func (rr *DHCID) copy() RR {
|
||||||
|
return &DHCID{*rr.Hdr.copyHeader(), rr.Digest}
|
||||||
|
}
|
||||||
|
func (rr *DNAME) copy() RR {
|
||||||
|
return &DNAME{*rr.Hdr.copyHeader(), rr.Target}
|
||||||
|
}
|
||||||
|
func (rr *DNSKEY) copy() RR {
|
||||||
|
return &DNSKEY{*rr.Hdr.copyHeader(), rr.Flags, rr.Protocol, rr.Algorithm, rr.PublicKey}
|
||||||
|
}
|
||||||
|
func (rr *DS) copy() RR {
|
||||||
|
return &DS{*rr.Hdr.copyHeader(), rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest}
|
||||||
|
}
|
||||||
|
func (rr *EID) copy() RR {
|
||||||
|
return &EID{*rr.Hdr.copyHeader(), rr.Endpoint}
|
||||||
|
}
|
||||||
|
func (rr *EUI48) copy() RR {
|
||||||
|
return &EUI48{*rr.Hdr.copyHeader(), rr.Address}
|
||||||
|
}
|
||||||
|
func (rr *EUI64) copy() RR {
|
||||||
|
return &EUI64{*rr.Hdr.copyHeader(), rr.Address}
|
||||||
|
}
|
||||||
|
func (rr *GID) copy() RR {
|
||||||
|
return &GID{*rr.Hdr.copyHeader(), rr.Gid}
|
||||||
|
}
|
||||||
|
func (rr *GPOS) copy() RR {
|
||||||
|
return &GPOS{*rr.Hdr.copyHeader(), rr.Longitude, rr.Latitude, rr.Altitude}
|
||||||
|
}
|
||||||
|
func (rr *HINFO) copy() RR {
|
||||||
|
return &HINFO{*rr.Hdr.copyHeader(), rr.Cpu, rr.Os}
|
||||||
|
}
|
||||||
|
func (rr *HIP) copy() RR {
|
||||||
|
RendezvousServers := make([]string, len(rr.RendezvousServers))
|
||||||
|
copy(RendezvousServers, rr.RendezvousServers)
|
||||||
|
return &HIP{*rr.Hdr.copyHeader(), rr.HitLength, rr.PublicKeyAlgorithm, rr.PublicKeyLength, rr.Hit, rr.PublicKey, RendezvousServers}
|
||||||
|
}
|
||||||
|
func (rr *IPSECKEY) copy() RR {
|
||||||
|
return &IPSECKEY{*rr.Hdr.copyHeader(), rr.Precedence, rr.GatewayType, rr.Algorithm, copyIP(rr.GatewayA), copyIP(rr.GatewayAAAA), rr.GatewayName, rr.PublicKey}
|
||||||
|
}
|
||||||
|
func (rr *KX) copy() RR {
|
||||||
|
return &KX{*rr.Hdr.copyHeader(), rr.Preference, rr.Exchanger}
|
||||||
|
}
|
||||||
|
func (rr *L32) copy() RR {
|
||||||
|
return &L32{*rr.Hdr.copyHeader(), rr.Preference, copyIP(rr.Locator32)}
|
||||||
|
}
|
||||||
|
func (rr *L64) copy() RR {
|
||||||
|
return &L64{*rr.Hdr.copyHeader(), rr.Preference, rr.Locator64}
|
||||||
|
}
|
||||||
|
func (rr *LOC) copy() RR {
|
||||||
|
return &LOC{*rr.Hdr.copyHeader(), rr.Version, rr.Size, rr.HorizPre, rr.VertPre, rr.Latitude, rr.Longitude, rr.Altitude}
|
||||||
|
}
|
||||||
|
func (rr *LP) copy() RR {
|
||||||
|
return &LP{*rr.Hdr.copyHeader(), rr.Preference, rr.Fqdn}
|
||||||
|
}
|
||||||
|
func (rr *MB) copy() RR {
|
||||||
|
return &MB{*rr.Hdr.copyHeader(), rr.Mb}
|
||||||
|
}
|
||||||
|
func (rr *MD) copy() RR {
|
||||||
|
return &MD{*rr.Hdr.copyHeader(), rr.Md}
|
||||||
|
}
|
||||||
|
func (rr *MF) copy() RR {
|
||||||
|
return &MF{*rr.Hdr.copyHeader(), rr.Mf}
|
||||||
|
}
|
||||||
|
func (rr *MG) copy() RR {
|
||||||
|
return &MG{*rr.Hdr.copyHeader(), rr.Mg}
|
||||||
|
}
|
||||||
|
func (rr *MINFO) copy() RR {
|
||||||
|
return &MINFO{*rr.Hdr.copyHeader(), rr.Rmail, rr.Email}
|
||||||
|
}
|
||||||
|
func (rr *MR) copy() RR {
|
||||||
|
return &MR{*rr.Hdr.copyHeader(), rr.Mr}
|
||||||
|
}
|
||||||
|
func (rr *MX) copy() RR {
|
||||||
|
return &MX{*rr.Hdr.copyHeader(), rr.Preference, rr.Mx}
|
||||||
|
}
|
||||||
|
func (rr *NAPTR) copy() RR {
|
||||||
|
return &NAPTR{*rr.Hdr.copyHeader(), rr.Order, rr.Preference, rr.Flags, rr.Service, rr.Regexp, rr.Replacement}
|
||||||
|
}
|
||||||
|
func (rr *NID) copy() RR {
|
||||||
|
return &NID{*rr.Hdr.copyHeader(), rr.Preference, rr.NodeID}
|
||||||
|
}
|
||||||
|
func (rr *NIMLOC) copy() RR {
|
||||||
|
return &NIMLOC{*rr.Hdr.copyHeader(), rr.Locator}
|
||||||
|
}
|
||||||
|
func (rr *NINFO) copy() RR {
|
||||||
|
ZSData := make([]string, len(rr.ZSData))
|
||||||
|
copy(ZSData, rr.ZSData)
|
||||||
|
return &NINFO{*rr.Hdr.copyHeader(), ZSData}
|
||||||
|
}
|
||||||
|
func (rr *NS) copy() RR {
|
||||||
|
return &NS{*rr.Hdr.copyHeader(), rr.Ns}
|
||||||
|
}
|
||||||
|
func (rr *NSAPPTR) copy() RR {
|
||||||
|
return &NSAPPTR{*rr.Hdr.copyHeader(), rr.Ptr}
|
||||||
|
}
|
||||||
|
func (rr *NSEC) copy() RR {
|
||||||
|
TypeBitMap := make([]uint16, len(rr.TypeBitMap))
|
||||||
|
copy(TypeBitMap, rr.TypeBitMap)
|
||||||
|
return &NSEC{*rr.Hdr.copyHeader(), rr.NextDomain, TypeBitMap}
|
||||||
|
}
|
||||||
|
func (rr *NSEC3) copy() RR {
|
||||||
|
TypeBitMap := make([]uint16, len(rr.TypeBitMap))
|
||||||
|
copy(TypeBitMap, rr.TypeBitMap)
|
||||||
|
return &NSEC3{*rr.Hdr.copyHeader(), rr.Hash, rr.Flags, rr.Iterations, rr.SaltLength, rr.Salt, rr.HashLength, rr.NextDomain, TypeBitMap}
|
||||||
|
}
|
||||||
|
func (rr *NSEC3PARAM) copy() RR {
|
||||||
|
return &NSEC3PARAM{*rr.Hdr.copyHeader(), rr.Hash, rr.Flags, rr.Iterations, rr.SaltLength, rr.Salt}
|
||||||
|
}
|
||||||
|
func (rr *OPENPGPKEY) copy() RR {
|
||||||
|
return &OPENPGPKEY{*rr.Hdr.copyHeader(), rr.PublicKey}
|
||||||
|
}
|
||||||
|
func (rr *OPT) copy() RR {
|
||||||
|
Option := make([]EDNS0, len(rr.Option))
|
||||||
|
copy(Option, rr.Option)
|
||||||
|
return &OPT{*rr.Hdr.copyHeader(), Option}
|
||||||
|
}
|
||||||
|
func (rr *PTR) copy() RR {
|
||||||
|
return &PTR{*rr.Hdr.copyHeader(), rr.Ptr}
|
||||||
|
}
|
||||||
|
func (rr *PX) copy() RR {
|
||||||
|
return &PX{*rr.Hdr.copyHeader(), rr.Preference, rr.Map822, rr.Mapx400}
|
||||||
|
}
|
||||||
|
func (rr *RFC3597) copy() RR {
|
||||||
|
return &RFC3597{*rr.Hdr.copyHeader(), rr.Rdata}
|
||||||
|
}
|
||||||
|
func (rr *RKEY) copy() RR {
|
||||||
|
return &RKEY{*rr.Hdr.copyHeader(), rr.Flags, rr.Protocol, rr.Algorithm, rr.PublicKey}
|
||||||
|
}
|
||||||
|
func (rr *RP) copy() RR {
|
||||||
|
return &RP{*rr.Hdr.copyHeader(), rr.Mbox, rr.Txt}
|
||||||
|
}
|
||||||
|
func (rr *RRSIG) copy() RR {
|
||||||
|
return &RRSIG{*rr.Hdr.copyHeader(), rr.TypeCovered, rr.Algorithm, rr.Labels, rr.OrigTtl, rr.Expiration, rr.Inception, rr.KeyTag, rr.SignerName, rr.Signature}
|
||||||
|
}
|
||||||
|
func (rr *RT) copy() RR {
|
||||||
|
return &RT{*rr.Hdr.copyHeader(), rr.Preference, rr.Host}
|
||||||
|
}
|
||||||
|
func (rr *SOA) copy() RR {
|
||||||
|
return &SOA{*rr.Hdr.copyHeader(), rr.Ns, rr.Mbox, rr.Serial, rr.Refresh, rr.Retry, rr.Expire, rr.Minttl}
|
||||||
|
}
|
||||||
|
func (rr *SPF) copy() RR {
|
||||||
|
Txt := make([]string, len(rr.Txt))
|
||||||
|
copy(Txt, rr.Txt)
|
||||||
|
return &SPF{*rr.Hdr.copyHeader(), Txt}
|
||||||
|
}
|
||||||
|
func (rr *SRV) copy() RR {
|
||||||
|
return &SRV{*rr.Hdr.copyHeader(), rr.Priority, rr.Weight, rr.Port, rr.Target}
|
||||||
|
}
|
||||||
|
func (rr *SSHFP) copy() RR {
|
||||||
|
return &SSHFP{*rr.Hdr.copyHeader(), rr.Algorithm, rr.Type, rr.FingerPrint}
|
||||||
|
}
|
||||||
|
func (rr *TA) copy() RR {
|
||||||
|
return &TA{*rr.Hdr.copyHeader(), rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest}
|
||||||
|
}
|
||||||
|
func (rr *TALINK) copy() RR {
|
||||||
|
return &TALINK{*rr.Hdr.copyHeader(), rr.PreviousName, rr.NextName}
|
||||||
|
}
|
||||||
|
func (rr *TKEY) copy() RR {
|
||||||
|
return &TKEY{*rr.Hdr.copyHeader(), rr.Algorithm, rr.Inception, rr.Expiration, rr.Mode, rr.Error, rr.KeySize, rr.Key, rr.OtherLen, rr.OtherData}
|
||||||
|
}
|
||||||
|
func (rr *TLSA) copy() RR {
|
||||||
|
return &TLSA{*rr.Hdr.copyHeader(), rr.Usage, rr.Selector, rr.MatchingType, rr.Certificate}
|
||||||
|
}
|
||||||
|
func (rr *TSIG) copy() RR {
|
||||||
|
return &TSIG{*rr.Hdr.copyHeader(), rr.Algorithm, rr.TimeSigned, rr.Fudge, rr.MACSize, rr.MAC, rr.OrigId, rr.Error, rr.OtherLen, rr.OtherData}
|
||||||
|
}
|
||||||
|
func (rr *TXT) copy() RR {
|
||||||
|
Txt := make([]string, len(rr.Txt))
|
||||||
|
copy(Txt, rr.Txt)
|
||||||
|
return &TXT{*rr.Hdr.copyHeader(), Txt}
|
||||||
|
}
|
||||||
|
func (rr *UID) copy() RR {
|
||||||
|
return &UID{*rr.Hdr.copyHeader(), rr.Uid}
|
||||||
|
}
|
||||||
|
func (rr *UINFO) copy() RR {
|
||||||
|
return &UINFO{*rr.Hdr.copyHeader(), rr.Uinfo}
|
||||||
|
}
|
||||||
|
func (rr *URI) copy() RR {
|
||||||
|
return &URI{*rr.Hdr.copyHeader(), rr.Priority, rr.Weight, rr.Target}
|
||||||
|
}
|
||||||
|
func (rr *WKS) copy() RR {
|
||||||
|
BitMap := make([]uint16, len(rr.BitMap))
|
||||||
|
copy(BitMap, rr.BitMap)
|
||||||
|
return &WKS{*rr.Hdr.copyHeader(), copyIP(rr.Address), rr.Protocol, BitMap}
|
||||||
|
}
|
||||||
|
func (rr *X25) copy() RR {
|
||||||
|
return &X25{*rr.Hdr.copyHeader(), rr.PSDNAddress}
|
||||||
|
}
|
58
vendor/github.com/skynetservices/skydns/msg/service.go
generated
vendored
58
vendor/github.com/skynetservices/skydns/msg/service.go
generated
vendored
@ -12,6 +12,14 @@ import (
|
|||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// PathPrefix is the prefix used to store SkyDNS data in the backend.
|
||||||
|
// It defaults to `skydns`.
|
||||||
|
// You can change it by set `path-prefix` configuration or SKYDNS_PATH_PREFIX env. variable.
|
||||||
|
// Then:
|
||||||
|
// The SkyDNS's configuration object should be stored under the key "/mydns/config";
|
||||||
|
// The etcd path of domain `service.staging.skydns.local.` will be "/mydns/local/skydns/staging/service".
|
||||||
|
var PathPrefix string = "skydns"
|
||||||
|
|
||||||
// This *is* the rdata from a SRV record, but with a twist.
|
// This *is* the rdata from a SRV record, but with a twist.
|
||||||
// Host (Target in SRV) must be a domain name, but if it looks like an IP
|
// Host (Target in SRV) must be a domain name, but if it looks like an IP
|
||||||
// address (4/6), we will treat it like an IP address.
|
// address (4/6), we will treat it like an IP address.
|
||||||
@ -29,7 +37,7 @@ type Service struct {
|
|||||||
// the record lives to a DNS name and use this as the srv.Target. When
|
// the record lives to a DNS name and use this as the srv.Target. When
|
||||||
// TargetStrip > 0 we strip the left most TargetStrip labels from the
|
// TargetStrip > 0 we strip the left most TargetStrip labels from the
|
||||||
// DNS name.
|
// DNS name.
|
||||||
TargetStrip int `json:"targetstrip",omitempty"`
|
TargetStrip int `json:"targetstrip,omitempty"`
|
||||||
|
|
||||||
// Group is used to group (or *not* to group) different services
|
// Group is used to group (or *not* to group) different services
|
||||||
// together. Services with an identical Group are returned in the same
|
// together. Services with an identical Group are returned in the same
|
||||||
@ -42,17 +50,7 @@ type Service struct {
|
|||||||
|
|
||||||
// NewSRV returns a new SRV record based on the Service.
|
// NewSRV returns a new SRV record based on the Service.
|
||||||
func (s *Service) NewSRV(name string, weight uint16) *dns.SRV {
|
func (s *Service) NewSRV(name string, weight uint16) *dns.SRV {
|
||||||
host := dns.Fqdn(s.Host)
|
host := targetStrip(dns.Fqdn(s.Host), s.TargetStrip)
|
||||||
|
|
||||||
offset, end := 0, false
|
|
||||||
for i := 0; i < s.TargetStrip; i++ {
|
|
||||||
offset, end = dns.NextLabel(host, offset)
|
|
||||||
}
|
|
||||||
if end {
|
|
||||||
// We overshot the name, use the orignal one.
|
|
||||||
offset = 0
|
|
||||||
}
|
|
||||||
host = host[offset:]
|
|
||||||
|
|
||||||
return &dns.SRV{Hdr: dns.RR_Header{Name: name, Rrtype: dns.TypeSRV, Class: dns.ClassINET, Ttl: s.Ttl},
|
return &dns.SRV{Hdr: dns.RR_Header{Name: name, Rrtype: dns.TypeSRV, Class: dns.ClassINET, Ttl: s.Ttl},
|
||||||
Priority: uint16(s.Priority), Weight: weight, Port: uint16(s.Port), Target: host}
|
Priority: uint16(s.Priority), Weight: weight, Port: uint16(s.Port), Target: host}
|
||||||
@ -60,17 +58,7 @@ func (s *Service) NewSRV(name string, weight uint16) *dns.SRV {
|
|||||||
|
|
||||||
// NewMX returns a new MX record based on the Service.
|
// NewMX returns a new MX record based on the Service.
|
||||||
func (s *Service) NewMX(name string) *dns.MX {
|
func (s *Service) NewMX(name string) *dns.MX {
|
||||||
host := dns.Fqdn(s.Host)
|
host := targetStrip(dns.Fqdn(s.Host), s.TargetStrip)
|
||||||
|
|
||||||
offset, end := 0, false
|
|
||||||
for i := 0; i < s.TargetStrip; i++ {
|
|
||||||
offset, end = dns.NextLabel(host, offset)
|
|
||||||
}
|
|
||||||
if end {
|
|
||||||
// We overshot the name, use the orignal one.
|
|
||||||
offset = 0
|
|
||||||
}
|
|
||||||
host = host[offset:]
|
|
||||||
|
|
||||||
return &dns.MX{Hdr: dns.RR_Header{Name: name, Rrtype: dns.TypeMX, Class: dns.ClassINET, Ttl: s.Ttl},
|
return &dns.MX{Hdr: dns.RR_Header{Name: name, Rrtype: dns.TypeMX, Class: dns.ClassINET, Ttl: s.Ttl},
|
||||||
Preference: uint16(s.Priority), Mx: host}
|
Preference: uint16(s.Priority), Mx: host}
|
||||||
@ -118,10 +106,10 @@ func PathWithWildcard(s string) (string, bool) {
|
|||||||
}
|
}
|
||||||
for i, k := range l {
|
for i, k := range l {
|
||||||
if k == "*" || k == "any" {
|
if k == "*" || k == "any" {
|
||||||
return path.Join(append([]string{"/skydns/"}, l[:i]...)...), true
|
return path.Join(append([]string{"/" + PathPrefix + "/"}, l[:i]...)...), true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return path.Join(append([]string{"/skydns/"}, l...)...), false
|
return path.Join(append([]string{"/" + PathPrefix + "/"}, l...)...), false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Path converts a domainname to an etcd path. If s looks like service.staging.skydns.local.,
|
// Path converts a domainname to an etcd path. If s looks like service.staging.skydns.local.,
|
||||||
@ -131,7 +119,7 @@ func Path(s string) string {
|
|||||||
for i, j := 0, len(l)-1; i < j; i, j = i+1, j-1 {
|
for i, j := 0, len(l)-1; i < j; i, j = i+1, j-1 {
|
||||||
l[i], l[j] = l[j], l[i]
|
l[i], l[j] = l[j], l[i]
|
||||||
}
|
}
|
||||||
return path.Join(append([]string{"/skydns/"}, l...)...)
|
return path.Join(append([]string{"/" + PathPrefix + "/"}, l...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Domain is the opposite of Path.
|
// Domain is the opposite of Path.
|
||||||
@ -213,3 +201,21 @@ func split255(s string) []string {
|
|||||||
|
|
||||||
return sx
|
return sx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// targetStrip strips "targetstrip" labels from the left side of the fully qualified name.
|
||||||
|
func targetStrip(name string, targetStrip int) string {
|
||||||
|
if targetStrip == 0 {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
|
offset, end := 0, false
|
||||||
|
for i := 0; i < targetStrip; i++ {
|
||||||
|
offset, end = dns.NextLabel(name, offset)
|
||||||
|
}
|
||||||
|
if end {
|
||||||
|
// We overshot the name, use the orignal one.
|
||||||
|
offset = 0
|
||||||
|
}
|
||||||
|
name = name[offset:]
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user