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",
|
||||
"Rev": "3f504e8dabd5d562e997d19ce0200aa41973e1b2"
|
||||
"Rev": "c2b278e70f35902fd68b54b69238cd10bb1b7451"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/mistifyio/go-zfs",
|
||||
@ -1779,8 +1779,8 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/skynetservices/skydns/msg",
|
||||
"Comment": "2.5.1a",
|
||||
"Rev": "1be70b5b8aa07acccd972146d84011b670af88b4"
|
||||
"Comment": "2.5.3a-32-gf7b6fb7",
|
||||
"Rev": "f7b6fb74bcfab300b4e7e0e27b1fe6c0ed555f78"
|
||||
},
|
||||
{
|
||||
"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
|
||||
sudo: false
|
||||
go:
|
||||
- 1.2
|
||||
- 1.3
|
||||
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
|
||||
- 1.5
|
||||
- 1.6
|
||||
script:
|
||||
- gvm cross $BUILD_GOOS $BUILD_GOARCH
|
||||
- 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
|
||||
- go test -race -v -bench=.
|
||||
|
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
|
||||
can build servers and resolvers with it.
|
||||
|
||||
If you like this, you may also be interested in:
|
||||
|
||||
* https://github.com/miekg/unbound -- Go wrapper for the Unbound resolver.
|
||||
We try to keep the "master" branch as sane as possible and at the bleeding edge
|
||||
of standards, avoiding breaking changes wherever reasonable. We support the last
|
||||
two versions of Go, currently: 1.4 and 1.5.
|
||||
|
||||
# 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:
|
||||
|
||||
* https://cloudflare.com
|
||||
* https://github.com/abh/geodns
|
||||
* http://www.statdns.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/kenshinx/godns
|
||||
* https://github.com/skynetservices/skydns
|
||||
* https://github.com/hashicorp/consul
|
||||
* https://github.com/DevelopersPL/godnsagent
|
||||
* 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.
|
||||
|
||||
@ -50,6 +64,7 @@ Send pull request if you want to be listed here.
|
||||
* EDNS0, NSID;
|
||||
* AXFR/IXFR;
|
||||
* TSIG, SIG(0);
|
||||
* DNS over TLS: optional encrypted connection between client and server;
|
||||
* DNS name compression;
|
||||
* Depends only on the standard library.
|
||||
|
||||
@ -67,7 +82,7 @@ correctly, the following should work:
|
||||
|
||||
## 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`).
|
||||
|
||||
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*
|
||||
|
||||
* 103{4,5} - DNS standard
|
||||
* 1348 - NSAP record
|
||||
* 1348 - NSAP record (removed the record)
|
||||
* 1982 - Serial Arithmetic
|
||||
* 1876 - LOC record
|
||||
* 1995 - IXFR
|
||||
@ -95,7 +110,8 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
|
||||
* 3225 - DO bit (DNSSEC OK)
|
||||
* 340{1,2,3} - NAPTR record
|
||||
* 3445 - Limiting the scope of (DNS)KEY
|
||||
* 3597 - Unkown RRs
|
||||
* 3597 - Unknown RRs
|
||||
* 4025 - IPSECKEY
|
||||
* 403{3,4,5} - DNSSEC + validation functions
|
||||
* 4255 - SSHFP record
|
||||
* 4343 - Case insensitivity
|
||||
@ -114,13 +130,16 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
|
||||
* 6605 - ECDSA
|
||||
* 6725 - IANA Registry Update
|
||||
* 6742 - ILNP DNS
|
||||
* 6840 - Clarifications and Implementation Notes for DNS Security
|
||||
* 6844 - CAA record
|
||||
* 6891 - EDNS0 update
|
||||
* 6895 - DNS IANA considerations
|
||||
* 6975 - Algorithm Understanding in DNSSEC
|
||||
* 7043 - EUI48/EUI64 records
|
||||
* 7314 - DNS (EDNS) EXPIRE Option
|
||||
* xxxx - URI record (draft)
|
||||
* 7553 - URI record
|
||||
* xxxx - EDNS0 DNS Update Lease (draft)
|
||||
* yyyy - DNS over TLS: Initiation and Performance Considerations (draft)
|
||||
|
||||
## Loosely based upon
|
||||
|
||||
@ -132,9 +151,7 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
|
||||
## TODO
|
||||
|
||||
* privatekey.Precompute() when signing?
|
||||
* Last remaining RRs: APL, ATMA, A6 and NXT;
|
||||
* Missing in parsing: ISDN, UNSPEC, ATMA;
|
||||
* CAA parsing is broken;
|
||||
* NSEC(3) cover/match/closest enclose;
|
||||
* Replies with TC bit are not parsed to the end;
|
||||
* Create IsMsg to validate a message before fully parsing it.
|
||||
* Last remaining RRs: APL, ATMA, A6, NSAP and NXT.
|
||||
* Missing in parsing: ISDN, UNSPEC, NSAP and ATMA.
|
||||
* NSEC(3) cover/match/closest enclose.
|
||||
* Replies with TC bit are not parsed to the end.
|
||||
|
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 (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"io"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
const dnsTimeout time.Duration = 2 * 1e9
|
||||
const dnsTimeout time.Duration = 2 * time.Second
|
||||
const tcpIdleTimeout time.Duration = 8 * time.Second
|
||||
|
||||
// A Conn represents a connection to a DNS server.
|
||||
@ -24,11 +25,12 @@ type Conn struct {
|
||||
|
||||
// A Client defines parameters for a DNS client.
|
||||
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
|
||||
DialTimeout time.Duration // net.DialTimeout (ns), defaults to 2 * 1e9
|
||||
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections (ns), defaults to 2 * 1e9
|
||||
WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections (ns), defaults to 2 * 1e9
|
||||
TLSConfig *tls.Config // TLS connection configuration
|
||||
DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds
|
||||
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
|
||||
SingleInflight bool // if true suppress multiple outstanding queries for the same Qname, Qtype and Qclass
|
||||
group singleflight
|
||||
@ -37,14 +39,7 @@ type Client struct {
|
||||
// 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
|
||||
// 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
|
||||
// following:
|
||||
//
|
||||
// co := &dns.Conn{Conn: c} // c is your net.Conn
|
||||
// co.WriteMsg(m)
|
||||
// in, err := co.ReadMsg()
|
||||
// co.Close()
|
||||
//
|
||||
// See client.Exchange for more information on setting larger buffer sizes.
|
||||
func Exchange(m *Msg, a string) (r *Msg, err error) {
|
||||
var co *Conn
|
||||
co, err = DialTimeout("udp", a, dnsTimeout)
|
||||
@ -53,12 +48,23 @@ func Exchange(m *Msg, a string) (r *Msg, err error) {
|
||||
}
|
||||
|
||||
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))
|
||||
if err = co.WriteMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
co.SetReadDeadline(time.Now().Add(dnsTimeout))
|
||||
r, err = co.ReadMsg()
|
||||
if err == nil && r.Id != m.Id {
|
||||
err = ErrId
|
||||
}
|
||||
return r, err
|
||||
}
|
||||
|
||||
@ -79,6 +85,9 @@ func ExchangeConn(c net.Conn, m *Msg) (r *Msg, err error) {
|
||||
return nil, err
|
||||
}
|
||||
r, err = co.ReadMsg()
|
||||
if err == nil && r.Id != m.Id {
|
||||
err = ErrId
|
||||
}
|
||||
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
|
||||
// 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) {
|
||||
if !c.SingleInflight {
|
||||
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
|
||||
}
|
||||
|
||||
func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
|
||||
timeout := dnsTimeout
|
||||
var co *Conn
|
||||
func (c *Client) dialTimeout() time.Duration {
|
||||
if c.DialTimeout != 0 {
|
||||
timeout = c.DialTimeout
|
||||
return c.DialTimeout
|
||||
}
|
||||
if c.Net == "" {
|
||||
co, err = DialTimeout("udp", a, timeout)
|
||||
return dnsTimeout
|
||||
}
|
||||
|
||||
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 {
|
||||
co, err = DialTimeout(c.Net, a, timeout)
|
||||
co, err = DialTimeout(network, a, c.dialTimeout())
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
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()
|
||||
|
||||
opt := m.IsEdns0()
|
||||
// If EDNS0 is used use that for size.
|
||||
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 {
|
||||
co.UDPSize = c.UDPSize
|
||||
}
|
||||
|
||||
co.TsigSecret = c.TsigSecret
|
||||
co.SetWriteDeadline(time.Now().Add(c.writeTimeout()))
|
||||
if err = co.WriteMsg(m); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
co.SetReadDeadline(time.Now().Add(c.readTimeout()))
|
||||
r, err = co.ReadMsg()
|
||||
if err == nil && r.Id != m.Id {
|
||||
err = ErrId
|
||||
}
|
||||
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
|
||||
// signature is verified.
|
||||
func (co *Conn) ReadMsg() (*Msg, error) {
|
||||
var p []byte
|
||||
p, err := co.ReadMsgHeader(nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
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 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
|
||||
}
|
||||
co.rtt = time.Since(co.t)
|
||||
if t := m.IsTsig(); t != nil {
|
||||
if _, ok := co.TsigSecret[t.Hdr.Name]; !ok {
|
||||
return m, ErrSecret
|
||||
@ -191,6 +234,86 @@ func (co *Conn) ReadMsg() (*Msg, error) {
|
||||
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.
|
||||
func (co *Conn) Read(p []byte) (n int, err error) {
|
||||
if co.Conn == nil {
|
||||
@ -199,32 +322,18 @@ func (co *Conn) Read(p []byte) (n int, err error) {
|
||||
if len(p) < 2 {
|
||||
return 0, io.ErrShortBuffer
|
||||
}
|
||||
if t, ok := co.Conn.(*net.TCPConn); ok {
|
||||
n, err = t.Read(p[0:2])
|
||||
if err != nil || n != 2 {
|
||||
return n, err
|
||||
switch t := co.Conn.(type) {
|
||||
case *net.TCPConn, *tls.Conn:
|
||||
r := t.(io.Reader)
|
||||
|
||||
l, err := tcpMsgLen(r)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
l, _ := unpackUint16(p[0:2], 0)
|
||||
if l == 0 {
|
||||
return 0, ErrShortRead
|
||||
}
|
||||
if int(l) > len(p) {
|
||||
if l > len(p) {
|
||||
return int(l), io.ErrShortBuffer
|
||||
}
|
||||
n, err = t.Read(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
|
||||
return tcpRead(r, p[:l])
|
||||
}
|
||||
// UDP connection
|
||||
n, err = co.Conn.Read(p)
|
||||
@ -234,7 +343,7 @@ func (co *Conn) Read(p []byte) (n int, err error) {
|
||||
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
|
||||
// signature is calculated.
|
||||
func (co *Conn) WriteMsg(m *Msg) (err error) {
|
||||
@ -245,7 +354,7 @@ func (co *Conn) WriteMsg(m *Msg) (err error) {
|
||||
return ErrSecret
|
||||
}
|
||||
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
|
||||
} else {
|
||||
out, err = m.Pack()
|
||||
@ -262,7 +371,10 @@ func (co *Conn) WriteMsg(m *Msg) (err error) {
|
||||
|
||||
// Write implements the net.Conn Write method.
|
||||
func (co *Conn) Write(p []byte) (n int, err error) {
|
||||
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)
|
||||
if lp < 2 {
|
||||
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[0], l[1] = packUint16(uint16(lp))
|
||||
p = append(l, p...)
|
||||
n, err := io.Copy(t, bytes.NewReader(p))
|
||||
n, err := io.Copy(w, bytes.NewReader(p))
|
||||
return int(n), err
|
||||
}
|
||||
n, err = co.Conn.(*net.UDPConn).Write(p)
|
||||
@ -290,7 +402,7 @@ func Dial(network, address string) (conn *Conn, err error) {
|
||||
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) {
|
||||
conn = new(Conn)
|
||||
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
|
||||
}
|
||||
|
||||
// Close implements the net.Conn Close method.
|
||||
func (co *Conn) Close() error { return co.Conn.Close() }
|
||||
// DialWithTLS connects to the address on the named network with TLS.
|
||||
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.
|
||||
func (co *Conn) LocalAddr() net.Addr { return co.Conn.LocalAddr() }
|
||||
// DialTimeoutWithTLS acts like DialWithTLS but takes a timeout.
|
||||
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.
|
||||
func (co *Conn) RemoteAddr() net.Addr { return co.Conn.RemoteAddr() }
|
||||
|
||||
// SetDeadline implements the net.Conn SetDeadline method.
|
||||
func (co *Conn) SetDeadline(t time.Time) error { return co.Conn.SetDeadline(t) }
|
||||
|
||||
// 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) }
|
||||
conn = new(Conn)
|
||||
conn.Conn, err = tls.DialWithDialer(&dialer, network, address, tlsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return conn, nil
|
||||
}
|
||||
|
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"
|
||||
)
|
||||
|
||||
// Wraps the contents of the /etc/resolv.conf.
|
||||
// ClientConfig wraps the contents of the /etc/resolv.conf file.
|
||||
type ClientConfig struct {
|
||||
Servers []string // servers to use
|
||||
Search []string // suffixes to append to local name
|
||||
@ -26,14 +26,19 @@ func ClientConfigFromFile(resolvconf string) (*ClientConfig, error) {
|
||||
}
|
||||
defer file.Close()
|
||||
c := new(ClientConfig)
|
||||
b := bufio.NewReader(file)
|
||||
scanner := bufio.NewScanner(file)
|
||||
c.Servers = make([]string, 0)
|
||||
c.Search = make([]string, 0)
|
||||
c.Port = "53"
|
||||
c.Ndots = 1
|
||||
c.Timeout = 5
|
||||
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)
|
||||
if len(f) < 1 {
|
||||
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
|
||||
}
|
||||
|
||||
// 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 {
|
||||
dns.Id = Id()
|
||||
dns.RecursionDesired = true
|
||||
@ -33,7 +35,9 @@ func (dns *Msg) SetQuestion(z string, t uint16) *Msg {
|
||||
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 {
|
||||
dns.Opcode = OpcodeNotify
|
||||
dns.Authoritative = true
|
||||
@ -73,13 +77,15 @@ func (dns *Msg) SetUpdate(z string) *Msg {
|
||||
}
|
||||
|
||||
// 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.Question = make([]Question, 1)
|
||||
dns.Ns = make([]RR, 1)
|
||||
s := new(SOA)
|
||||
s.Hdr = RR_Header{z, TypeSOA, ClassINET, defaultTtl, 0}
|
||||
s.Serial = serial
|
||||
s.Ns = ns
|
||||
s.Mbox = mbox
|
||||
dns.Question[0] = Question{z, TypeIXFR, ClassINET}
|
||||
dns.Ns[0] = s
|
||||
return dns
|
||||
@ -144,11 +150,14 @@ func (dns *Msg) IsEdns0() *OPT {
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsDomainName checks if s is a valid domainname, it returns
|
||||
// the number of labels and true, when a domain name is valid.
|
||||
// Note that non fully qualified domain name is considered valid, in this case the
|
||||
// last label is counted in the number of labels.
|
||||
// When false is returned the number of labels is not defined.
|
||||
// IsDomainName checks if s is a valid domain name, it returns the number of
|
||||
// labels and true, when a domain name is valid. Note that non fully qualified
|
||||
// domain name is considered valid, in this case the last label is counted in
|
||||
// the number of labels. When false is returned the number of labels is not
|
||||
// defined. Also note that this function is extremely liberal; almost any
|
||||
// string is a valid domain name as the DNS is 8 bit protocol. It checks if each
|
||||
// label fits in 63 characters, but there is no length check for the entire
|
||||
// string s. I.e. a domain name longer than 255 characters is considered valid.
|
||||
func IsDomainName(s string) (labels int, ok bool) {
|
||||
_, labels, err := packDomainName(s, nil, 0, nil, false)
|
||||
return labels, err == nil
|
||||
@ -182,7 +191,34 @@ func IsFqdn(s string) bool {
|
||||
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.
|
||||
func Fqdn(s string) string {
|
||||
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
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
import "strconv"
|
||||
|
||||
const (
|
||||
year68 = 1 << 31 // For RFC1982 (Serial Arithmetic) calculations in 32 bits.
|
||||
DefaultMsgSize = 4096 // Standard default for larger than 512 bytes.
|
||||
MinMsgSize = 512 // Minimal size of a DNS packet.
|
||||
MaxMsgSize = 65536 // Largest possible DNS packet.
|
||||
defaultTtl = 3600 // Default TTL.
|
||||
year68 = 1 << 31 // For RFC1982 (Serial Arithmetic) calculations in 32 bits.
|
||||
// DefaultMsgSize is the standard default for messages larger than 512 bytes.
|
||||
DefaultMsgSize = 4096
|
||||
// MinMsgSize is the minimal size of a DNS packet.
|
||||
MinMsgSize = 512
|
||||
// MaxMsgSize is the largest possible DNS packet.
|
||||
MaxMsgSize = 65535
|
||||
defaultTtl = 3600 // Default internal TTL.
|
||||
)
|
||||
|
||||
// Error represents a DNS error
|
||||
@ -124,13 +32,11 @@ type RR interface {
|
||||
String() string
|
||||
// copy returns a copy of the 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
|
||||
}
|
||||
|
||||
// DNS resource records.
|
||||
// There are many types of RRs,
|
||||
// but they all share the same header.
|
||||
// RR_Header is the header all DNS resource records share.
|
||||
type RR_Header struct {
|
||||
Name string `dns:"cdomain-name"`
|
||||
Rrtype uint16
|
||||
@ -139,9 +45,10 @@ type RR_Header struct {
|
||||
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 }
|
||||
|
||||
// Just to imlement the RR interface
|
||||
// Just to imlement the RR interface.
|
||||
func (h *RR_Header) copy() RR { return nil }
|
||||
|
||||
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
|
||||
|
||||
import (
|
||||
@ -19,15 +6,14 @@ import (
|
||||
"crypto/dsa"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/md5"
|
||||
_ "crypto/md5"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
_ "crypto/sha1"
|
||||
_ "crypto/sha256"
|
||||
_ "crypto/sha512"
|
||||
"encoding/asn1"
|
||||
"encoding/hex"
|
||||
"hash"
|
||||
"io"
|
||||
"math/big"
|
||||
"sort"
|
||||
"strings"
|
||||
@ -56,6 +42,38 @@ const (
|
||||
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.
|
||||
const (
|
||||
_ uint8 = iota
|
||||
@ -66,6 +84,18 @@ const (
|
||||
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.
|
||||
const (
|
||||
SEP = 1
|
||||
@ -74,7 +104,7 @@ const (
|
||||
)
|
||||
|
||||
// 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).
|
||||
type rrsigWireFmt struct {
|
||||
TypeCovered uint16
|
||||
@ -182,35 +212,49 @@ func (k *DNSKEY) ToDS(h uint8) *DS {
|
||||
// digest buffer
|
||||
digest := append(owner, wire...) // another copy
|
||||
|
||||
var hash crypto.Hash
|
||||
switch h {
|
||||
case SHA1:
|
||||
s := sha1.New()
|
||||
io.WriteString(s, string(digest))
|
||||
ds.Digest = hex.EncodeToString(s.Sum(nil))
|
||||
hash = crypto.SHA1
|
||||
case SHA256:
|
||||
s := sha256.New()
|
||||
io.WriteString(s, string(digest))
|
||||
ds.Digest = hex.EncodeToString(s.Sum(nil))
|
||||
hash = crypto.SHA256
|
||||
case SHA384:
|
||||
s := sha512.New384()
|
||||
io.WriteString(s, string(digest))
|
||||
ds.Digest = hex.EncodeToString(s.Sum(nil))
|
||||
case GOST94:
|
||||
/* I have no clue */
|
||||
hash = crypto.SHA384
|
||||
case SHA512:
|
||||
hash = crypto.SHA512
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
||||
s := hash.New()
|
||||
s.Write(digest)
|
||||
ds.Digest = hex.EncodeToString(s.Sum(nil))
|
||||
return ds
|
||||
}
|
||||
|
||||
// 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 true when the signing went OK,
|
||||
// otherwise false.
|
||||
// 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 PrivateKey, rrset []RR) error {
|
||||
// ToCDNSKEY converts a DNSKEY record to a CDNSKEY record.
|
||||
func (k *DNSKEY) ToCDNSKEY() *CDNSKEY {
|
||||
c := &CDNSKEY{DNSKEY: *k}
|
||||
c.Hdr = *k.Hdr.copyHeader()
|
||||
c.Hdr.Rrtype = TypeCDNSKEY
|
||||
return c
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return ErrPrivKey
|
||||
}
|
||||
@ -256,72 +300,72 @@ func (rr *RRSIG) Sign(k PrivateKey, rrset []RR) error {
|
||||
}
|
||||
signdata = append(signdata, wire...)
|
||||
|
||||
var sighash []byte
|
||||
var h hash.Hash
|
||||
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:
|
||||
hash, ok := AlgorithmToHash[rr.Algorithm]
|
||||
if !ok {
|
||||
return ErrAlg
|
||||
}
|
||||
io.WriteString(h, string(signdata))
|
||||
sighash = h.Sum(nil)
|
||||
|
||||
switch p := k.(type) {
|
||||
case *dsa.PrivateKey:
|
||||
r1, s1, err := dsa.Sign(rand.Reader, p, sighash)
|
||||
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
|
||||
h := hash.New()
|
||||
h.Write(signdata)
|
||||
|
||||
signature, err := sign(k, h.Sum(nil), hash, rr.Algorithm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rr.Signature = toBase64(signature)
|
||||
|
||||
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
|
||||
// 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.
|
||||
func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
|
||||
// First the easy checks
|
||||
if len(rrset) == 0 {
|
||||
if !IsRRset(rrset) {
|
||||
return ErrRRset
|
||||
}
|
||||
if rr.KeyTag != k.KeyTag() {
|
||||
@ -339,14 +383,17 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
|
||||
if k.Protocol != 3 {
|
||||
return ErrKey
|
||||
}
|
||||
for _, r := range rrset {
|
||||
if r.Header().Class != rr.Hdr.Class {
|
||||
return ErrRRset
|
||||
}
|
||||
if r.Header().Rrtype != rr.TypeCovered {
|
||||
return ErrRRset
|
||||
}
|
||||
|
||||
// IsRRset checked that we have at least one RR and that the RRs in
|
||||
// the set have consistent type, class, and name. Also check that type and
|
||||
// class matches the RRSIG record.
|
||||
if rrset[0].Header().Class != rr.Hdr.Class {
|
||||
return ErrRRset
|
||||
}
|
||||
if rrset[0].Header().Rrtype != rr.TypeCovered {
|
||||
return ErrRRset
|
||||
}
|
||||
|
||||
// RFC 4035 5.3.2. Reconstructing the Signed Data
|
||||
// Copy the sig, except the rrsig data
|
||||
sigwire := new(rrsigWireFmt)
|
||||
@ -373,8 +420,13 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
|
||||
|
||||
sigbuf := rr.sigBuf() // Get the binary signature data
|
||||
if rr.Algorithm == PRIVATEDNS { // PRIVATEOID
|
||||
// TODO(mg)
|
||||
// remove the domain name and assume its our
|
||||
// TODO(miek)
|
||||
// remove the domain name and assume its ours?
|
||||
}
|
||||
|
||||
hash, ok := AlgorithmToHash[rr.Algorithm]
|
||||
if !ok {
|
||||
return ErrAlg
|
||||
}
|
||||
|
||||
switch rr.Algorithm {
|
||||
@ -384,57 +436,37 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
|
||||
if pubkey == nil {
|
||||
return ErrKey
|
||||
}
|
||||
// Setup the hash as defined for this alg.
|
||||
var h hash.Hash
|
||||
var ch crypto.Hash
|
||||
switch rr.Algorithm {
|
||||
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)
|
||||
|
||||
h := hash.New()
|
||||
h.Write(signeddata)
|
||||
return rsa.VerifyPKCS1v15(pubkey, hash, h.Sum(nil), sigbuf)
|
||||
|
||||
case ECDSAP256SHA256, ECDSAP384SHA384:
|
||||
pubkey := k.publicKeyCurve()
|
||||
pubkey := k.publicKeyECDSA()
|
||||
if pubkey == nil {
|
||||
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
|
||||
r := big.NewInt(0)
|
||||
r.SetBytes(sigbuf[:len(sigbuf)/2])
|
||||
s := big.NewInt(0)
|
||||
s.SetBytes(sigbuf[len(sigbuf)/2:])
|
||||
if ecdsa.Verify(pubkey, sighash, r, s) {
|
||||
r := new(big.Int).SetBytes(sigbuf[:len(sigbuf)/2])
|
||||
s := new(big.Int).SetBytes(sigbuf[len(sigbuf)/2:])
|
||||
|
||||
h := hash.New()
|
||||
h.Write(signeddata)
|
||||
if ecdsa.Verify(pubkey, h.Sum(nil), r, s) {
|
||||
return nil
|
||||
}
|
||||
return ErrSig
|
||||
|
||||
default:
|
||||
return ErrAlg
|
||||
}
|
||||
// Unknown alg
|
||||
return ErrAlg
|
||||
}
|
||||
|
||||
// ValidityPeriod uses RFC1982 serial arithmetic to calculate
|
||||
// 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 {
|
||||
var utc int64
|
||||
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.
|
||||
func (s *RRSIG) sigBuf() []byte {
|
||||
sigbuf, err := fromBase64([]byte(s.Signature))
|
||||
func (rr *RRSIG) sigBuf() []byte {
|
||||
sigbuf, err := fromBase64([]byte(rr.Signature))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
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.
|
||||
func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey {
|
||||
keybuf, err := fromBase64([]byte(k.PublicKey))
|
||||
@ -521,8 +528,8 @@ func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey {
|
||||
return pubkey
|
||||
}
|
||||
|
||||
// publicKeyCurve returns the Curve public key from the DNSKEY record.
|
||||
func (k *DNSKEY) publicKeyCurve() *ecdsa.PublicKey {
|
||||
// publicKeyECDSA returns the Curve public key from the DNSKEY record.
|
||||
func (k *DNSKEY) publicKeyECDSA() *ecdsa.PublicKey {
|
||||
keybuf, err := fromBase64([]byte(k.PublicKey))
|
||||
if err != nil {
|
||||
return nil
|
||||
@ -573,81 +580,6 @@ func (k *DNSKEY) publicKeyDSA() *dsa.PublicKey {
|
||||
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
|
||||
|
||||
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,
|
||||
// HINFO, MINFO, MX, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX,
|
||||
// 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) {
|
||||
case *NS:
|
||||
x.Ns = strings.ToLower(x.Ns)
|
||||
@ -716,41 +654,11 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
|
||||
wires[i] = wire
|
||||
}
|
||||
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...)
|
||||
}
|
||||
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
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/dsa"
|
||||
"crypto/ecdsa"
|
||||
"crypto/rsa"
|
||||
"io"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"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
|
||||
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
|
||||
// only used in error reporting.
|
||||
// The public key must be
|
||||
// known, because some cryptographic algorithms embed the public inside the privatekey.
|
||||
func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (PrivateKey, error) {
|
||||
// The public key must be known, because some cryptographic algorithms embed
|
||||
// the public inside the privatekey.
|
||||
func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, error) {
|
||||
m, e := parseKey(q, file)
|
||||
if m == nil {
|
||||
return nil, e
|
||||
@ -32,57 +36,63 @@ func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (PrivateKey, error) {
|
||||
return nil, ErrPrivKey
|
||||
}
|
||||
// TODO(mg): check if the pubkey matches the private key
|
||||
switch m["algorithm"] {
|
||||
case "3 (DSA)":
|
||||
p, e := readPrivateKeyDSA(m)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
if !k.setPublicKeyInPrivate(p) {
|
||||
return nil, ErrKey
|
||||
}
|
||||
return p, e
|
||||
case "1 (RSAMD5)":
|
||||
fallthrough
|
||||
case "5 (RSASHA1)":
|
||||
fallthrough
|
||||
case "7 (RSASHA1NSEC3SHA1)":
|
||||
fallthrough
|
||||
case "8 (RSASHA256)":
|
||||
fallthrough
|
||||
case "10 (RSASHA512)":
|
||||
p, e := readPrivateKeyRSA(m)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
if !k.setPublicKeyInPrivate(p) {
|
||||
return nil, ErrKey
|
||||
}
|
||||
return p, e
|
||||
case "12 (ECC-GOST)":
|
||||
p, e := readPrivateKeyGOST(m)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
// setPublicKeyInPrivate(p)
|
||||
return p, e
|
||||
case "13 (ECDSAP256SHA256)":
|
||||
fallthrough
|
||||
case "14 (ECDSAP384SHA384)":
|
||||
p, e := readPrivateKeyECDSA(m)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
if !k.setPublicKeyInPrivate(p) {
|
||||
return nil, ErrKey
|
||||
}
|
||||
return p, e
|
||||
algo, err := strconv.Atoi(strings.SplitN(m["algorithm"], " ", 2)[0])
|
||||
if err != nil {
|
||||
return nil, ErrPrivKey
|
||||
}
|
||||
switch uint8(algo) {
|
||||
case DSA:
|
||||
priv, e := readPrivateKeyDSA(m)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
pub := k.publicKeyDSA()
|
||||
if pub == nil {
|
||||
return nil, ErrKey
|
||||
}
|
||||
priv.PublicKey = *pub
|
||||
return priv, e
|
||||
case RSAMD5:
|
||||
fallthrough
|
||||
case RSASHA1:
|
||||
fallthrough
|
||||
case RSASHA1NSEC3SHA1:
|
||||
fallthrough
|
||||
case RSASHA256:
|
||||
fallthrough
|
||||
case RSASHA512:
|
||||
priv, e := readPrivateKeyRSA(m)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
pub := k.publicKeyRSA()
|
||||
if pub == nil {
|
||||
return nil, ErrKey
|
||||
}
|
||||
priv.PublicKey = *pub
|
||||
return priv, e
|
||||
case ECCGOST:
|
||||
return nil, ErrPrivKey
|
||||
case ECDSAP256SHA256:
|
||||
fallthrough
|
||||
case ECDSAP384SHA384:
|
||||
priv, e := readPrivateKeyECDSA(m)
|
||||
if e != nil {
|
||||
return nil, 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.
|
||||
func readPrivateKeyRSA(m map[string]string) (PrivateKey, error) {
|
||||
func readPrivateKeyRSA(m map[string]string) (*rsa.PrivateKey, error) {
|
||||
p := new(rsa.PrivateKey)
|
||||
p.Primes = []*big.Int{nil, nil}
|
||||
for k, v := range m {
|
||||
@ -119,7 +129,7 @@ func readPrivateKeyRSA(m map[string]string) (PrivateKey, error) {
|
||||
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.X = big.NewInt(0)
|
||||
for k, v := range m {
|
||||
@ -137,7 +147,7 @@ func readPrivateKeyDSA(m map[string]string) (PrivateKey, error) {
|
||||
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.D = big.NewInt(0)
|
||||
// TODO: validate that the required flags are present
|
||||
@ -156,11 +166,6 @@ func readPrivateKeyECDSA(m map[string]string) (PrivateKey, error) {
|
||||
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,
|
||||
// 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) {
|
||||
@ -173,9 +178,9 @@ func parseKey(r io.Reader, file string) (map[string]string, error) {
|
||||
for l := range c {
|
||||
// It should alternate
|
||||
switch l.value {
|
||||
case _KEY:
|
||||
case zKey:
|
||||
k = l.token
|
||||
case _VALUE:
|
||||
case zValue:
|
||||
if k == "" {
|
||||
return nil, &ParseError{file, "no private key seen", l}
|
||||
}
|
||||
@ -205,14 +210,14 @@ func klexer(s *scan, c chan lex) {
|
||||
}
|
||||
l.token = str
|
||||
if key {
|
||||
l.value = _KEY
|
||||
l.value = zKey
|
||||
c <- l
|
||||
// Next token is a space, eat it
|
||||
s.tokenText()
|
||||
key = false
|
||||
str = ""
|
||||
} else {
|
||||
l.value = _VALUE
|
||||
l.value = zValue
|
||||
}
|
||||
case ';':
|
||||
commt = true
|
||||
@ -221,7 +226,7 @@ func klexer(s *scan, c chan lex) {
|
||||
// Reset a comment
|
||||
commt = false
|
||||
}
|
||||
l.value = _VALUE
|
||||
l.value = zValue
|
||||
l.token = str
|
||||
c <- l
|
||||
str = ""
|
||||
@ -238,7 +243,7 @@ func klexer(s *scan, c chan lex) {
|
||||
if len(str) > 0 {
|
||||
// Send remainder
|
||||
l.token = str
|
||||
l.value = _VALUE
|
||||
l.value = zValue
|
||||
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
|
||||
|
||||
import (
|
||||
@ -44,18 +18,18 @@ const (
|
||||
EDNS0SUBNET = 0x8 // client-subnet (RFC6891)
|
||||
EDNS0EXPIRE = 0x9 // EDNS0 expire
|
||||
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
|
||||
)
|
||||
|
||||
// OPT is the EDNS0 RR appended to messages to convey extra (meta) information.
|
||||
// See RFC 6891.
|
||||
type OPT struct {
|
||||
Hdr RR_Header
|
||||
Option []EDNS0 `dns:"opt"`
|
||||
}
|
||||
|
||||
func (rr *OPT) Header() *RR_Header {
|
||||
return &rr.Hdr
|
||||
}
|
||||
|
||||
func (rr *OPT) String() string {
|
||||
s := "\n;; OPT PSEUDOSECTION:\n; EDNS: version " + strconv.Itoa(int(rr.Version())) + "; "
|
||||
if rr.Do() {
|
||||
@ -92,6 +66,8 @@ func (rr *OPT) String() string {
|
||||
s += "\n; DS HASH UNDERSTOOD: " + o.String()
|
||||
case *EDNS0_N3U:
|
||||
s += "\n; NSEC3 HASH UNDERSTOOD: " + o.String()
|
||||
case *EDNS0_LOCAL:
|
||||
s += "\n; LOCAL OPT: " + o.String()
|
||||
}
|
||||
}
|
||||
return s
|
||||
@ -100,16 +76,13 @@ func (rr *OPT) String() string {
|
||||
func (rr *OPT) len() int {
|
||||
l := rr.Hdr.len()
|
||||
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()
|
||||
l += 2 + len(lo)
|
||||
l += len(lo)
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
func (rr *OPT) copy() RR {
|
||||
return &OPT{*rr.Hdr.copyHeader(), rr.Option}
|
||||
}
|
||||
|
||||
// return the old value -> delete SetVersion?
|
||||
|
||||
// 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) 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
|
||||
// answer depending on the location or network topology.
|
||||
// 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("2001:7b8:32a::2") // for IPV6
|
||||
// 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 {
|
||||
Code uint16 // Always EDNS0SUBNET
|
||||
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 {
|
||||
return nil, errors.New("dns: bad netmask")
|
||||
}
|
||||
ip := make([]byte, net.IPv4len)
|
||||
a := e.Address.To4().Mask(net.CIDRMask(int(e.SourceNetmask), net.IPv4len*8))
|
||||
for i := 0; i < net.IPv4len; i++ {
|
||||
if i+1 > len(e.Address) {
|
||||
break
|
||||
}
|
||||
ip[i] = a[i]
|
||||
if len(e.Address.To4()) != net.IPv4len {
|
||||
return nil, errors.New("dns: bad address")
|
||||
}
|
||||
needLength := e.SourceNetmask / 8
|
||||
if e.SourceNetmask%8 > 0 {
|
||||
needLength++
|
||||
}
|
||||
ip = ip[:needLength]
|
||||
b = append(b, ip...)
|
||||
ip := e.Address.To4().Mask(net.CIDRMask(int(e.SourceNetmask), net.IPv4len*8))
|
||||
needLength := (e.SourceNetmask + 8 - 1) / 8 // division rounding up
|
||||
b = append(b, ip[:needLength]...)
|
||||
case 2:
|
||||
if e.SourceNetmask > net.IPv6len*8 {
|
||||
return nil, errors.New("dns: bad netmask")
|
||||
}
|
||||
ip := make([]byte, net.IPv6len)
|
||||
a := e.Address.Mask(net.CIDRMask(int(e.SourceNetmask), net.IPv6len*8))
|
||||
for i := 0; i < net.IPv6len; i++ {
|
||||
if i+1 > len(e.Address) {
|
||||
break
|
||||
}
|
||||
ip[i] = a[i]
|
||||
if len(e.Address) != net.IPv6len {
|
||||
return nil, errors.New("dns: bad address")
|
||||
}
|
||||
needLength := e.SourceNetmask / 8
|
||||
if e.SourceNetmask%8 > 0 {
|
||||
needLength++
|
||||
}
|
||||
ip = ip[:needLength]
|
||||
b = append(b, ip...)
|
||||
ip := e.Address.Mask(net.CIDRMask(int(e.SourceNetmask), net.IPv6len*8))
|
||||
needLength := (e.SourceNetmask + 8 - 1) / 8 // division rounding up
|
||||
b = append(b, ip[:needLength]...)
|
||||
default:
|
||||
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 {
|
||||
lb := len(b)
|
||||
if lb < 4 {
|
||||
if len(b) < 4 {
|
||||
return ErrBuf
|
||||
}
|
||||
e.Family, _ = unpackUint16(b, 0)
|
||||
@ -285,25 +246,27 @@ func (e *EDNS0_SUBNET) unpack(b []byte) error {
|
||||
e.SourceScope = b[3]
|
||||
switch e.Family {
|
||||
case 1:
|
||||
addr := make([]byte, 4)
|
||||
for i := 0; i < int(e.SourceNetmask/8); i++ {
|
||||
if i >= len(addr) || 4+i >= len(b) {
|
||||
return ErrBuf
|
||||
}
|
||||
if e.SourceNetmask > net.IPv4len*8 || e.SourceScope > net.IPv4len*8 {
|
||||
return errors.New("dns: bad netmask")
|
||||
}
|
||||
addr := make([]byte, net.IPv4len)
|
||||
for i := 0; i < net.IPv4len && 4+i < len(b); i++ {
|
||||
addr[i] = b[4+i]
|
||||
}
|
||||
e.Address = net.IPv4(addr[0], addr[1], addr[2], addr[3])
|
||||
case 2:
|
||||
addr := make([]byte, 16)
|
||||
for i := 0; i < int(e.SourceNetmask/8); i++ {
|
||||
if i >= len(addr) || 4+i >= len(b) {
|
||||
return ErrBuf
|
||||
}
|
||||
if e.SourceNetmask > net.IPv6len*8 || e.SourceScope > net.IPv6len*8 {
|
||||
return errors.New("dns: bad netmask")
|
||||
}
|
||||
addr := make([]byte, net.IPv6len)
|
||||
for i := 0; i < net.IPv6len && 4+i < len(b); i++ {
|
||||
addr[i] = b[4+i]
|
||||
}
|
||||
e.Address = net.IP{addr[0], addr[1], addr[2], addr[3], addr[4],
|
||||
addr[5], addr[6], addr[7], addr[8], addr[9], addr[10],
|
||||
addr[11], addr[12], addr[13], addr[14], addr[15]}
|
||||
default:
|
||||
return errors.New("dns: bad address family")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -320,7 +283,7 @@ func (e *EDNS0_SUBNET) String() (s string) {
|
||||
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
|
||||
// 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
|
||||
@ -358,7 +321,7 @@ func (e *EDNS0_UL) unpack(b []byte) error {
|
||||
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.
|
||||
type EDNS0_LLQ struct {
|
||||
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])
|
||||
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.
|
||||
// www.miek.nl. returns []string{"www", "miek", "nl"}
|
||||
// .www.miek.nl. returns []string{"", "www", "miek", "nl"},
|
||||
// The root label (.) returns nil. Note that using
|
||||
// strings.Split(s) will work in most cases, but does not handle
|
||||
// escaped dots (\.) for instance.
|
||||
// s must be a syntactically valid domain name, see IsDomainName.
|
||||
func SplitDomainName(s string) (labels []string) {
|
||||
if len(s) == 0 {
|
||||
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 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) {
|
||||
s1 = Fqdn(s1)
|
||||
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.
|
||||
// s must be a syntactically valid domain name.
|
||||
func CountLabel(s string) (labels int) {
|
||||
if s == "." {
|
||||
return
|
||||
@ -98,12 +103,12 @@ func CountLabel(s string) (labels int) {
|
||||
return
|
||||
}
|
||||
}
|
||||
panic("dns: not reached")
|
||||
}
|
||||
|
||||
// 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}.
|
||||
// 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 {
|
||||
if s == "." {
|
||||
return nil
|
||||
@ -119,12 +124,12 @@ func Split(s string) []int {
|
||||
}
|
||||
idx = append(idx, off)
|
||||
}
|
||||
panic("dns: not reached")
|
||||
}
|
||||
|
||||
// NextLabel returns the index of the start of the next label in the
|
||||
// string s starting at offset.
|
||||
// The bool end is true when the end of the string has been reached.
|
||||
// Also see PrevLabel.
|
||||
func NextLabel(s string, offset int) (i int, end bool) {
|
||||
quote := false
|
||||
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
|
||||
// jumping n labels to the left.
|
||||
// The bool start is true when the start of the string has been overshot.
|
||||
// Also see NextLabel.
|
||||
func PrevLabel(s string, n int) (i int, start bool) {
|
||||
if n == 0 {
|
||||
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
|
||||
|
||||
var (
|
||||
ErrAlg error = &Error{err: "bad algorithm"}
|
||||
ErrAuth error = &Error{err: "bad authentication"}
|
||||
ErrBuf error = &Error{err: "buffer size too small"}
|
||||
ErrConnEmpty error = &Error{err: "conn has no connection"}
|
||||
ErrConn error = &Error{err: "conn holds both UDP and TCP connection"}
|
||||
// ErrAlg indicates an error with the (DNSSEC) algorithm.
|
||||
ErrAlg error = &Error{err: "bad algorithm"}
|
||||
// ErrAuth indicates an error in the TSIG authentication.
|
||||
ErrAuth error = &Error{err: "bad authentication"}
|
||||
// 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"}
|
||||
ErrFqdn error = &Error{err: "domain must be fully qualified"}
|
||||
ErrId error = &Error{err: "id mismatch"}
|
||||
ErrKeyAlg error = &Error{err: "bad key algorithm"}
|
||||
ErrKey error = &Error{err: "bad key"}
|
||||
ErrKeySize error = &Error{err: "bad key size"}
|
||||
ErrNoSig error = &Error{err: "no signature found"}
|
||||
ErrPrivKey error = &Error{err: "bad private key"}
|
||||
ErrRcode error = &Error{err: "bad rcode"}
|
||||
ErrRdata error = &Error{err: "bad rdata"}
|
||||
ErrRRset error = &Error{err: "bad rrset"}
|
||||
ErrSecret error = &Error{err: "no secrets defined"}
|
||||
ErrServ error = &Error{err: "no servers could be reached"}
|
||||
ErrShortRead error = &Error{err: "short read"}
|
||||
ErrSig error = &Error{err: "bad signature"}
|
||||
ErrSigGen error = &Error{err: "bad signature generation"}
|
||||
ErrSoa error = &Error{err: "no SOA"}
|
||||
ErrTime error = &Error{err: "bad time"}
|
||||
// ErrFqdn indicates that a domain name does not have a closing dot.
|
||||
ErrFqdn error = &Error{err: "domain must be fully qualified"}
|
||||
// ErrId indicates there is a mismatch with the message's ID.
|
||||
ErrId error = &Error{err: "id mismatch"}
|
||||
// ErrKeyAlg indicates that the algorithm in the key is not valid.
|
||||
ErrKeyAlg error = &Error{err: "bad key algorithm"}
|
||||
ErrKey error = &Error{err: "bad key"}
|
||||
ErrKeySize error = &Error{err: "bad key size"}
|
||||
ErrNoSig error = &Error{err: "no signature found"}
|
||||
ErrPrivKey error = &Error{err: "bad private key"}
|
||||
ErrRcode error = &Error{err: "bad rcode"}
|
||||
ErrRdata error = &Error{err: "bad rdata"}
|
||||
ErrRRset error = &Error{err: "bad rrset"}
|
||||
ErrSecret error = &Error{err: "no secrets defined"}
|
||||
ErrShortRead error = &Error{err: "short read"}
|
||||
// ErrSig indicates that a signature can not be cryptographically validated.
|
||||
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
|
||||
@ -56,8 +67,7 @@ var (
|
||||
// dns.Id = func() uint16 { return 3 }
|
||||
var Id func() uint16 = id
|
||||
|
||||
// A manually-unpacked version of (id, bits).
|
||||
// This is in its own struct for easy printing.
|
||||
// MsgHdr is a a manually-unpacked version of (id, bits).
|
||||
type MsgHdr struct {
|
||||
Id uint16
|
||||
Response bool
|
||||
@ -72,7 +82,7 @@ type MsgHdr struct {
|
||||
Rcode int
|
||||
}
|
||||
|
||||
// The layout of a DNS message.
|
||||
// Msg contains the layout of a DNS message.
|
||||
type Msg struct {
|
||||
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.
|
||||
@ -82,87 +92,10 @@ type Msg struct {
|
||||
Extra []RR // Holds the RR(s) of the additional section.
|
||||
}
|
||||
|
||||
// Map of strings for each RR wire type.
|
||||
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.
|
||||
// StringToType is the reverse of TypeToString, needed for string parsing.
|
||||
var StringToType = reverseInt16(TypeToString)
|
||||
|
||||
// StringToClass is the reverse of ClassToString, needed for string parsing.
|
||||
var StringToClass = reverseInt16(ClassToString)
|
||||
|
||||
// Map of opcodes strings.
|
||||
@ -171,7 +104,7 @@ var StringToOpcode = reverseInt(OpcodeToString)
|
||||
// Map of rcodes strings.
|
||||
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{
|
||||
ClassINET: "IN",
|
||||
ClassCSNET: "CS",
|
||||
@ -181,7 +114,7 @@ var ClassToString = map[uint16]string{
|
||||
ClassANY: "ANY",
|
||||
}
|
||||
|
||||
// Map of strings for opcodes.
|
||||
// OpcodeToString maps Opcodes to strings.
|
||||
var OpcodeToString = map[int]string{
|
||||
OpcodeQuery: "QUERY",
|
||||
OpcodeIQuery: "IQUERY",
|
||||
@ -190,7 +123,7 @@ var OpcodeToString = map[int]string{
|
||||
OpcodeUpdate: "UPDATE",
|
||||
}
|
||||
|
||||
// Map of strings for rcodes.
|
||||
// RcodeToString maps Rcodes to strings.
|
||||
var RcodeToString = map[int]string{
|
||||
RcodeSuccess: "NOERROR",
|
||||
RcodeFormatError: "FORMERR",
|
||||
@ -225,7 +158,7 @@ var RcodeToString = map[int]string{
|
||||
// PackDomainName packs a domain name s into msg[off:].
|
||||
// If compression is wanted compress must be true and the compression
|
||||
// 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) {
|
||||
off1, _, err = packDomainName(s, msg, off, compression, compress)
|
||||
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.
|
||||
begin := 0
|
||||
bs := []byte(s)
|
||||
ro_bs, bs_fresh, escaped_dot := s, true, false
|
||||
roBs, bsFresh, escapedDot := s, true, false
|
||||
for i := 0; i < ls; i++ {
|
||||
if bs[i] == '\\' {
|
||||
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' {
|
||||
bs[i] = '\n'
|
||||
}
|
||||
escaped_dot = bs[i] == '.'
|
||||
bs_fresh = false
|
||||
escapedDot = bs[i] == '.'
|
||||
bsFresh = false
|
||||
continue
|
||||
}
|
||||
|
||||
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
|
||||
return lenmsg, labels, ErrRdata
|
||||
}
|
||||
@ -320,16 +253,16 @@ func packDomainName(s string, msg []byte, off int, compression map[string]int, c
|
||||
}
|
||||
off++
|
||||
}
|
||||
if compress && !bs_fresh {
|
||||
ro_bs = string(bs)
|
||||
bs_fresh = true
|
||||
if compress && !bsFresh {
|
||||
roBs = string(bs)
|
||||
bsFresh = true
|
||||
}
|
||||
// Dont try to compress '.'
|
||||
if compress && ro_bs[begin:] != "." {
|
||||
if p, ok := compression[ro_bs[begin:]]; !ok {
|
||||
// Don't try to compress '.'
|
||||
if compress && roBs[begin:] != "." {
|
||||
if p, ok := compression[roBs[begin:]]; !ok {
|
||||
// Only offsets smaller than this can be used.
|
||||
if offset < maxCompressionOffset {
|
||||
compression[ro_bs[begin:]] = offset
|
||||
compression[roBs[begin:]] = offset
|
||||
}
|
||||
} else {
|
||||
// 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++
|
||||
begin = i + 1
|
||||
}
|
||||
escaped_dot = false
|
||||
escapedDot = false
|
||||
}
|
||||
// Root label is special
|
||||
if len(bs) == 1 && bs[0] == '.' {
|
||||
@ -401,9 +334,6 @@ Loop:
|
||||
case 0x00:
|
||||
if c == 0x00 {
|
||||
// end of name
|
||||
if len(s) == 0 {
|
||||
return ".", off, nil
|
||||
}
|
||||
break Loop
|
||||
}
|
||||
// literal string
|
||||
@ -464,6 +394,9 @@ Loop:
|
||||
if ptr == 0 {
|
||||
off1 = off
|
||||
}
|
||||
if len(s) == 0 {
|
||||
s = []byte(".")
|
||||
}
|
||||
return string(s), off1, nil
|
||||
}
|
||||
|
||||
@ -531,17 +464,46 @@ func packTxtString(s string, msg []byte, offset int, tmp []byte) (int, error) {
|
||||
return offset, nil
|
||||
}
|
||||
|
||||
func unpackTxt(msg []byte, offset, rdend int) ([]string, int, error) {
|
||||
var err error
|
||||
var ss []string
|
||||
func packOctetString(s string, msg []byte, offset int, tmp []byte) (int, error) {
|
||||
if offset >= len(msg) {
|
||||
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
|
||||
for offset < rdend && err == nil {
|
||||
s, offset, err = unpackTxtString(msg, offset)
|
||||
for off < len(msg) && err == nil {
|
||||
s, off, err = unpackTxtString(msg, off)
|
||||
if err == nil {
|
||||
ss = append(ss, s)
|
||||
}
|
||||
}
|
||||
return ss, offset, err
|
||||
return
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
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
|
||||
// only the first 4
|
||||
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"}
|
||||
}
|
||||
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 {
|
||||
break
|
||||
}
|
||||
@ -694,58 +668,49 @@ func packStructValue(val reflect.Value, msg []byte, off int, compression map[str
|
||||
if val.Field(i).Len() == 0 {
|
||||
break
|
||||
}
|
||||
var bitmapbyte uint16
|
||||
off1 := off
|
||||
for j := 0; j < val.Field(i).Len(); j++ {
|
||||
serv := uint16((fv.Index(j).Uint()))
|
||||
bitmapbyte = uint16(serv / 8)
|
||||
if int(bitmapbyte) > lenmsg {
|
||||
return lenmsg, &Error{err: "overflow packing wks"}
|
||||
serv := int(fv.Index(j).Uint())
|
||||
if off+serv/8+1 > len(msg) {
|
||||
return len(msg), &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
|
||||
// This is the uint16 type bitmap
|
||||
if val.Field(i).Len() == 0 {
|
||||
// Do absolutely nothing
|
||||
break
|
||||
}
|
||||
|
||||
lastwindow := uint16(0)
|
||||
length := uint16(0)
|
||||
if off+2 > lenmsg {
|
||||
return lenmsg, &Error{err: "overflow packing nsecx"}
|
||||
}
|
||||
var lastwindow, lastlength uint16
|
||||
for j := 0; j < val.Field(i).Len(); j++ {
|
||||
t := uint16((fv.Index(j).Uint()))
|
||||
window := uint16(t / 256)
|
||||
if lastwindow != window {
|
||||
t := uint16(fv.Index(j).Uint())
|
||||
window := t / 256
|
||||
length := (t-window*256)/8 + 1
|
||||
if window > lastwindow && lastlength != 0 {
|
||||
// New window, jump to the new offset
|
||||
off += int(length) + 3
|
||||
if off > lenmsg {
|
||||
return lenmsg, &Error{err: "overflow packing nsecx bitmap"}
|
||||
}
|
||||
off += int(lastlength) + 2
|
||||
lastlength = 0
|
||||
}
|
||||
length = (t - window*256) / 8
|
||||
bit := t - (window * 256) - (length * 8)
|
||||
if off+2+int(length) > lenmsg {
|
||||
return lenmsg, &Error{err: "overflow packing nsecx bitmap"}
|
||||
if window < lastwindow || length < lastlength {
|
||||
return len(msg), &Error{err: "nsec bits out of order"}
|
||||
}
|
||||
if off+2+int(length) > len(msg) {
|
||||
return len(msg), &Error{err: "overflow packing nsec"}
|
||||
}
|
||||
|
||||
// Setting the window #
|
||||
msg[off] = byte(window)
|
||||
// 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
|
||||
msg[off+2+int(length)] |= byte(1 << (7 - bit))
|
||||
lastwindow = window
|
||||
}
|
||||
off += 2 + int(length)
|
||||
off++
|
||||
if off > lenmsg {
|
||||
return lenmsg, &Error{err: "overflow packing nsecx bitmap"}
|
||||
msg[off+1+int(length)] |= byte(1 << (7 - (t % 8)))
|
||||
lastwindow, lastlength = window, length
|
||||
}
|
||||
off += int(lastlength) + 2
|
||||
}
|
||||
case reflect.Struct:
|
||||
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)
|
||||
off += len(b64)
|
||||
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 {
|
||||
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)
|
||||
copy(msg[off:off+len(s)], 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"`:
|
||||
fallthrough
|
||||
case "":
|
||||
@ -890,17 +868,11 @@ func packStructCompress(any interface{}, msg []byte, off int, compression map[st
|
||||
return off, err
|
||||
}
|
||||
|
||||
// TODO(miek): Fix use of rdlength here
|
||||
|
||||
// Unpack a reflect.StructValue from msg.
|
||||
// Same restrictions as packStructValue.
|
||||
func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err error) {
|
||||
var lenrd int
|
||||
lenmsg := len(msg)
|
||||
for i := 0; i < val.NumField(); i++ {
|
||||
if lenrd != 0 && lenrd == off {
|
||||
break
|
||||
}
|
||||
if off > lenmsg {
|
||||
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
|
||||
switch data := fv.Interface().(type) {
|
||||
case PrivateRdata:
|
||||
n, err := data.Unpack(msg[off:lenrd])
|
||||
n, err := data.Unpack(msg[off:])
|
||||
if err != nil {
|
||||
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")}
|
||||
case `dns:"domain-name"`:
|
||||
// HIP record slice of name (or none)
|
||||
servers := make([]string, 0)
|
||||
var servers []string
|
||||
var s string
|
||||
for off < lenrd {
|
||||
for off < lenmsg {
|
||||
s, off, err = UnpackDomainName(msg, off)
|
||||
if err != nil {
|
||||
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))
|
||||
case `dns:"txt"`:
|
||||
if off == lenmsg || lenrd == off {
|
||||
if off == lenmsg {
|
||||
break
|
||||
}
|
||||
var txt []string
|
||||
txt, off, err = unpackTxt(msg, off, lenrd)
|
||||
txt, off, err = unpackTxt(msg, off)
|
||||
if err != nil {
|
||||
return lenmsg, err
|
||||
}
|
||||
fv.Set(reflect.ValueOf(txt))
|
||||
case `dns:"opt"`: // edns0
|
||||
if off == lenrd {
|
||||
if off == lenmsg {
|
||||
// This is an EDNS0 (OPT Record) with no rdata
|
||||
// We can safely return here.
|
||||
break
|
||||
}
|
||||
edns := make([]EDNS0, 0)
|
||||
var edns []EDNS0
|
||||
Option:
|
||||
code := uint16(0)
|
||||
if off+2 > lenmsg {
|
||||
if off+4 > lenmsg {
|
||||
return lenmsg, &Error{err: "overflow unpacking opt"}
|
||||
}
|
||||
code, off = 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"}
|
||||
}
|
||||
switch code {
|
||||
@ -1017,27 +989,44 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err er
|
||||
edns = append(edns, e)
|
||||
off = off1 + int(optlen)
|
||||
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)
|
||||
}
|
||||
if off < lenrd {
|
||||
if off < lenmsg {
|
||||
goto Option
|
||||
}
|
||||
fv.Set(reflect.ValueOf(edns))
|
||||
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
|
||||
}
|
||||
if off+net.IPv4len > lenrd || off+net.IPv4len > lenmsg {
|
||||
if off+net.IPv4len > lenmsg {
|
||||
return lenmsg, &Error{err: "overflow unpacking a"}
|
||||
}
|
||||
fv.Set(reflect.ValueOf(net.IPv4(msg[off], msg[off+1], msg[off+2], msg[off+3])))
|
||||
off += net.IPv4len
|
||||
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
|
||||
}
|
||||
if off+net.IPv6len > lenrd || off+net.IPv6len > lenmsg {
|
||||
if off+net.IPv6len > lenmsg {
|
||||
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],
|
||||
@ -1046,9 +1035,9 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err er
|
||||
off += net.IPv6len
|
||||
case `dns:"wks"`:
|
||||
// Rest of the record is the bitmap
|
||||
serv := make([]uint16, 0)
|
||||
var serv []uint16
|
||||
j := 0
|
||||
for off < lenrd {
|
||||
for off < lenmsg {
|
||||
if off+1 > lenmsg {
|
||||
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))
|
||||
case `dns:"nsec"`: // NSEC/NSEC3
|
||||
if off == lenrd {
|
||||
if off == len(msg) {
|
||||
break
|
||||
}
|
||||
// Rest of the record is the type bitmap
|
||||
if off+2 > lenrd || off+2 > lenmsg {
|
||||
return lenmsg, &Error{err: "overflow unpacking nsecx"}
|
||||
}
|
||||
nsec := make([]uint16, 0)
|
||||
var nsec []uint16
|
||||
length := 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])
|
||||
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 {
|
||||
// A length window of zero is strange. If there
|
||||
// the window should not have been specified. Bail out
|
||||
// println("dns: length == 0 when unpacking NSEC")
|
||||
return lenmsg, &Error{err: "overflow unpacking nsecx"}
|
||||
// RFC 4034: Blocks with no types present MUST NOT be included.
|
||||
return len(msg), &Error{err: "empty NSEC block"}
|
||||
}
|
||||
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...
|
||||
off += 2
|
||||
// Walk the bytes in the window and extract the type bits
|
||||
for j := 0; j < length; j++ {
|
||||
if off+j+1 > lenmsg {
|
||||
return lenmsg, &Error{err: "overflow unpacking nsecx"}
|
||||
}
|
||||
b := msg[off+j]
|
||||
// Check the bits one by one, and set the type
|
||||
if b&0x80 == 0x80 {
|
||||
@ -1141,6 +1133,7 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err er
|
||||
}
|
||||
}
|
||||
off += length
|
||||
lastwindow = window
|
||||
}
|
||||
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
|
||||
}
|
||||
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:
|
||||
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])))
|
||||
off += 4
|
||||
case reflect.Uint64:
|
||||
if off == lenmsg {
|
||||
break
|
||||
}
|
||||
switch val.Type().Field(i).Tag {
|
||||
default:
|
||||
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 {
|
||||
default:
|
||||
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"`:
|
||||
hexend := lenrd
|
||||
hexend := lenmsg
|
||||
if val.FieldByName("Hdr").FieldByName("Rrtype").Uint() == uint64(TypeHIP) {
|
||||
hexend = off + int(val.FieldByName("HitLength").Uint())
|
||||
}
|
||||
if hexend > lenrd || hexend > lenmsg {
|
||||
return lenmsg, &Error{err: "overflow unpacking hex"}
|
||||
if hexend > lenmsg {
|
||||
return lenmsg, &Error{err: "overflow unpacking HIP hex"}
|
||||
}
|
||||
s = hex.EncodeToString(msg[off:hexend])
|
||||
off = hexend
|
||||
case `dns:"base64"`:
|
||||
// Rest of the RR is base64 encoded value
|
||||
b64end := lenrd
|
||||
b64end := lenmsg
|
||||
if val.FieldByName("Hdr").FieldByName("Rrtype").Uint() == uint64(TypeHIP) {
|
||||
b64end = off + int(val.FieldByName("PublicKeyLength").Uint())
|
||||
}
|
||||
if b64end > lenrd || b64end > lenmsg {
|
||||
return lenmsg, &Error{err: "overflow unpacking base64"}
|
||||
if b64end > lenmsg {
|
||||
return lenmsg, &Error{err: "overflow unpacking HIP base64"}
|
||||
}
|
||||
s = toBase64(msg[off:b64end])
|
||||
off = b64end
|
||||
case `dns:"cdomain-name"`:
|
||||
fallthrough
|
||||
case `dns:"domain-name"`:
|
||||
if off == lenmsg {
|
||||
// zero rdata foo, OK for dyn. updates
|
||||
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 == lenmsg && int(val.FieldByName("Hdr").FieldByName("Rdlength").Uint()) == 0 {
|
||||
// zero rdata is ok for dyn updates, but only if rdlength is 0
|
||||
break
|
||||
}
|
||||
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)
|
||||
// make an rr of that type and re-unpack.
|
||||
mk, known := typeToRR[h.Rrtype]
|
||||
mk, known := TypeToRR[h.Rrtype]
|
||||
if !known {
|
||||
rr = new(RFC3597)
|
||||
} else {
|
||||
@ -1388,6 +1399,32 @@ func UnpackRR(msg []byte, off int) (rr RR, off1 int, err error) {
|
||||
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
|
||||
func reverseInt8(m map[uint8]string) 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.Rcode = int(dh.Bits & 0xF)
|
||||
|
||||
// Arrays.
|
||||
dns.Question = make([]Question, dh.Qdcount)
|
||||
dns.Answer = make([]RR, dh.Ancount)
|
||||
dns.Ns = make([]RR, dh.Nscount)
|
||||
dns.Extra = make([]RR, dh.Arcount)
|
||||
// Optimistically use the count given to us in the header
|
||||
dns.Question = make([]Question, 0, int(dh.Qdcount))
|
||||
|
||||
for i := 0; i < len(dns.Question); i++ {
|
||||
off, err = UnpackStruct(&dns.Question[i], msg, off)
|
||||
var q Question
|
||||
for i := 0; i < int(dh.Qdcount); i++ {
|
||||
off1 := off
|
||||
off, err = UnpackStruct(&q, msg, off)
|
||||
if err != nil {
|
||||
// Even if Truncated is set, we only will set ErrTruncated if we
|
||||
// actually got the questions
|
||||
return err
|
||||
}
|
||||
}
|
||||
// If we see a TC bit being set we return here, without
|
||||
// an error, because technically it isn't an error. So return
|
||||
// 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
|
||||
if off1 == off { // Offset does not increase anymore, dh.Qdcount is a lie!
|
||||
dh.Qdcount = uint16(i)
|
||||
break
|
||||
}
|
||||
dns.Question = append(dns.Question, q)
|
||||
}
|
||||
for i := 0; i < len(dns.Ns); i++ {
|
||||
dns.Ns[i], off, err = UnpackRR(msg, off)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dns.Answer, off, err = unpackRRslice(int(dh.Ancount), msg, off)
|
||||
// The header counts might have been wrong so we need to update it
|
||||
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++ {
|
||||
dns.Extra[i], off, err = UnpackRR(msg, off)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// The header counts might have been wrong so we need to update it
|
||||
dh.Nscount = uint16(len(dns.Ns))
|
||||
if err == nil {
|
||||
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) {
|
||||
// TODO(miek) make this an error?
|
||||
// use PackOpt to let people tell how detailed the error reporting should be?
|
||||
// println("dns: extra bytes in dns packet", off, "<", len(msg))
|
||||
} else if dns.Truncated {
|
||||
// Whether we ran into a an error or not, we want to return that it
|
||||
// was truncated
|
||||
err = ErrTruncated
|
||||
}
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
// Convert a complete message to a string with dig-like output.
|
||||
@ -1863,9 +1896,18 @@ func Copy(r RR) RR {
|
||||
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.
|
||||
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.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
|
||||
}
|
||||
|
||||
rrArr := make([]RR, len(dns.Answer)+len(dns.Ns)+len(dns.Extra))
|
||||
var rri int
|
||||
|
||||
if len(dns.Answer) > 0 {
|
||||
r1.Answer = make([]RR, len(dns.Answer))
|
||||
rrbegin := rri
|
||||
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 {
|
||||
r1.Ns = make([]RR, len(dns.Ns))
|
||||
rrbegin := rri
|
||||
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 {
|
||||
r1.Extra = make([]RR, len(dns.Extra))
|
||||
rrbegin := rri
|
||||
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
|
||||
|
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)
|
||||
}
|
||||
|
||||
// Denialer is an interface that should be implemented by types that are used to denial
|
||||
// answers in DNSSEC.
|
||||
type Denialer interface {
|
||||
// Cover will check if the (unhashed) name is being covered by this NSEC or NSEC3.
|
||||
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
|
||||
|
||||
import (
|
||||
@ -40,7 +33,7 @@ type PrivateRR struct {
|
||||
|
||||
func mkPrivateRR(rrtype uint16) *PrivateRR {
|
||||
// Panics if RR is not an instance of PrivateRR.
|
||||
rrfunc, ok := typeToRR[rrtype]
|
||||
rrfunc, ok := TypeToRR[rrtype]
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("dns: invalid operation with Private RR type %d", rrtype))
|
||||
}
|
||||
@ -50,11 +43,13 @@ func mkPrivateRR(rrtype uint16) *PrivateRR {
|
||||
case *PrivateRR:
|
||||
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) 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.
|
||||
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) {
|
||||
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
|
||||
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
|
||||
// be an issue (basically parsing TXT becomes hard)
|
||||
switch l = <-c; l.value {
|
||||
case _NEWLINE, _EOF:
|
||||
case zNewline, zEOF:
|
||||
break FETCH
|
||||
case _STRING:
|
||||
case zString:
|
||||
text = append(text, l.token)
|
||||
}
|
||||
}
|
||||
@ -113,7 +108,7 @@ func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata)
|
||||
func PrivateHandleRemove(rtype uint16) {
|
||||
rtypestr, ok := TypeToString[rtype]
|
||||
if ok {
|
||||
delete(typeToRR, rtype)
|
||||
delete(TypeToRR, rtype)
|
||||
delete(TypeToString, rtype)
|
||||
delete(typeToparserFunc, rtype)
|
||||
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
|
||||
}
|
||||
|
||||
// rawSetAnswerLen sets the lenght of the answer section.
|
||||
// rawSetAnswerLen sets the length of the answer section.
|
||||
func rawSetAnswerLen(msg []byte, i uint16) bool {
|
||||
if len(msg) < 8 {
|
||||
return false
|
||||
@ -30,7 +30,7 @@ func rawSetAnswerLen(msg []byte, i uint16) bool {
|
||||
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 {
|
||||
if len(msg) < 10 {
|
||||
return false
|
||||
@ -39,7 +39,7 @@ func rawSetNsLen(msg []byte, i uint16) bool {
|
||||
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 {
|
||||
if len(msg) < 12 {
|
||||
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 (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
"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 {
|
||||
ServeDNS(w ResponseWriter, r *Msg)
|
||||
}
|
||||
@ -43,9 +48,10 @@ type response struct {
|
||||
tsigRequestMAC string
|
||||
tsigSecret map[string]string // the tsig secrets
|
||||
udp *net.UDPConn // i/o connection if UDP was used
|
||||
tcp *net.TCPConn // i/o connection if TCP was used
|
||||
udpSession *sessionUDP // oob data to get egress interface right
|
||||
tcp net.Conn // i/o connection if TCP was used
|
||||
udpSession *SessionUDP // oob data to get egress interface right
|
||||
remoteAddr net.Addr // address of the client
|
||||
writer Writer // writer to output the raw DNS bits
|
||||
}
|
||||
|
||||
// ServeMux is an DNS request multiplexer. It matches the
|
||||
@ -72,12 +78,12 @@ var DefaultServeMux = NewServeMux()
|
||||
// Handler object that calls f.
|
||||
type HandlerFunc func(ResponseWriter, *Msg)
|
||||
|
||||
// ServerDNS calls f(w, r)
|
||||
// ServeDNS calls f(w, r).
|
||||
func (f HandlerFunc) ServeDNS(w ResponseWriter, r *Msg) {
|
||||
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) {
|
||||
m := new(Msg)
|
||||
m.SetRcode(r, RcodeServerFailure)
|
||||
@ -87,13 +93,35 @@ func HandleFailed(w ResponseWriter, r *Msg) {
|
||||
|
||||
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.
|
||||
func ListenAndServe(addr string, network string, handler Handler) error {
|
||||
server := &Server{Addr: addr, Net: network, Handler: handler}
|
||||
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,
|
||||
// l and p should not both be non-nil.
|
||||
// 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 t != TypeDS {
|
||||
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)
|
||||
if end {
|
||||
@ -148,7 +175,7 @@ func (mux *ServeMux) Handle(pattern string, handler Handler) {
|
||||
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)) {
|
||||
mux.Handle(pattern, HandlerFunc(handler))
|
||||
}
|
||||
@ -158,9 +185,9 @@ func (mux *ServeMux) HandleRemove(pattern string) {
|
||||
if pattern == "" {
|
||||
panic("dns: invalid pattern " + pattern)
|
||||
}
|
||||
// don't need a mutex here, because deleting is OK, even if the
|
||||
// entry is note there.
|
||||
mux.m.Lock()
|
||||
delete(mux.z, Fqdn(pattern))
|
||||
mux.m.Unlock()
|
||||
}
|
||||
|
||||
// ServeDNS dispatches the request to the handler whose
|
||||
@ -197,14 +224,53 @@ func HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) {
|
||||
DefaultServeMux.HandleFunc(pattern, handler)
|
||||
}
|
||||
|
||||
// Writer writes raw DNS messages; each call to Write should send an entire message.
|
||||
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.
|
||||
type Server struct {
|
||||
// Address to listen on, ":dns" if empty.
|
||||
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
|
||||
// TCP Listener to use, this is to aid in systemd's socket activation.
|
||||
Listener net.Listener
|
||||
// TLS connection configuration
|
||||
TLSConfig *tls.Config
|
||||
// UDP "Listener" to use, this is to aid in systemd's socket activation.
|
||||
PacketConn net.PacketConn
|
||||
// Handler to invoke, dns.DefaultServeMux if nil.
|
||||
@ -221,31 +287,30 @@ type Server struct {
|
||||
// Secret(s) for Tsig map[<zonename>]<base64 secret>.
|
||||
TsigSecret map[string]string
|
||||
// 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
|
||||
// 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()
|
||||
// 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.
|
||||
stopUDP chan bool
|
||||
stopTCP chan bool
|
||||
wgUDP sync.WaitGroup
|
||||
wgTCP sync.WaitGroup
|
||||
// Graceful shutdown handling
|
||||
|
||||
// make start/shutdown not racy
|
||||
lock sync.Mutex
|
||||
inFlight sync.WaitGroup
|
||||
|
||||
lock sync.RWMutex
|
||||
started bool
|
||||
}
|
||||
|
||||
// ListenAndServe starts a nameserver on the configured address in *Server.
|
||||
func (srv *Server) ListenAndServe() error {
|
||||
srv.lock.Lock()
|
||||
defer srv.lock.Unlock()
|
||||
if srv.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
|
||||
if addr == "" {
|
||||
addr = ":domain"
|
||||
@ -263,7 +328,30 @@ func (srv *Server) ListenAndServe() error {
|
||||
if e != nil {
|
||||
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":
|
||||
a, e := net.ResolveUDPAddr(srv.Net, addr)
|
||||
if e != nil {
|
||||
@ -276,7 +364,12 @@ func (srv *Server) ListenAndServe() error {
|
||||
if e := setUDPSocketOptions(l); e != nil {
|
||||
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"}
|
||||
}
|
||||
@ -285,71 +378,62 @@ func (srv *Server) ListenAndServe() error {
|
||||
// configured in *Server. Its main use is to start a server from systemd.
|
||||
func (srv *Server) ActivateAndServe() error {
|
||||
srv.lock.Lock()
|
||||
defer srv.lock.Unlock()
|
||||
if srv.started {
|
||||
return &Error{err: "server already started"}
|
||||
}
|
||||
srv.stopUDP, srv.stopTCP = make(chan bool), make(chan bool)
|
||||
srv.started = true
|
||||
srv.lock.Unlock()
|
||||
if srv.PacketConn != nil {
|
||||
pConn := srv.PacketConn
|
||||
l := srv.Listener
|
||||
if pConn != nil {
|
||||
if srv.UDPSize == 0 {
|
||||
srv.UDPSize = MinMsgSize
|
||||
}
|
||||
if t, ok := srv.PacketConn.(*net.UDPConn); ok {
|
||||
if t, ok := pConn.(*net.UDPConn); ok {
|
||||
if e := setUDPSocketOptions(t); e != nil {
|
||||
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 t, ok := srv.Listener.(*net.TCPListener); ok {
|
||||
return srv.serveTCP(t)
|
||||
}
|
||||
if l != nil {
|
||||
srv.started = true
|
||||
srv.lock.Unlock()
|
||||
e := srv.serveTCP(l)
|
||||
srv.lock.Lock() // to satisfy the defer at the top
|
||||
return e
|
||||
}
|
||||
return &Error{err: "bad listeners"}
|
||||
}
|
||||
|
||||
// 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
|
||||
// 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.
|
||||
func (srv *Server) Shutdown() error {
|
||||
srv.lock.Lock()
|
||||
if !srv.started {
|
||||
srv.lock.Unlock()
|
||||
return &Error{err: "server not started"}
|
||||
}
|
||||
srv.started = false
|
||||
srv.lock.Unlock()
|
||||
net, addr := srv.Net, srv.Addr
|
||||
switch {
|
||||
case srv.Listener != nil:
|
||||
a := srv.Listener.Addr()
|
||||
net, addr = a.Network(), a.String()
|
||||
case srv.PacketConn != nil:
|
||||
a := srv.PacketConn.LocalAddr()
|
||||
net, addr = a.Network(), a.String()
|
||||
|
||||
if srv.PacketConn != nil {
|
||||
srv.PacketConn.Close()
|
||||
}
|
||||
if srv.Listener != nil {
|
||||
srv.Listener.Close()
|
||||
}
|
||||
|
||||
fin := make(chan bool)
|
||||
switch net {
|
||||
case "tcp", "tcp4", "tcp6":
|
||||
go func() {
|
||||
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
|
||||
go func() {
|
||||
srv.inFlight.Wait()
|
||||
fin <- true
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-time.After(srv.getReadTimeout()):
|
||||
@ -369,14 +453,19 @@ func (srv *Server) getReadTimeout() time.Duration {
|
||||
}
|
||||
|
||||
// serveTCP starts a TCP listener for the server.
|
||||
// Each request is handled in a seperate goroutine.
|
||||
func (srv *Server) serveTCP(l *net.TCPListener) error {
|
||||
// Each request is handled in a separate goroutine.
|
||||
func (srv *Server) serveTCP(l net.Listener) error {
|
||||
defer l.Close()
|
||||
|
||||
if srv.NotifyStartedFunc != nil {
|
||||
srv.NotifyStartedFunc()
|
||||
}
|
||||
|
||||
reader := Reader(&defaultReader{srv})
|
||||
if srv.DecorateReader != nil {
|
||||
reader = srv.DecorateReader(reader)
|
||||
}
|
||||
|
||||
handler := srv.Handler
|
||||
if handler == nil {
|
||||
handler = DefaultServeMux
|
||||
@ -384,27 +473,30 @@ func (srv *Server) serveTCP(l *net.TCPListener) error {
|
||||
rtimeout := srv.getReadTimeout()
|
||||
// deadline is not used here
|
||||
for {
|
||||
rw, e := l.AcceptTCP()
|
||||
rw, e := l.Accept()
|
||||
if e != nil {
|
||||
continue
|
||||
if neterr, ok := e.(net.Error); ok && neterr.Temporary() {
|
||||
continue
|
||||
}
|
||||
return e
|
||||
}
|
||||
m, e := srv.readTCP(rw, rtimeout)
|
||||
select {
|
||||
case <-srv.stopTCP:
|
||||
m, e := reader.ReadTCP(rw, rtimeout)
|
||||
srv.lock.RLock()
|
||||
if !srv.started {
|
||||
srv.lock.RUnlock()
|
||||
return nil
|
||||
default:
|
||||
}
|
||||
srv.lock.RUnlock()
|
||||
if e != nil {
|
||||
continue
|
||||
}
|
||||
srv.wgTCP.Add(1)
|
||||
srv.inFlight.Add(1)
|
||||
go srv.serve(rw.RemoteAddr(), handler, m, nil, nil, rw)
|
||||
}
|
||||
panic("dns: not reached")
|
||||
}
|
||||
|
||||
// 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 {
|
||||
defer l.Close()
|
||||
|
||||
@ -412,6 +504,11 @@ func (srv *Server) serveUDP(l *net.UDPConn) error {
|
||||
srv.NotifyStartedFunc()
|
||||
}
|
||||
|
||||
reader := Reader(&defaultReader{srv})
|
||||
if srv.DecorateReader != nil {
|
||||
reader = srv.DecorateReader(reader)
|
||||
}
|
||||
|
||||
handler := srv.Handler
|
||||
if handler == nil {
|
||||
handler = DefaultServeMux
|
||||
@ -419,35 +516,39 @@ func (srv *Server) serveUDP(l *net.UDPConn) error {
|
||||
rtimeout := srv.getReadTimeout()
|
||||
// deadline is not used here
|
||||
for {
|
||||
m, s, e := srv.readUDP(l, rtimeout)
|
||||
select {
|
||||
case <-srv.stopUDP:
|
||||
m, s, e := reader.ReadUDP(l, rtimeout)
|
||||
srv.lock.RLock()
|
||||
if !srv.started {
|
||||
srv.lock.RUnlock()
|
||||
return nil
|
||||
default:
|
||||
}
|
||||
srv.lock.RUnlock()
|
||||
if e != nil {
|
||||
continue
|
||||
}
|
||||
srv.wgUDP.Add(1)
|
||||
srv.inFlight.Add(1)
|
||||
go srv.serve(s.RemoteAddr(), handler, m, l, s, nil)
|
||||
}
|
||||
panic("dns: not reached")
|
||||
}
|
||||
|
||||
// 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}
|
||||
q := 0
|
||||
defer func() {
|
||||
if u != nil {
|
||||
srv.wgUDP.Done()
|
||||
}
|
||||
if t != nil {
|
||||
srv.wgTCP.Done()
|
||||
}
|
||||
}()
|
||||
if srv.DecorateWriter != nil {
|
||||
w.writer = srv.DecorateWriter(w)
|
||||
} else {
|
||||
w.writer = w
|
||||
}
|
||||
|
||||
q := 0 // counter for the amount of TCP queries we get
|
||||
|
||||
reader := Reader(&defaultReader{srv})
|
||||
if srv.DecorateReader != nil {
|
||||
reader = srv.DecorateReader(reader)
|
||||
}
|
||||
Redo:
|
||||
// Ideally we want use isMsg here before we allocate memory to actually parse the packet.
|
||||
req := new(Msg)
|
||||
err := req.Unpack(m)
|
||||
if err != nil { // Send a FormatError back
|
||||
@ -475,6 +576,15 @@ Redo:
|
||||
h.ServeDNS(w, req) // Writes back to the client
|
||||
|
||||
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 {
|
||||
return // client calls Close()
|
||||
}
|
||||
@ -486,21 +596,16 @@ Exit:
|
||||
if srv.IdleTimeout != nil {
|
||||
idleTimeout = srv.IdleTimeout()
|
||||
}
|
||||
m, e := srv.readTCP(w.tcp, idleTimeout)
|
||||
m, e := reader.ReadTCP(w.tcp, idleTimeout)
|
||||
if e == nil {
|
||||
q++
|
||||
// TODO(miek): make this number configurable?
|
||||
if q > 128 { // close socket after this many queries
|
||||
w.Close()
|
||||
return
|
||||
}
|
||||
goto Redo
|
||||
}
|
||||
w.Close()
|
||||
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))
|
||||
l := make([]byte, 2)
|
||||
n, err := conn.Read(l)
|
||||
@ -535,10 +640,10 @@ func (srv *Server) readTCP(conn *net.TCPConn, timeout time.Duration) ([]byte, er
|
||||
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))
|
||||
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 {
|
||||
return nil, nil, e
|
||||
@ -558,7 +663,7 @@ func (w *response) WriteMsg(m *Msg) (err error) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = w.Write(data)
|
||||
_, err = w.writer.Write(data)
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -566,7 +671,7 @@ func (w *response) WriteMsg(m *Msg) (err error) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = w.Write(data)
|
||||
_, err = w.writer.Write(data)
|
||||
return err
|
||||
}
|
||||
|
||||
@ -574,7 +679,7 @@ func (w *response) WriteMsg(m *Msg) (err error) {
|
||||
func (w *response) Write(m []byte) (int, error) {
|
||||
switch {
|
||||
case w.udp != nil:
|
||||
n, err := writeToSessionUDP(w.udp, m, w.udpSession)
|
||||
n, err := WriteToSessionUDP(w.udp, m, w.udpSession)
|
||||
return n, err
|
||||
case w.tcp != nil:
|
||||
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
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/dsa"
|
||||
"crypto/ecdsa"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"math/big"
|
||||
"strings"
|
||||
@ -29,7 +13,7 @@ import (
|
||||
// Sign signs a dns.Msg. It fills the signature with the appropriate data.
|
||||
// The SIG record should have the SignerName, KeyTag, Algorithm, Inception
|
||||
// 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 {
|
||||
return nil, ErrPrivKey
|
||||
}
|
||||
@ -57,56 +41,26 @@ func (rr *SIG) Sign(k PrivateKey, m *Msg) ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
buf = buf[:off:cap(buf)]
|
||||
var hash crypto.Hash
|
||||
var intlen int
|
||||
switch rr.Algorithm {
|
||||
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:
|
||||
|
||||
hash, ok := AlgorithmToHash[rr.Algorithm]
|
||||
if !ok {
|
||||
return nil, ErrAlg
|
||||
}
|
||||
|
||||
hasher := hash.New()
|
||||
// Write SIG rdata
|
||||
hasher.Write(buf[len(mbuf)+1+2+2+4+2:])
|
||||
// Write message
|
||||
hasher.Write(buf[:len(mbuf)])
|
||||
hashed := hasher.Sum(nil)
|
||||
|
||||
var sig []byte
|
||||
switch p := k.(type) {
|
||||
case *dsa.PrivateKey:
|
||||
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
|
||||
signature, err := sign(k, hasher.Sum(nil), hash, rr.Algorithm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rr.Signature = toBase64(sig)
|
||||
|
||||
rr.Signature = toBase64(signature)
|
||||
sig := string(signature)
|
||||
|
||||
buf = append(buf, sig...)
|
||||
if len(buf) > int(^uint16(0)) {
|
||||
return nil, ErrBuf
|
||||
@ -118,7 +72,7 @@ func (rr *SIG) Sign(k PrivateKey, m *Msg) ([]byte, error) {
|
||||
buf[rdoff], buf[rdoff+1] = packUint16(rdlen)
|
||||
// Adjust additional count
|
||||
adc, _ := unpackUint16(buf, 10)
|
||||
adc += 1
|
||||
adc++
|
||||
buf[10], buf[11] = packUint16(adc)
|
||||
return buf, nil
|
||||
}
|
||||
@ -246,7 +200,7 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
|
||||
return rsa.VerifyPKCS1v15(pk, hash, hashed, sig)
|
||||
}
|
||||
case ECDSAP256SHA256, ECDSAP384SHA384:
|
||||
pk := k.publicKeyCurve()
|
||||
pk := k.publicKeyECDSA()
|
||||
r := big.NewInt(0)
|
||||
r.SetBytes(sig[:len(sig)/2])
|
||||
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()
|
||||
switch selector {
|
||||
case 0:
|
||||
return hex.EncodeToString(cert.Raw), nil
|
||||
io.WriteString(h, string(cert.Raw))
|
||||
return hex.EncodeToString(h.Sum(nil)), nil
|
||||
case 1:
|
||||
io.WriteString(h, string(cert.RawSubjectPublicKeyInfo))
|
||||
return hex.EncodeToString(h.Sum(nil)), nil
|
||||
@ -34,7 +35,8 @@ func CertificateToDANE(selector, matchingType uint8, cert *x509.Certificate) (st
|
||||
h := sha512.New()
|
||||
switch selector {
|
||||
case 0:
|
||||
return hex.EncodeToString(cert.Raw), nil
|
||||
io.WriteString(h, string(cert.Raw))
|
||||
return hex.EncodeToString(h.Sum(nil)), nil
|
||||
case 1:
|
||||
io.WriteString(h, string(cert.RawSubjectPublicKeyInfo))
|
||||
return hex.EncodeToString(h.Sum(nil)), nil
|
||||
@ -80,5 +82,5 @@ func TLSAName(name, service, network string) (string, error) {
|
||||
if e != nil {
|
||||
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
|
||||
|
||||
import (
|
||||
@ -58,6 +5,7 @@ import (
|
||||
"crypto/md5"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"encoding/hex"
|
||||
"hash"
|
||||
"io"
|
||||
@ -71,8 +19,11 @@ const (
|
||||
HmacMD5 = "hmac-md5.sig-alg.reg.int."
|
||||
HmacSHA1 = "hmac-sha1."
|
||||
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 {
|
||||
Hdr RR_Header
|
||||
Algorithm string `dns:"domain-name"`
|
||||
@ -86,10 +37,6 @@ type TSIG struct {
|
||||
OtherData string `dns:"size-hex"`
|
||||
}
|
||||
|
||||
func (rr *TSIG) Header() *RR_Header {
|
||||
return &rr.Hdr
|
||||
}
|
||||
|
||||
// TSIG has no official presentation format, but this will suffice.
|
||||
|
||||
func (rr *TSIG) String() string {
|
||||
@ -107,15 +54,6 @@ func (rr *TSIG) String() string {
|
||||
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.
|
||||
// RFC 2845, section 3.4.2. TSIG Variables.
|
||||
type tsigWireFmt struct {
|
||||
@ -174,13 +112,15 @@ func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, s
|
||||
|
||||
t := new(TSIG)
|
||||
var h hash.Hash
|
||||
switch rr.Algorithm {
|
||||
switch strings.ToLower(rr.Algorithm) {
|
||||
case HmacMD5:
|
||||
h = hmac.New(md5.New, []byte(rawsecret))
|
||||
case HmacSHA1:
|
||||
h = hmac.New(sha1.New, []byte(rawsecret))
|
||||
case HmacSHA256:
|
||||
h = hmac.New(sha256.New, []byte(rawsecret))
|
||||
case HmacSHA512:
|
||||
h = hmac.New(sha512.New, []byte(rawsecret))
|
||||
default:
|
||||
return nil, "", ErrKeyAlg
|
||||
}
|
||||
@ -238,13 +178,15 @@ func TsigVerify(msg []byte, secret, requestMAC string, timersOnly bool) error {
|
||||
}
|
||||
|
||||
var h hash.Hash
|
||||
switch tsig.Algorithm {
|
||||
switch strings.ToLower(tsig.Algorithm) {
|
||||
case HmacMD5:
|
||||
h = hmac.New(md5.New, rawsecret)
|
||||
case HmacSHA1:
|
||||
h = hmac.New(sha1.New, rawsecret)
|
||||
case HmacSHA256:
|
||||
h = hmac.New(sha256.New, rawsecret)
|
||||
case HmacSHA512:
|
||||
h = hmac.New(sha512.New, rawsecret)
|
||||
default:
|
||||
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
|
||||
|
||||
@ -7,12 +7,15 @@ import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
type sessionUDP struct {
|
||||
// SessionUDP holds the remote address and the associated
|
||||
// out-of-band data.
|
||||
type SessionUDP struct {
|
||||
raddr *net.UDPAddr
|
||||
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.
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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.
|
||||
func readFromSessionUDP(conn *net.UDPConn, b []byte) (int, *sessionUDP, error) {
|
||||
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
|
||||
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) {
|
||||
// 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
|
||||
}
|
||||
|
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 {
|
||||
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
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
return err
|
||||
}
|
||||
err = syscall.SetNonblock(int(file.Fd()), true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
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
|
||||
|
||||
|
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"
|
||||
|
||||
type sessionUDP struct {
|
||||
type SessionUDP struct {
|
||||
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.
|
||||
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)
|
||||
if err != nil {
|
||||
return n, nil, err
|
||||
}
|
||||
session := &sessionUDP{raddr.(*net.UDPAddr)}
|
||||
session := &SessionUDP{raddr.(*net.UDPAddr)}
|
||||
return n, session, 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) {
|
||||
// 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.WriteTo(b, session.raddr)
|
||||
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.
|
||||
// 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
|
||||
|
||||
// NameUsed sets the RRs in the prereq section to
|
||||
// "Name is in use" RRs. RFC 2136 section 2.4.4.
|
||||
func (u *Msg) NameUsed(rr []RR) {
|
||||
u.Answer = make([]RR, len(rr))
|
||||
for i, r := range rr {
|
||||
u.Answer[i] = &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassANY}}
|
||||
if u.Answer == nil {
|
||||
u.Answer = make([]RR, 0, len(rr))
|
||||
}
|
||||
for _, r := range rr {
|
||||
u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassANY}})
|
||||
}
|
||||
}
|
||||
|
||||
// NameNotUsed sets the RRs in the prereq section to
|
||||
// "Name is in not use" RRs. RFC 2136 section 2.4.5.
|
||||
func (u *Msg) NameNotUsed(rr []RR) {
|
||||
u.Answer = make([]RR, len(rr))
|
||||
for i, r := range rr {
|
||||
u.Answer[i] = &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassNONE}}
|
||||
if u.Answer == nil {
|
||||
u.Answer = make([]RR, 0, len(rr))
|
||||
}
|
||||
for _, r := range rr {
|
||||
u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassNONE}})
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,34 +28,34 @@ func (u *Msg) Used(rr []RR) {
|
||||
if len(u.Question) == 0 {
|
||||
panic("dns: empty question section")
|
||||
}
|
||||
u.Answer = make([]RR, len(rr))
|
||||
for i, r := range rr {
|
||||
u.Answer[i] = r
|
||||
u.Answer[i].Header().Class = u.Question[0].Qclass
|
||||
if u.Answer == nil {
|
||||
u.Answer = make([]RR, 0, len(rr))
|
||||
}
|
||||
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
|
||||
// "RRset exists (value independent -- no rdata)" RRs. RFC 2136 section 2.4.1.
|
||||
func (u *Msg) RRsetUsed(rr []RR) {
|
||||
u.Answer = make([]RR, len(rr))
|
||||
for i, r := range rr {
|
||||
u.Answer[i] = r
|
||||
u.Answer[i].Header().Class = ClassANY
|
||||
u.Answer[i].Header().Ttl = 0
|
||||
u.Answer[i].Header().Rdlength = 0
|
||||
if u.Answer == nil {
|
||||
u.Answer = make([]RR, 0, len(rr))
|
||||
}
|
||||
for _, r := range rr {
|
||||
u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: r.Header().Rrtype, Class: ClassANY}})
|
||||
}
|
||||
}
|
||||
|
||||
// RRsetNotUsed sets the RRs in the prereq section to
|
||||
// "RRset does not exist" RRs. RFC 2136 section 2.4.3.
|
||||
func (u *Msg) RRsetNotUsed(rr []RR) {
|
||||
u.Answer = make([]RR, len(rr))
|
||||
for i, r := range rr {
|
||||
u.Answer[i] = r
|
||||
u.Answer[i].Header().Class = ClassNONE
|
||||
u.Answer[i].Header().Rdlength = 0
|
||||
u.Answer[i].Header().Ttl = 0
|
||||
if u.Answer == nil {
|
||||
u.Answer = make([]RR, 0, len(rr))
|
||||
}
|
||||
for _, r := range rr {
|
||||
u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: r.Header().Rrtype, Class: ClassNONE}})
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,44 +64,43 @@ func (u *Msg) Insert(rr []RR) {
|
||||
if len(u.Question) == 0 {
|
||||
panic("dns: empty question section")
|
||||
}
|
||||
u.Ns = make([]RR, len(rr))
|
||||
for i, r := range rr {
|
||||
u.Ns[i] = r
|
||||
u.Ns[i].Header().Class = u.Question[0].Qclass
|
||||
if u.Ns == nil {
|
||||
u.Ns = make([]RR, 0, len(rr))
|
||||
}
|
||||
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.
|
||||
func (u *Msg) RemoveRRset(rr []RR) {
|
||||
m := make(map[RR_Header]struct{})
|
||||
u.Ns = make([]RR, 0, len(rr))
|
||||
if u.Ns == nil {
|
||||
u.Ns = make([]RR, 0, len(rr))
|
||||
}
|
||||
for _, r := range rr {
|
||||
h := *r.Header().copyHeader()
|
||||
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})
|
||||
u.Ns = append(u.Ns, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: r.Header().Rrtype, Class: ClassANY}})
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
u.Ns = make([]RR, len(rr))
|
||||
for i, r := range rr {
|
||||
u.Ns[i] = &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassANY}}
|
||||
if u.Ns == nil {
|
||||
u.Ns = make([]RR, 0, len(rr))
|
||||
}
|
||||
for _, r := range rr {
|
||||
u.Ns = append(u.Ns, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: 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) {
|
||||
u.Ns = make([]RR, len(rr))
|
||||
for i, r := range rr {
|
||||
u.Ns[i] = r
|
||||
u.Ns[i].Header().Class = ClassNONE
|
||||
u.Ns[i].Header().Ttl = 0
|
||||
if u.Ns == nil {
|
||||
u.Ns = make([]RR, 0, len(rr))
|
||||
}
|
||||
for _, r := range rr {
|
||||
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.
|
||||
type Transfer struct {
|
||||
*Conn
|
||||
DialTimeout time.Duration // net.DialTimeout (ns), defaults to 2 * 1e9
|
||||
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections (ns), defaults to 2 * 1e9
|
||||
WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections (ns), defaults to 2 * 1e9
|
||||
DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds
|
||||
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
|
||||
tsigTimersOnly bool
|
||||
}
|
||||
@ -23,14 +23,26 @@ type Transfer struct {
|
||||
// Think we need to away to stop the transfer
|
||||
|
||||
// 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) {
|
||||
timeout := dnsTimeout
|
||||
if t.DialTimeout != 0 {
|
||||
timeout = t.DialTimeout
|
||||
}
|
||||
t.Conn, err = DialTimeout("tcp", a, timeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if t.Conn == nil {
|
||||
t.Conn, err = DialTimeout("tcp", a, timeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if err := t.WriteMsg(q); err != nil {
|
||||
return nil, err
|
||||
@ -91,7 +103,6 @@ func (t *Transfer) inAxfr(id uint16, c chan *Envelope) {
|
||||
c <- &Envelope{in.Answer, nil}
|
||||
}
|
||||
}
|
||||
panic("dns: not reached")
|
||||
}
|
||||
|
||||
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))
|
||||
in, err := t.ReadMsg()
|
||||
if err != nil {
|
||||
c <- &Envelope{in.Answer, err}
|
||||
c <- &Envelope{nil, err}
|
||||
return
|
||||
}
|
||||
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
|
||||
// channel ch.
|
||||
func (t *Transfer) Out(w ResponseWriter, q *Msg, ch chan *Envelope) error {
|
||||
r := new(Msg)
|
||||
// Compress?
|
||||
r.SetReply(q)
|
||||
r.Authoritative = true
|
||||
|
||||
go func() {
|
||||
for x := range ch {
|
||||
// assume it fits TODO(miek): fix
|
||||
r.Answer = append(r.Answer, x.RR...)
|
||||
if err := w.WriteMsg(r); err != nil {
|
||||
return
|
||||
}
|
||||
for x := range ch {
|
||||
r := new(Msg)
|
||||
// Compress?
|
||||
r.SetReply(q)
|
||||
r.Authoritative = true
|
||||
// assume it fits TODO(miek): fix
|
||||
r.Answer = append(r.Answer, x.RR...)
|
||||
if err := w.WriteMsg(r); err != nil {
|
||||
return err
|
||||
}
|
||||
w.TsigTimersOnly(true)
|
||||
r.Answer = nil
|
||||
}()
|
||||
}
|
||||
w.TsigTimersOnly(true)
|
||||
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.
|
||||
err = TsigVerify(p, t.TsigSecret[ts.Hdr.Name], t.tsigRequestMAC, t.tsigTimersOnly)
|
||||
t.tsigRequestMAC = ts.MAC
|
||||
}
|
||||
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
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -14,7 +15,7 @@ import (
|
||||
// * [[ttl][class]]
|
||||
// * type
|
||||
// * 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.
|
||||
// Any error are returned as a string value, the empty string signals
|
||||
// "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) {
|
||||
return "bad step in $GENERATE range"
|
||||
}
|
||||
if s, e := strconv.Atoi(l.token[i+1:]); e != nil {
|
||||
return "bad step in $GENERATE range"
|
||||
} else {
|
||||
if s, e := strconv.Atoi(l.token[i+1:]); e == nil {
|
||||
if s < 0 {
|
||||
return "bad step in $GENERATE range"
|
||||
}
|
||||
step = s
|
||||
} else {
|
||||
return "bad step in $GENERATE range"
|
||||
}
|
||||
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 {
|
||||
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"
|
||||
}
|
||||
|
||||
@ -55,14 +56,14 @@ func generate(l lex, c chan lex, t chan *Token, o string) string {
|
||||
s := ""
|
||||
BuildRR:
|
||||
l = <-c
|
||||
if l.value != _NEWLINE && l.value != _EOF {
|
||||
if l.value != zNewline && l.value != zEOF {
|
||||
s += l.token
|
||||
goto BuildRR
|
||||
}
|
||||
for i := start; i <= end; i += step {
|
||||
var (
|
||||
escape bool
|
||||
dom string
|
||||
dom bytes.Buffer
|
||||
mod string
|
||||
err string
|
||||
offset int
|
||||
@ -72,7 +73,7 @@ BuildRR:
|
||||
switch s[j] {
|
||||
case '\\':
|
||||
if escape {
|
||||
dom += "\\"
|
||||
dom.WriteByte('\\')
|
||||
escape = false
|
||||
continue
|
||||
}
|
||||
@ -81,17 +82,17 @@ BuildRR:
|
||||
mod = "%d"
|
||||
offset = 0
|
||||
if escape {
|
||||
dom += "$"
|
||||
dom.WriteByte('$')
|
||||
escape = false
|
||||
continue
|
||||
}
|
||||
escape = false
|
||||
if j+1 >= len(s) { // End of the string
|
||||
dom += fmt.Sprintf(mod, i+offset)
|
||||
dom.WriteString(fmt.Sprintf(mod, i+offset))
|
||||
continue
|
||||
} else {
|
||||
if s[j+1] == '$' {
|
||||
dom += "$"
|
||||
dom.WriteByte('$')
|
||||
j++
|
||||
continue
|
||||
}
|
||||
@ -108,17 +109,17 @@ BuildRR:
|
||||
}
|
||||
j += 2 + sep // Jump to it
|
||||
}
|
||||
dom += fmt.Sprintf(mod, i+offset)
|
||||
dom.WriteString(fmt.Sprintf(mod, i+offset))
|
||||
default:
|
||||
if escape { // Pretty useless here
|
||||
escape = false
|
||||
continue
|
||||
}
|
||||
dom += string(s[j])
|
||||
dom.WriteByte(s[j])
|
||||
}
|
||||
}
|
||||
// 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 {
|
||||
return e.(*ParseError).err
|
||||
}
|
||||
@ -140,11 +141,11 @@ func modToPrintf(s string) (string, int, string) {
|
||||
return "", 0, "bad base in $GENERATE"
|
||||
}
|
||||
offset, err := strconv.Atoi(xs[0])
|
||||
if err != nil {
|
||||
if err != nil || offset > 255 {
|
||||
return "", 0, "bad offset in $GENERATE"
|
||||
}
|
||||
width, err := strconv.Atoi(xs[1])
|
||||
if err != nil {
|
||||
if err != nil || width > 255 {
|
||||
return "", offset, "bad width in $GENERATE"
|
||||
}
|
||||
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.
|
||||
const (
|
||||
// Zonefile
|
||||
_EOF = iota
|
||||
_STRING
|
||||
_BLANK
|
||||
_QUOTE
|
||||
_NEWLINE
|
||||
_RRTYPE
|
||||
_OWNER
|
||||
_CLASS
|
||||
_DIRORIGIN // $ORIGIN
|
||||
_DIRTTL // $TTL
|
||||
_DIRINCLUDE // $INCLUDE
|
||||
_DIRGENERATE // $GENERATE
|
||||
zEOF = iota
|
||||
zString
|
||||
zBlank
|
||||
zQuote
|
||||
zNewline
|
||||
zRrtpe
|
||||
zOwner
|
||||
zClass
|
||||
zDirOrigin // $ORIGIN
|
||||
zDirTtl // $TTL
|
||||
zDirInclude // $INCLUDE
|
||||
zDirGenerate // $GENERATE
|
||||
|
||||
// Privatekey file
|
||||
_VALUE
|
||||
_KEY
|
||||
zValue
|
||||
zKey
|
||||
|
||||
_EXPECT_OWNER_DIR // Ownername
|
||||
_EXPECT_OWNER_BL // Whitespace after the ownername
|
||||
_EXPECT_ANY // Expect rrtype, ttl or class
|
||||
_EXPECT_ANY_NOCLASS // Expect rrtype or ttl
|
||||
_EXPECT_ANY_NOCLASS_BL // The whitespace after _EXPECT_ANY_NOCLASS
|
||||
_EXPECT_ANY_NOTTL // Expect rrtype or class
|
||||
_EXPECT_ANY_NOTTL_BL // Whitespace after _EXPECT_ANY_NOTTL
|
||||
_EXPECT_RRTYPE // Expect rrtype
|
||||
_EXPECT_RRTYPE_BL // Whitespace BEFORE rrtype
|
||||
_EXPECT_RDATA // The first element of the rdata
|
||||
_EXPECT_DIRTTL_BL // Space after directive $TTL
|
||||
_EXPECT_DIRTTL // Directive $TTL
|
||||
_EXPECT_DIRORIGIN_BL // Space after directive $ORIGIN
|
||||
_EXPECT_DIRORIGIN // Directive $ORIGIN
|
||||
_EXPECT_DIRINCLUDE_BL // Space after directive $INCLUDE
|
||||
_EXPECT_DIRINCLUDE // Directive $INCLUDE
|
||||
_EXPECT_DIRGENERATE // Directive $GENERATE
|
||||
_EXPECT_DIRGENERATE_BL // Space after directive $GENERATE
|
||||
zExpectOwnerDir // Ownername
|
||||
zExpectOwnerBl // Whitespace after the ownername
|
||||
zExpectAny // Expect rrtype, ttl or class
|
||||
zExpectAnyNoClass // Expect rrtype or ttl
|
||||
zExpectAnyNoClassBl // The whitespace after _EXPECT_ANY_NOCLASS
|
||||
zExpectAnyNoTtl // Expect rrtype or class
|
||||
zExpectAnyNoTtlBl // Whitespace after _EXPECT_ANY_NOTTL
|
||||
zExpectRrtype // Expect rrtype
|
||||
zExpectRrtypeBl // Whitespace BEFORE rrtype
|
||||
zExpectRdata // The first element of the rdata
|
||||
zExpectDirTtlBl // Space after directive $TTL
|
||||
zExpectDirTtl // Directive $TTL
|
||||
zExpectDirOriginBl // Space after directive $ORIGIN
|
||||
zExpectDirOrigin // Directive $ORIGIN
|
||||
zExpectDirIncludeBl // Space after directive $INCLUDE
|
||||
zExpectDirInclude // Directive $INCLUDE
|
||||
zExpectDirGenerate // Directive $GENERATE
|
||||
zExpectDirGenerateBl // Space after directive $GENERATE
|
||||
)
|
||||
|
||||
// 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 {
|
||||
file string
|
||||
err string
|
||||
@ -86,28 +86,32 @@ func (e *ParseError) Error() (s string) {
|
||||
type lex struct {
|
||||
token string // 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
|
||||
value uint8 // value: _STRING, _BLANK, etc.
|
||||
value uint8 // value: zString, _BLANK, etc.
|
||||
line int // line 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
|
||||
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 {
|
||||
RR // the scanned resource record when error is not nil
|
||||
Error *ParseError // when an error occured, this has the error specifics
|
||||
Comment string // a potential comment positioned after the RR and on the same line
|
||||
// The scanned resource record when error is not nil.
|
||||
RR
|
||||
// When an error occurred, this has the error specifics.
|
||||
Error *ParseError
|
||||
// A potential comment positioned after the RR and on the same line.
|
||||
Comment string
|
||||
}
|
||||
|
||||
// NewRR reads the RR contained in the string s. Only the first RR is returned.
|
||||
// The class defaults to IN and TTL defaults to 3600. The full zone file
|
||||
// syntax like $TTL, $ORIGIN, etc. is supported.
|
||||
// All fields of the returned RR are set, except RR.Header().Rdlength which is set to 0.
|
||||
// NewRR reads the RR contained in the string s. Only the first RR is
|
||||
// returned. If s contains no RR, return nil with no error. The class
|
||||
// defaults to IN and TTL defaults to 3600. The full zone file syntax
|
||||
// like $TTL, $ORIGIN, etc. is supported. All fields of the returned
|
||||
// RR are set, except RR.Header().Rdlength which is set to 0.
|
||||
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), "")
|
||||
@ -117,17 +121,21 @@ func NewRR(s string) (RR, error) {
|
||||
// See NewRR for more documentation.
|
||||
func ReadRR(q io.Reader, filename string) (RR, error) {
|
||||
r := <-parseZoneHelper(q, ".", filename, 1)
|
||||
if r == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if r.Error != nil {
|
||||
return nil, r.Error
|
||||
}
|
||||
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.
|
||||
// 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
|
||||
// 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 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), "", "") {
|
||||
// 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:
|
||||
//
|
||||
// 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.
|
||||
func ParseZone(r io.Reader, origin, file string) chan *Token {
|
||||
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)
|
||||
c := make(chan lex, 1000)
|
||||
c := make(chan lex)
|
||||
// Start the lexer
|
||||
go zlexer(s, c)
|
||||
// 6 possible beginnings of a line, _ is a space
|
||||
// 0. _RRTYPE -> all omitted until the rrtype
|
||||
// 1. _OWNER _ _RRTYPE -> class/ttl omitted
|
||||
// 2. _OWNER _ _STRING _ _RRTYPE -> class omitted
|
||||
// 3. _OWNER _ _STRING _ _CLASS _ _RRTYPE -> ttl/class
|
||||
// 4. _OWNER _ _CLASS _ _RRTYPE -> ttl omitted
|
||||
// 5. _OWNER _ _CLASS _ _STRING _ _RRTYPE -> class/ttl (reversed)
|
||||
// After detecting these, we know the _RRTYPE so we can jump to functions
|
||||
// 0. zRRTYPE -> all omitted until the rrtype
|
||||
// 1. zOwner _ zRrtype -> class/ttl omitted
|
||||
// 2. zOwner _ zString _ zRrtype -> class omitted
|
||||
// 3. zOwner _ zString _ zClass _ zRrtype -> ttl/class
|
||||
// 4. zOwner _ zClass _ zRrtype -> ttl omitted
|
||||
// 5. zOwner _ zClass _ zString _ zRrtype -> class/ttl (reversed)
|
||||
// After detecting these, we know the zRrtype so we can jump to functions
|
||||
// handling the rdata for each of these types.
|
||||
|
||||
if origin == "" {
|
||||
@ -185,7 +195,7 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
||||
return
|
||||
}
|
||||
|
||||
st := _EXPECT_OWNER_DIR // initial state
|
||||
st := zExpectOwnerDir // initial state
|
||||
var h RR_Header
|
||||
var defttl uint32 = defaultTtl
|
||||
var prevName string
|
||||
@ -197,19 +207,19 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
||||
|
||||
}
|
||||
switch st {
|
||||
case _EXPECT_OWNER_DIR:
|
||||
case zExpectOwnerDir:
|
||||
// We can also expect a directive, like $TTL or $ORIGIN
|
||||
h.Ttl = defttl
|
||||
h.Class = ClassINET
|
||||
switch l.value {
|
||||
case _NEWLINE: // Empty line
|
||||
st = _EXPECT_OWNER_DIR
|
||||
case _OWNER:
|
||||
case zNewline:
|
||||
st = zExpectOwnerDir
|
||||
case zOwner:
|
||||
h.Name = l.token
|
||||
if l.token[0] == '@' {
|
||||
h.Name = origin
|
||||
prevName = h.Name
|
||||
st = _EXPECT_OWNER_BL
|
||||
st = zExpectOwnerBl
|
||||
break
|
||||
}
|
||||
if h.Name[l.length-1] != '.' {
|
||||
@ -221,59 +231,59 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
||||
return
|
||||
}
|
||||
prevName = h.Name
|
||||
st = _EXPECT_OWNER_BL
|
||||
case _DIRTTL:
|
||||
st = _EXPECT_DIRTTL_BL
|
||||
case _DIRORIGIN:
|
||||
st = _EXPECT_DIRORIGIN_BL
|
||||
case _DIRINCLUDE:
|
||||
st = _EXPECT_DIRINCLUDE_BL
|
||||
case _DIRGENERATE:
|
||||
st = _EXPECT_DIRGENERATE_BL
|
||||
case _RRTYPE: // Everthing has been omitted, this is the first thing on the line
|
||||
st = zExpectOwnerBl
|
||||
case zDirTtl:
|
||||
st = zExpectDirTtlBl
|
||||
case zDirOrigin:
|
||||
st = zExpectDirOriginBl
|
||||
case zDirInclude:
|
||||
st = zExpectDirIncludeBl
|
||||
case zDirGenerate:
|
||||
st = zExpectDirGenerateBl
|
||||
case zRrtpe:
|
||||
h.Name = prevName
|
||||
h.Rrtype = l.torc
|
||||
st = _EXPECT_RDATA
|
||||
case _CLASS: // First thing on the line is the class
|
||||
st = zExpectRdata
|
||||
case zClass:
|
||||
h.Name = prevName
|
||||
h.Class = l.torc
|
||||
st = _EXPECT_ANY_NOCLASS_BL
|
||||
case _BLANK:
|
||||
st = zExpectAnyNoClassBl
|
||||
case zBlank:
|
||||
// Discard, can happen when there is nothing on the
|
||||
// line except the RR type
|
||||
case _STRING: // First thing on the is the ttl
|
||||
if ttl, ok := stringToTtl(l.token); !ok {
|
||||
case zString:
|
||||
ttl, ok := stringToTtl(l.token)
|
||||
if !ok {
|
||||
t <- &Token{Error: &ParseError{f, "not a TTL", l}}
|
||||
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:
|
||||
t <- &Token{Error: &ParseError{f, "syntax error at beginning", l}}
|
||||
return
|
||||
}
|
||||
case _EXPECT_DIRINCLUDE_BL:
|
||||
if l.value != _BLANK {
|
||||
case zExpectDirIncludeBl:
|
||||
if l.value != zBlank {
|
||||
t <- &Token{Error: &ParseError{f, "no blank after $INCLUDE-directive", l}}
|
||||
return
|
||||
}
|
||||
st = _EXPECT_DIRINCLUDE
|
||||
case _EXPECT_DIRINCLUDE:
|
||||
if l.value != _STRING {
|
||||
st = zExpectDirInclude
|
||||
case zExpectDirInclude:
|
||||
if l.value != zString {
|
||||
t <- &Token{Error: &ParseError{f, "expecting $INCLUDE value, not this...", l}}
|
||||
return
|
||||
}
|
||||
neworigin := origin // There may be optionally a new origin set after the filename, if not use current one
|
||||
l := <-c
|
||||
switch l.value {
|
||||
case _BLANK:
|
||||
case zBlank:
|
||||
l := <-c
|
||||
if l.value == _STRING {
|
||||
if _, ok := IsDomainName(l.token); !ok {
|
||||
if l.value == zString {
|
||||
if _, ok := IsDomainName(l.token); !ok || l.length == 0 || l.err {
|
||||
t <- &Token{Error: &ParseError{f, "bad origin name", l}}
|
||||
return
|
||||
}
|
||||
@ -288,7 +298,7 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
||||
neworigin = l.token
|
||||
}
|
||||
}
|
||||
case _NEWLINE, _EOF:
|
||||
case zNewline, zEOF:
|
||||
// Ok
|
||||
default:
|
||||
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
|
||||
}
|
||||
parseZone(r1, l.token, neworigin, t, include+1)
|
||||
st = _EXPECT_OWNER_DIR
|
||||
case _EXPECT_DIRTTL_BL:
|
||||
if l.value != _BLANK {
|
||||
st = zExpectOwnerDir
|
||||
case zExpectDirTtlBl:
|
||||
if l.value != zBlank {
|
||||
t <- &Token{Error: &ParseError{f, "no blank after $TTL-directive", l}}
|
||||
return
|
||||
}
|
||||
st = _EXPECT_DIRTTL
|
||||
case _EXPECT_DIRTTL:
|
||||
if l.value != _STRING {
|
||||
st = zExpectDirTtl
|
||||
case zExpectDirTtl:
|
||||
if l.value != zString {
|
||||
t <- &Token{Error: &ParseError{f, "expecting $TTL value, not this...", l}}
|
||||
return
|
||||
}
|
||||
@ -321,21 +331,21 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
||||
t <- &Token{Error: e}
|
||||
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}}
|
||||
return
|
||||
} else {
|
||||
defttl = ttl
|
||||
}
|
||||
st = _EXPECT_OWNER_DIR
|
||||
case _EXPECT_DIRORIGIN_BL:
|
||||
if l.value != _BLANK {
|
||||
defttl = ttl
|
||||
st = zExpectOwnerDir
|
||||
case zExpectDirOriginBl:
|
||||
if l.value != zBlank {
|
||||
t <- &Token{Error: &ParseError{f, "no blank after $ORIGIN-directive", l}}
|
||||
return
|
||||
}
|
||||
st = _EXPECT_DIRORIGIN
|
||||
case _EXPECT_DIRORIGIN:
|
||||
if l.value != _STRING {
|
||||
st = zExpectDirOrigin
|
||||
case zExpectDirOrigin:
|
||||
if l.value != zString {
|
||||
t <- &Token{Error: &ParseError{f, "expecting $ORIGIN value, not this...", l}}
|
||||
return
|
||||
}
|
||||
@ -355,15 +365,15 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
||||
} else {
|
||||
origin = l.token
|
||||
}
|
||||
st = _EXPECT_OWNER_DIR
|
||||
case _EXPECT_DIRGENERATE_BL:
|
||||
if l.value != _BLANK {
|
||||
st = zExpectOwnerDir
|
||||
case zExpectDirGenerateBl:
|
||||
if l.value != zBlank {
|
||||
t <- &Token{Error: &ParseError{f, "no blank after $GENERATE-directive", l}}
|
||||
return
|
||||
}
|
||||
st = _EXPECT_DIRGENERATE
|
||||
case _EXPECT_DIRGENERATE:
|
||||
if l.value != _STRING {
|
||||
st = zExpectDirGenerate
|
||||
case zExpectDirGenerate:
|
||||
if l.value != zString {
|
||||
t <- &Token{Error: &ParseError{f, "expecting $GENERATE value, not this...", l}}
|
||||
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}}
|
||||
return
|
||||
}
|
||||
st = _EXPECT_OWNER_DIR
|
||||
case _EXPECT_OWNER_BL:
|
||||
if l.value != _BLANK {
|
||||
st = zExpectOwnerDir
|
||||
case zExpectOwnerBl:
|
||||
if l.value != zBlank {
|
||||
t <- &Token{Error: &ParseError{f, "no blank after owner", l}}
|
||||
return
|
||||
}
|
||||
st = _EXPECT_ANY
|
||||
case _EXPECT_ANY:
|
||||
st = zExpectAny
|
||||
case zExpectAny:
|
||||
switch l.value {
|
||||
case _RRTYPE:
|
||||
case zRrtpe:
|
||||
h.Rrtype = l.torc
|
||||
st = _EXPECT_RDATA
|
||||
case _CLASS:
|
||||
st = zExpectRdata
|
||||
case zClass:
|
||||
h.Class = l.torc
|
||||
st = _EXPECT_ANY_NOCLASS_BL
|
||||
case _STRING: // TTL is this case
|
||||
if ttl, ok := stringToTtl(l.token); !ok {
|
||||
st = zExpectAnyNoClassBl
|
||||
case zString:
|
||||
ttl, ok := stringToTtl(l.token)
|
||||
if !ok {
|
||||
t <- &Token{Error: &ParseError{f, "not a TTL", l}}
|
||||
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:
|
||||
t <- &Token{Error: &ParseError{f, "expecting RR type, TTL or class, not this...", l}}
|
||||
return
|
||||
}
|
||||
case _EXPECT_ANY_NOCLASS_BL:
|
||||
if l.value != _BLANK {
|
||||
case zExpectAnyNoClassBl:
|
||||
if l.value != zBlank {
|
||||
t <- &Token{Error: &ParseError{f, "no blank before class", l}}
|
||||
return
|
||||
}
|
||||
st = _EXPECT_ANY_NOCLASS
|
||||
case _EXPECT_ANY_NOTTL_BL:
|
||||
if l.value != _BLANK {
|
||||
st = zExpectAnyNoClass
|
||||
case zExpectAnyNoTtlBl:
|
||||
if l.value != zBlank {
|
||||
t <- &Token{Error: &ParseError{f, "no blank before TTL", l}}
|
||||
return
|
||||
}
|
||||
st = _EXPECT_ANY_NOTTL
|
||||
case _EXPECT_ANY_NOTTL:
|
||||
st = zExpectAnyNoTtl
|
||||
case zExpectAnyNoTtl:
|
||||
switch l.value {
|
||||
case _CLASS:
|
||||
case zClass:
|
||||
h.Class = l.torc
|
||||
st = _EXPECT_RRTYPE_BL
|
||||
case _RRTYPE:
|
||||
st = zExpectRrtypeBl
|
||||
case zRrtpe:
|
||||
h.Rrtype = l.torc
|
||||
st = _EXPECT_RDATA
|
||||
st = zExpectRdata
|
||||
default:
|
||||
t <- &Token{Error: &ParseError{f, "expecting RR type or class, not this...", l}}
|
||||
return
|
||||
}
|
||||
case _EXPECT_ANY_NOCLASS:
|
||||
case zExpectAnyNoClass:
|
||||
switch l.value {
|
||||
case _STRING: // TTL
|
||||
if ttl, ok := stringToTtl(l.token); !ok {
|
||||
case zString:
|
||||
ttl, ok := stringToTtl(l.token)
|
||||
if !ok {
|
||||
t <- &Token{Error: &ParseError{f, "not a TTL", l}}
|
||||
return
|
||||
} else {
|
||||
h.Ttl = ttl
|
||||
// defttl = ttl // don't set the def ttl anymore
|
||||
}
|
||||
st = _EXPECT_RRTYPE_BL
|
||||
case _RRTYPE:
|
||||
h.Ttl = ttl
|
||||
// defttl = ttl // don't set the def ttl anymore
|
||||
st = zExpectRrtypeBl
|
||||
case zRrtpe:
|
||||
h.Rrtype = l.torc
|
||||
st = _EXPECT_RDATA
|
||||
st = zExpectRdata
|
||||
default:
|
||||
t <- &Token{Error: &ParseError{f, "expecting RR type or TTL, not this...", l}}
|
||||
return
|
||||
}
|
||||
case _EXPECT_RRTYPE_BL:
|
||||
if l.value != _BLANK {
|
||||
case zExpectRrtypeBl:
|
||||
if l.value != zBlank {
|
||||
t <- &Token{Error: &ParseError{f, "no blank before RR type", l}}
|
||||
return
|
||||
}
|
||||
st = _EXPECT_RRTYPE
|
||||
case _EXPECT_RRTYPE:
|
||||
if l.value != _RRTYPE {
|
||||
st = zExpectRrtype
|
||||
case zExpectRrtype:
|
||||
if l.value != zRrtpe {
|
||||
t <- &Token{Error: &ParseError{f, "unknown RR type", l}}
|
||||
return
|
||||
}
|
||||
h.Rrtype = l.torc
|
||||
st = _EXPECT_RDATA
|
||||
case _EXPECT_RDATA:
|
||||
st = zExpectRdata
|
||||
case zExpectRdata:
|
||||
r, e, c1 := setRR(h, c, origin, f)
|
||||
if e != nil {
|
||||
// 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
|
||||
}
|
||||
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
|
||||
@ -492,14 +502,14 @@ func zlexer(s *scan, c chan lex) {
|
||||
for err == nil {
|
||||
l.column = s.position.Column
|
||||
l.line = s.position.Line
|
||||
if stri > maxTok {
|
||||
if stri >= maxTok {
|
||||
l.token = "token length insufficient for parsing"
|
||||
l.err = true
|
||||
debug.Printf("[%+v]", l.token)
|
||||
c <- l
|
||||
return
|
||||
}
|
||||
if comi > maxTok {
|
||||
if comi >= maxTok {
|
||||
l.token = "comment length insufficient for parsing"
|
||||
l.err = true
|
||||
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
|
||||
} else if 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.tokenUpper = strings.ToUpper(l.token)
|
||||
l.length = stri
|
||||
// escape $... start with a \ not a $, so this will work
|
||||
switch l.tokenUpper {
|
||||
case "$TTL":
|
||||
l.value = _DIRTTL
|
||||
l.value = zDirTtl
|
||||
case "$ORIGIN":
|
||||
l.value = _DIRORIGIN
|
||||
l.value = zDirOrigin
|
||||
case "$INCLUDE":
|
||||
l.value = _DIRINCLUDE
|
||||
l.value = zDirInclude
|
||||
case "$GENERATE":
|
||||
l.value = _DIRGENERATE
|
||||
l.value = zDirGenerate
|
||||
}
|
||||
debug.Printf("[7 %+v]", l.token)
|
||||
c <- l
|
||||
} else {
|
||||
l.value = _STRING
|
||||
l.value = zString
|
||||
l.token = string(str[:stri])
|
||||
l.tokenUpper = strings.ToUpper(l.token)
|
||||
l.length = stri
|
||||
if !rrtype {
|
||||
if t, ok := StringToType[l.tokenUpper]; ok {
|
||||
l.value = _RRTYPE
|
||||
l.value = zRrtpe
|
||||
l.torc = t
|
||||
rrtype = true
|
||||
} else {
|
||||
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.err = true
|
||||
c <- l
|
||||
return
|
||||
} else {
|
||||
l.value = _RRTYPE
|
||||
l.torc = t
|
||||
}
|
||||
l.value = zRrtpe
|
||||
l.torc = t
|
||||
}
|
||||
}
|
||||
if t, ok := StringToClass[l.tokenUpper]; ok {
|
||||
l.value = _CLASS
|
||||
l.value = zClass
|
||||
l.torc = t
|
||||
} else {
|
||||
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.err = true
|
||||
c <- l
|
||||
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
|
||||
// I reverse space stuff here
|
||||
if !space && !commt {
|
||||
l.value = _BLANK
|
||||
l.value = zBlank
|
||||
l.token = " "
|
||||
l.length = 1
|
||||
debug.Printf("[5 %+v]", l.token)
|
||||
@ -615,7 +625,7 @@ func zlexer(s *scan, c chan lex) {
|
||||
break
|
||||
}
|
||||
if stri > 0 {
|
||||
l.value = _STRING
|
||||
l.value = zString
|
||||
l.token = string(str[:stri])
|
||||
l.length = stri
|
||||
debug.Printf("[4 %+v]", l.token)
|
||||
@ -651,7 +661,7 @@ func zlexer(s *scan, c chan lex) {
|
||||
if brace == 0 {
|
||||
owner = true
|
||||
owner = true
|
||||
l.value = _NEWLINE
|
||||
l.value = zNewline
|
||||
l.token = "\n"
|
||||
l.length = 1
|
||||
l.comment = string(com[:comi])
|
||||
@ -669,14 +679,14 @@ func zlexer(s *scan, c chan lex) {
|
||||
if brace == 0 {
|
||||
// If there is previous text, we should output it here
|
||||
if stri != 0 {
|
||||
l.value = _STRING
|
||||
l.value = zString
|
||||
l.token = string(str[:stri])
|
||||
l.tokenUpper = strings.ToUpper(l.token)
|
||||
|
||||
l.length = stri
|
||||
if !rrtype {
|
||||
if t, ok := StringToType[l.tokenUpper]; ok {
|
||||
l.value = _RRTYPE
|
||||
l.value = zRrtpe
|
||||
l.torc = t
|
||||
rrtype = true
|
||||
}
|
||||
@ -684,7 +694,7 @@ func zlexer(s *scan, c chan lex) {
|
||||
debug.Printf("[2 %+v]", l.token)
|
||||
c <- l
|
||||
}
|
||||
l.value = _NEWLINE
|
||||
l.value = zNewline
|
||||
l.token = "\n"
|
||||
l.length = 1
|
||||
debug.Printf("[1 %+v]", l.token)
|
||||
@ -728,7 +738,7 @@ func zlexer(s *scan, c chan lex) {
|
||||
space = false
|
||||
// send previous gathered text and the quote
|
||||
if stri != 0 {
|
||||
l.value = _STRING
|
||||
l.value = zString
|
||||
l.token = string(str[:stri])
|
||||
l.length = stri
|
||||
|
||||
@ -738,7 +748,7 @@ func zlexer(s *scan, c chan lex) {
|
||||
}
|
||||
|
||||
// send quote itself as separate token
|
||||
l.value = _QUOTE
|
||||
l.value = zQuote
|
||||
l.token = "\""
|
||||
l.length = 1
|
||||
c <- l
|
||||
@ -790,7 +800,7 @@ func zlexer(s *scan, c chan lex) {
|
||||
// Send remainder
|
||||
l.token = string(str[:stri])
|
||||
l.length = stri
|
||||
l.value = _STRING
|
||||
l.value = zString
|
||||
debug.Printf("[%+v]", l.token)
|
||||
c <- l
|
||||
}
|
||||
@ -798,7 +808,11 @@ func zlexer(s *scan, c chan lex) {
|
||||
|
||||
// Extract the class number from CLASSxx
|
||||
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 {
|
||||
return 0, false
|
||||
}
|
||||
@ -807,7 +821,11 @@ func classToInt(token string) (uint16, bool) {
|
||||
|
||||
// Extract the rr number from TYPExxx
|
||||
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 {
|
||||
return 0, false
|
||||
}
|
||||
@ -922,15 +940,15 @@ func slurpRemainder(c chan lex, f string) (*ParseError, string) {
|
||||
l := <-c
|
||||
com := ""
|
||||
switch l.value {
|
||||
case _BLANK:
|
||||
case zBlank:
|
||||
l = <-c
|
||||
com = l.comment
|
||||
if l.value != _NEWLINE && l.value != _EOF {
|
||||
if l.value != zNewline && l.value != zEOF {
|
||||
return &ParseError{f, "garbage after rdata", l}, ""
|
||||
}
|
||||
case _NEWLINE:
|
||||
case zNewline:
|
||||
com = l.comment
|
||||
case _EOF:
|
||||
case zEOF:
|
||||
default:
|
||||
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"
|
||||
)
|
||||
|
||||
// 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.
|
||||
// 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.
|
||||
@ -29,7 +37,7 @@ type Service struct {
|
||||
// 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
|
||||
// DNS name.
|
||||
TargetStrip int `json:"targetstrip",omitempty"`
|
||||
TargetStrip int `json:"targetstrip,omitempty"`
|
||||
|
||||
// Group is used to group (or *not* to group) different services
|
||||
// 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.
|
||||
func (s *Service) NewSRV(name string, weight uint16) *dns.SRV {
|
||||
host := dns.Fqdn(s.Host)
|
||||
|
||||
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:]
|
||||
host := targetStrip(dns.Fqdn(s.Host), s.TargetStrip)
|
||||
|
||||
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}
|
||||
@ -60,17 +58,7 @@ func (s *Service) NewSRV(name string, weight uint16) *dns.SRV {
|
||||
|
||||
// NewMX returns a new MX record based on the Service.
|
||||
func (s *Service) NewMX(name string) *dns.MX {
|
||||
host := dns.Fqdn(s.Host)
|
||||
|
||||
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:]
|
||||
host := targetStrip(dns.Fqdn(s.Host), s.TargetStrip)
|
||||
|
||||
return &dns.MX{Hdr: dns.RR_Header{Name: name, Rrtype: dns.TypeMX, Class: dns.ClassINET, Ttl: s.Ttl},
|
||||
Preference: uint16(s.Priority), Mx: host}
|
||||
@ -118,10 +106,10 @@ func PathWithWildcard(s string) (string, bool) {
|
||||
}
|
||||
for i, k := range l {
|
||||
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.,
|
||||
@ -131,7 +119,7 @@ func Path(s string) string {
|
||||
for i, j := 0, len(l)-1; i < j; i, j = i+1, j-1 {
|
||||
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.
|
||||
@ -213,3 +201,21 @@ func split255(s string) []string {
|
||||
|
||||
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