Merge pull request #2422 from levenlabs/nameList

discovery: Instead of looping over conf.Search, use NameList()
This commit is contained in:
Björn Rabenstein 2017-02-14 17:48:06 +01:00 committed by GitHub
commit 0f412e7e26
25 changed files with 305 additions and 292 deletions

View file

@ -179,13 +179,12 @@ func lookupAll(name string, qtype uint16) (*dns.Msg, error) {
for _, server := range conf.Servers { for _, server := range conf.Servers {
servAddr := net.JoinHostPort(server, conf.Port) servAddr := net.JoinHostPort(server, conf.Port)
for _, suffix := range conf.Search { for _, lname := range conf.NameList(name) {
response, err = lookup(name, qtype, client, servAddr, suffix, false) response, err = lookup(lname, qtype, client, servAddr, false)
if err != nil { if err != nil {
log. log.
With("server", server). With("server", server).
With("name", name). With("name", name).
With("suffix", suffix).
With("reason", err). With("reason", err).
Warn("DNS resolution failed.") Warn("DNS resolution failed.")
continue continue
@ -194,22 +193,12 @@ func lookupAll(name string, qtype uint16) (*dns.Msg, error) {
return response, nil return response, nil
} }
} }
response, err = lookup(name, qtype, client, servAddr, "", false)
if err == nil {
return response, nil
}
log.
With("server", server).
With("name", name).
With("reason", err).
Warn("DNS resolution failed.")
} }
return response, fmt.Errorf("could not resolve %s: no server responded", name) return response, fmt.Errorf("could not resolve %s: no server responded", name)
} }
func lookup(name string, queryType uint16, client *dns.Client, servAddr string, suffix string, edns bool) (*dns.Msg, error) { func lookup(lname string, queryType uint16, client *dns.Client, servAddr string, edns bool) (*dns.Msg, error) {
msg := &dns.Msg{} msg := &dns.Msg{}
lname := strings.Join([]string{name, suffix}, ".")
msg.SetQuestion(dns.Fqdn(lname), queryType) msg.SetQuestion(dns.Fqdn(lname), queryType)
if edns { if edns {
@ -224,7 +213,7 @@ func lookup(name string, queryType uint16, client *dns.Client, servAddr string,
if edns { // Truncated even though EDNS is used if edns { // Truncated even though EDNS is used
client.Net = "tcp" client.Net = "tcp"
} }
return lookup(name, queryType, client, servAddr, suffix, !edns) return lookup(lname, queryType, client, servAddr, !edns)
} }
if err != nil { if err != nil {
return nil, err return nil, err

View file

@ -1,4 +1,5 @@
[![Build Status](https://travis-ci.org/miekg/dns.svg?branch=master)](https://travis-ci.org/miekg/dns) [![](https://godoc.org/github.com/miekg/dns?status.svg)](https://godoc.org/github.com/miekg/dns) [![Build Status](https://travis-ci.org/miekg/dns.svg?branch=master)](https://travis-ci.org/miekg/dns)
[![](https://godoc.org/github.com/miekg/dns?status.svg)](https://godoc.org/github.com/miekg/dns)
# Alternative (more granular) approach to a DNS library # Alternative (more granular) approach to a DNS library
@ -12,7 +13,7 @@ can build servers and resolvers with it.
We try to keep the "master" branch as sane as possible and at the bleeding edge 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 of standards, avoiding breaking changes wherever reasonable. We support the last
two versions of Go, currently: 1.5 and 1.6. two versions of Go, currently: 1.6 and 1.7.
# Goals # Goals

View file

@ -300,6 +300,18 @@ func tcpMsgLen(t io.Reader) (int, error) {
if err != nil { if err != nil {
return 0, err return 0, err
} }
// As seen with my local router/switch, retursn 1 byte on the above read,
// resulting a a ShortRead. Just write it out (instead of loop) and read the
// other byte.
if n == 1 {
n1, err := t.Read(p[1:])
if err != nil {
return 0, err
}
n += n1
}
if n != 2 { if n != 2 {
return 0, ErrShortRead return 0, ErrShortRead
} }
@ -400,7 +412,7 @@ func (co *Conn) Write(p []byte) (n int, err error) {
n, err := io.Copy(w, bytes.NewReader(p)) n, err := io.Copy(w, bytes.NewReader(p))
return int(n), err return int(n), err
} }
n, err = co.Conn.(*net.UDPConn).Write(p) n, err = co.Conn.Write(p)
return n, err return n, err
} }

View file

@ -97,3 +97,35 @@ func ClientConfigFromFile(resolvconf string) (*ClientConfig, error) {
} }
return c, nil return c, nil
} }
// NameList returns all of the names that should be queried based on the
// config. It is based off of go's net/dns name building, but it does not
// check the length of the resulting names.
func (c *ClientConfig) NameList(name string) []string {
// if this domain is already fully qualified, no append needed.
if IsFqdn(name) {
return []string{name}
}
// Check to see if the name has more labels than Ndots. Do this before making
// the domain fully qualified.
hasNdots := CountLabel(name) > c.Ndots
// Make the domain fully qualified.
name = Fqdn(name)
// Make a list of names based off search.
names := []string{}
// If name has enough dots, try that first.
if hasNdots {
names = append(names, name)
}
for _, s := range c.Search {
names = append(names, Fqdn(name+s))
}
// If we didn't have enough dots, try after suffixes.
if !hasNdots {
names = append(names, name)
}
return names
}

View file

@ -6,7 +6,6 @@ import (
"crypto/x509" "crypto/x509"
"encoding/hex" "encoding/hex"
"errors" "errors"
"io"
) )
// CertificateToDANE converts a certificate to a hex string as used in the TLSA or SMIMEA records. // CertificateToDANE converts a certificate to a hex string as used in the TLSA or SMIMEA records.
@ -23,20 +22,20 @@ func CertificateToDANE(selector, matchingType uint8, cert *x509.Certificate) (st
h := sha256.New() h := sha256.New()
switch selector { switch selector {
case 0: case 0:
io.WriteString(h, string(cert.Raw)) h.Write(cert.Raw)
return hex.EncodeToString(h.Sum(nil)), nil return hex.EncodeToString(h.Sum(nil)), nil
case 1: case 1:
io.WriteString(h, string(cert.RawSubjectPublicKeyInfo)) h.Write(cert.RawSubjectPublicKeyInfo)
return hex.EncodeToString(h.Sum(nil)), nil return hex.EncodeToString(h.Sum(nil)), nil
} }
case 2: case 2:
h := sha512.New() h := sha512.New()
switch selector { switch selector {
case 0: case 0:
io.WriteString(h, string(cert.Raw)) h.Write(cert.Raw)
return hex.EncodeToString(h.Sum(nil)), nil return hex.EncodeToString(h.Sum(nil)), nil
case 1: case 1:
io.WriteString(h, string(cert.RawSubjectPublicKeyInfo)) h.Write(cert.RawSubjectPublicKeyInfo)
return hex.EncodeToString(h.Sum(nil)), nil return hex.EncodeToString(h.Sum(nil)), nil
} }
} }

View file

@ -102,11 +102,11 @@ func (dns *Msg) SetAxfr(z string) *Msg {
// SetTsig appends a TSIG RR to the message. // SetTsig appends a TSIG RR to the message.
// This is only a skeleton TSIG RR that is added as the last RR in the // This is only a skeleton TSIG RR that is added as the last RR in the
// additional section. The Tsig is calculated when the message is being send. // additional section. The Tsig is calculated when the message is being send.
func (dns *Msg) SetTsig(z, algo string, fudge, timesigned int64) *Msg { func (dns *Msg) SetTsig(z, algo string, fudge uint16, timesigned int64) *Msg {
t := new(TSIG) t := new(TSIG)
t.Hdr = RR_Header{z, TypeTSIG, ClassANY, 0, 0} t.Hdr = RR_Header{z, TypeTSIG, ClassANY, 0, 0}
t.Algorithm = algo t.Algorithm = algo
t.Fudge = 300 t.Fudge = fudge
t.TimeSigned = uint64(timesigned) t.TimeSigned = uint64(timesigned)
t.OrigId = dns.Id t.OrigId = dns.Id
dns.Extra = append(dns.Extra, t) dns.Extra = append(dns.Extra, t)

View file

@ -208,9 +208,6 @@ func (k *DNSKEY) ToDS(h uint8) *DS {
// "|" denotes concatenation // "|" denotes concatenation
// DNSKEY RDATA = Flags | Protocol | Algorithm | Public Key. // DNSKEY RDATA = Flags | Protocol | Algorithm | Public Key.
// digest buffer
digest := append(owner, wire...) // another copy
var hash crypto.Hash var hash crypto.Hash
switch h { switch h {
case SHA1: case SHA1:
@ -226,7 +223,8 @@ func (k *DNSKEY) ToDS(h uint8) *DS {
} }
s := hash.New() s := hash.New()
s.Write(digest) s.Write(owner)
s.Write(wire)
ds.Digest = hex.EncodeToString(s.Sum(nil)) ds.Digest = hex.EncodeToString(s.Sum(nil))
return ds return ds
} }
@ -297,7 +295,6 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
if err != nil { if err != nil {
return err return err
} }
signdata = append(signdata, wire...)
hash, ok := AlgorithmToHash[rr.Algorithm] hash, ok := AlgorithmToHash[rr.Algorithm]
if !ok { if !ok {
@ -306,6 +303,7 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
h := hash.New() h := hash.New()
h.Write(signdata) h.Write(signdata)
h.Write(wire)
signature, err := sign(k, h.Sum(nil), hash, rr.Algorithm) signature, err := sign(k, h.Sum(nil), hash, rr.Algorithm)
if err != nil { if err != nil {
@ -415,7 +413,6 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
if err != nil { if err != nil {
return err return err
} }
signeddata = append(signeddata, wire...)
sigbuf := rr.sigBuf() // Get the binary signature data sigbuf := rr.sigBuf() // Get the binary signature data
if rr.Algorithm == PRIVATEDNS { // PRIVATEOID if rr.Algorithm == PRIVATEDNS { // PRIVATEOID
@ -438,6 +435,7 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
h := hash.New() h := hash.New()
h.Write(signeddata) h.Write(signeddata)
h.Write(wire)
return rsa.VerifyPKCS1v15(pubkey, hash, h.Sum(nil), sigbuf) return rsa.VerifyPKCS1v15(pubkey, hash, h.Sum(nil), sigbuf)
case ECDSAP256SHA256, ECDSAP384SHA384: case ECDSAP256SHA256, ECDSAP384SHA384:
@ -452,6 +450,7 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
h := hash.New() h := hash.New()
h.Write(signeddata) h.Write(signeddata)
h.Write(wire)
if ecdsa.Verify(pubkey, h.Sum(nil), r, s) { if ecdsa.Verify(pubkey, h.Sum(nil), r, s) {
return nil return nil
} }

View file

@ -121,17 +121,17 @@ func (k *DNSKEY) setPublicKeyDSA(_Q, _P, _G, _Y *big.Int) bool {
// RFC 3110: Section 2. RSA Public KEY Resource Records // RFC 3110: Section 2. RSA Public KEY Resource Records
func exponentToBuf(_E int) []byte { func exponentToBuf(_E int) []byte {
var buf []byte var buf []byte
i := big.NewInt(int64(_E)) i := big.NewInt(int64(_E)).Bytes()
if len(i.Bytes()) < 256 { if len(i) < 256 {
buf = make([]byte, 1) buf = make([]byte, 1, 1+len(i))
buf[0] = uint8(len(i.Bytes())) buf[0] = uint8(len(i))
} else { } else {
buf = make([]byte, 3) buf = make([]byte, 3, 3+len(i))
buf[0] = 0 buf[0] = 0
buf[1] = uint8(len(i.Bytes()) >> 8) buf[1] = uint8(len(i) >> 8)
buf[2] = uint8(len(i.Bytes())) buf[2] = uint8(len(i))
} }
buf = append(buf, i.Bytes()...) buf = append(buf, i...)
return buf return buf
} }

83
vendor/github.com/miekg/dns/edns.go generated vendored
View file

@ -4,25 +4,27 @@ import (
"encoding/binary" "encoding/binary"
"encoding/hex" "encoding/hex"
"errors" "errors"
"fmt"
"net" "net"
"strconv" "strconv"
) )
// EDNS0 Option codes. // EDNS0 Option codes.
const ( const (
EDNS0LLQ = 0x1 // long lived queries: http://tools.ietf.org/html/draft-sekar-dns-llq-01 EDNS0LLQ = 0x1 // long lived queries: http://tools.ietf.org/html/draft-sekar-dns-llq-01
EDNS0UL = 0x2 // update lease draft: http://files.dns-sd.org/draft-sekar-dns-ul.txt EDNS0UL = 0x2 // update lease draft: http://files.dns-sd.org/draft-sekar-dns-ul.txt
EDNS0NSID = 0x3 // nsid (RFC5001) EDNS0NSID = 0x3 // nsid (RFC5001)
EDNS0DAU = 0x5 // DNSSEC Algorithm Understood EDNS0DAU = 0x5 // DNSSEC Algorithm Understood
EDNS0DHU = 0x6 // DS Hash Understood EDNS0DHU = 0x6 // DS Hash Understood
EDNS0N3U = 0x7 // NSEC3 Hash Understood EDNS0N3U = 0x7 // NSEC3 Hash Understood
EDNS0SUBNET = 0x8 // client-subnet (RFC6891) EDNS0SUBNET = 0x8 // client-subnet (RFC6891)
EDNS0EXPIRE = 0x9 // EDNS0 expire EDNS0EXPIRE = 0x9 // EDNS0 expire
EDNS0COOKIE = 0xa // EDNS0 Cookie EDNS0COOKIE = 0xa // EDNS0 Cookie
EDNS0SUBNETDRAFT = 0x50fa // Don't use! Use EDNS0SUBNET EDNS0TCPKEEPALIVE = 0xb // EDNS0 tcp keep alive (RFC7828)
EDNS0LOCALSTART = 0xFDE9 // Beginning of range reserved for local/experimental use (RFC6891) EDNS0SUBNETDRAFT = 0x50fa // Don't use! Use EDNS0SUBNET
EDNS0LOCALEND = 0xFFFE // End of range reserved for local/experimental use (RFC6891) EDNS0LOCALSTART = 0xFDE9 // Beginning of range reserved for local/experimental use (RFC6891)
_DO = 1 << 15 // dnssec ok 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. // OPT is the EDNS0 RR appended to messages to convey extra (meta) information.
@ -195,7 +197,7 @@ func (e *EDNS0_NSID) String() string { return string(e.Nsid) }
// e := new(dns.EDNS0_SUBNET) // e := new(dns.EDNS0_SUBNET)
// e.Code = dns.EDNS0SUBNET // e.Code = dns.EDNS0SUBNET
// e.Family = 1 // 1 for IPv4 source address, 2 for IPv6 // e.Family = 1 // 1 for IPv4 source address, 2 for IPv6
// e.NetMask = 32 // 32 for IPV4, 128 for IPv6 // e.SourceNetMask = 32 // 32 for IPV4, 128 for IPv6
// e.SourceScope = 0 // e.SourceScope = 0
// e.Address = net.ParseIP("127.0.0.1").To4() // for IPv4 // e.Address = net.ParseIP("127.0.0.1").To4() // for IPv4
// // e.Address = net.ParseIP("2001:7b8:32a::2") // for IPV6 // // e.Address = net.ParseIP("2001:7b8:32a::2") // for IPV6
@ -540,3 +542,56 @@ func (e *EDNS0_LOCAL) unpack(b []byte) error {
} }
return nil return nil
} }
type EDNS0_TCP_KEEPALIVE struct {
Code uint16 // Always EDNSTCPKEEPALIVE
Length uint16 // the value 0 if the TIMEOUT is omitted, the value 2 if it is present;
Timeout uint16 // an idle timeout value for the TCP connection, specified in units of 100 milliseconds, encoded in network byte order.
}
func (e *EDNS0_TCP_KEEPALIVE) Option() uint16 {
return EDNS0TCPKEEPALIVE
}
func (e *EDNS0_TCP_KEEPALIVE) pack() ([]byte, error) {
if e.Timeout != 0 && e.Length != 2 {
return nil, errors.New("dns: timeout specified but length is not 2")
}
if e.Timeout == 0 && e.Length != 0 {
return nil, errors.New("dns: timeout not specified but length is not 0")
}
b := make([]byte, 4+e.Length)
binary.BigEndian.PutUint16(b[0:], e.Code)
binary.BigEndian.PutUint16(b[2:], e.Length)
if e.Length == 2 {
binary.BigEndian.PutUint16(b[4:], e.Timeout)
}
return b, nil
}
func (e *EDNS0_TCP_KEEPALIVE) unpack(b []byte) error {
if len(b) < 4 {
return ErrBuf
}
e.Length = binary.BigEndian.Uint16(b[2:4])
if e.Length != 0 && e.Length != 2 {
return errors.New("dns: length mismatch, want 0/2 but got " + strconv.FormatUint(uint64(e.Length), 10))
}
if e.Length == 2 {
if len(b) < 6 {
return ErrBuf
}
e.Timeout = binary.BigEndian.Uint16(b[4:6])
}
return nil
}
func (e *EDNS0_TCP_KEEPALIVE) String() (s string) {
s = "use tcp keep-alive"
if e.Length == 0 {
s += ", timeout omitted"
} else {
s += fmt.Sprintf(", timeout %dms", e.Timeout*100)
}
return
}

82
vendor/github.com/miekg/dns/msg.go generated vendored
View file

@ -16,22 +16,9 @@ import (
"math/big" "math/big"
"math/rand" "math/rand"
"strconv" "strconv"
"sync"
) )
func init() {
// Initialize default math/rand source using crypto/rand to provide better
// security without the performance trade-off.
buf := make([]byte, 8)
_, err := crand.Read(buf)
if err != nil {
// Failed to read from cryptographic source, fallback to default initial
// seed (1) by returning early
return
}
seed := binary.BigEndian.Uint64(buf)
rand.Seed(int64(seed))
}
const maxCompressionOffset = 2 << 13 // We have 14 bits for the compression pointer const maxCompressionOffset = 2 << 13 // We have 14 bits for the compression pointer
var ( var (
@ -66,11 +53,45 @@ var (
// dns.Id = func() uint16 { return 3 } // dns.Id = func() uint16 { return 3 }
var Id func() uint16 = id var Id func() uint16 = id
var (
idLock sync.Mutex
idRand *rand.Rand
)
// id returns a 16 bits random number to be used as a // id returns a 16 bits random number to be used as a
// message id. The random provided should be good enough. // message id. The random provided should be good enough.
func id() uint16 { func id() uint16 {
id32 := rand.Uint32() idLock.Lock()
return uint16(id32)
if idRand == nil {
// This (partially) works around
// https://github.com/golang/go/issues/11833 by only
// seeding idRand upon the first call to id.
var seed int64
var buf [8]byte
if _, err := crand.Read(buf[:]); err == nil {
seed = int64(binary.LittleEndian.Uint64(buf[:]))
} else {
seed = rand.Int63()
}
idRand = rand.New(rand.NewSource(seed))
}
// The call to idRand.Uint32 must be within the
// mutex lock because *rand.Rand is not safe for
// concurrent use.
//
// There is no added performance overhead to calling
// idRand.Uint32 inside a mutex lock over just
// calling rand.Uint32 as the global math/rand rng
// is internally protected by a sync.Mutex.
id := uint16(idRand.Uint32())
idLock.Unlock()
return id
} }
// MsgHdr is a a manually-unpacked version of (id, bits). // MsgHdr is a a manually-unpacked version of (id, bits).
@ -203,12 +224,6 @@ func packDomainName(s string, msg []byte, off int, compression map[string]int, c
bs[j] = bs[j+2] bs[j] = bs[j+2]
} }
ls -= 2 ls -= 2
} else if bs[i] == 't' {
bs[i] = '\t'
} else if bs[i] == 'r' {
bs[i] = '\r'
} else if bs[i] == 'n' {
bs[i] = '\n'
} }
escapedDot = bs[i] == '.' escapedDot = bs[i] == '.'
bsFresh = false bsFresh = false
@ -335,10 +350,6 @@ Loop:
fallthrough fallthrough
case '"', '\\': case '"', '\\':
s = append(s, '\\', b) s = append(s, '\\', b)
case '\t':
s = append(s, '\\', 't')
case '\r':
s = append(s, '\\', 'r')
default: default:
if b < 32 || b >= 127 { // unprintable use \DDD if b < 32 || b >= 127 { // unprintable use \DDD
var buf [3]byte var buf [3]byte
@ -431,12 +442,6 @@ func packTxtString(s string, msg []byte, offset int, tmp []byte) (int, error) {
if i+2 < len(bs) && isDigit(bs[i]) && isDigit(bs[i+1]) && isDigit(bs[i+2]) { if i+2 < len(bs) && isDigit(bs[i]) && isDigit(bs[i+1]) && isDigit(bs[i+2]) {
msg[offset] = dddToByte(bs[i:]) msg[offset] = dddToByte(bs[i:])
i += 2 i += 2
} else if bs[i] == 't' {
msg[offset] = '\t'
} else if bs[i] == 'r' {
msg[offset] = '\r'
} else if bs[i] == 'n' {
msg[offset] = '\n'
} else { } else {
msg[offset] = bs[i] msg[offset] = bs[i]
} }
@ -508,12 +513,6 @@ func unpackTxtString(msg []byte, offset int) (string, int, error) {
switch b { switch b {
case '"', '\\': case '"', '\\':
s = append(s, '\\', b) s = append(s, '\\', b)
case '\t':
s = append(s, `\t`...)
case '\r':
s = append(s, `\r`...)
case '\n':
s = append(s, `\n`...)
default: default:
if b < 32 || b > 127 { // unprintable if b < 32 || b > 127 { // unprintable
var buf [3]byte var buf [3]byte
@ -781,9 +780,6 @@ func (dns *Msg) Unpack(msg []byte) (err error) {
if dh, off, err = unpackMsgHdr(msg, off); err != nil { if dh, off, err = unpackMsgHdr(msg, off); err != nil {
return err return err
} }
if off == len(msg) {
return ErrTruncated
}
dns.Id = dh.Id dns.Id = dh.Id
dns.Response = (dh.Bits & _QR) != 0 dns.Response = (dh.Bits & _QR) != 0
@ -797,6 +793,10 @@ func (dns *Msg) Unpack(msg []byte) (err error) {
dns.CheckingDisabled = (dh.Bits & _CD) != 0 dns.CheckingDisabled = (dh.Bits & _CD) != 0
dns.Rcode = int(dh.Bits & 0xF) dns.Rcode = int(dh.Bits & 0xF)
if off == len(msg) {
return ErrTruncated
}
// Optimistically use the count given to us in the header // Optimistically use the count given to us in the header
dns.Question = make([]Question, 0, int(dh.Qdcount)) dns.Question = make([]Question, 0, int(dh.Qdcount))

View file

@ -117,9 +117,9 @@ return off, err
switch { switch {
case st.Tag(i) == `dns:"-"`: // ignored case st.Tag(i) == `dns:"-"`: // ignored
case st.Tag(i) == `dns:"cdomain-name"`: case st.Tag(i) == `dns:"cdomain-name"`:
fallthrough
case st.Tag(i) == `dns:"domain-name"`:
o("off, err = PackDomainName(rr.%s, msg, off, compression, compress)\n") o("off, err = PackDomainName(rr.%s, msg, off, compression, compress)\n")
case st.Tag(i) == `dns:"domain-name"`:
o("off, err = PackDomainName(rr.%s, msg, off, compression, false)\n")
case st.Tag(i) == `dns:"a"`: case st.Tag(i) == `dns:"a"`:
o("off, err = packDataA(rr.%s, msg, off)\n") o("off, err = packDataA(rr.%s, msg, off)\n")
case st.Tag(i) == `dns:"aaaa"`: case st.Tag(i) == `dns:"aaaa"`:

View file

@ -263,8 +263,6 @@ func unpackString(msg []byte, off int) (string, int, error) {
switch b { switch b {
case '"', '\\': case '"', '\\':
s = append(s, '\\', b) s = append(s, '\\', b)
case '\t', '\r', '\n':
s = append(s, b)
default: default:
if b < 32 || b > 127 { // unprintable if b < 32 || b > 127 { // unprintable
var buf [3]byte var buf [3]byte

11
vendor/github.com/miekg/dns/nsecx.go generated vendored
View file

@ -3,7 +3,6 @@ package dns
import ( import (
"crypto/sha1" "crypto/sha1"
"hash" "hash"
"io"
"strings" "strings"
) )
@ -36,15 +35,15 @@ func HashName(label string, ha uint8, iter uint16, salt string) string {
} }
// k = 0 // k = 0
name = append(name, wire...) s.Write(name)
io.WriteString(s, string(name)) s.Write(wire)
nsec3 := s.Sum(nil) nsec3 := s.Sum(nil)
// k > 0 // k > 0
for k := uint16(0); k < iter; k++ { for k := uint16(0); k < iter; k++ {
s.Reset() s.Reset()
nsec3 = append(nsec3, wire...) s.Write(nsec3)
io.WriteString(s, string(nsec3)) s.Write(wire)
nsec3 = s.Sum(nil) nsec3 = s.Sum(nsec3[:0])
} }
return toBase32(nsec3) return toBase32(nsec3)
} }

View file

@ -64,74 +64,63 @@ func endingToString(c chan lex, errstr, f string) (string, *ParseError, string)
return s, nil, l.comment return s, nil, l.comment
} }
// A remainder of the rdata with embedded spaces, return the parsed string slice (sans the spaces) // A remainder of the rdata with embedded spaces, split on unquoted whitespace
// or an error // and return the parsed string slice or an error
func endingToTxtSlice(c chan lex, errstr, f string) ([]string, *ParseError, string) { func endingToTxtSlice(c chan lex, errstr, f string) ([]string, *ParseError, string) {
// Get the remaining data until we see a zNewline // Get the remaining data until we see a zNewline
quote := false
l := <-c l := <-c
var s []string
if l.err { if l.err {
return s, &ParseError{f, errstr, l}, "" return nil, &ParseError{f, errstr, l}, ""
} }
switch l.value == zQuote {
case true: // A number of quoted string
s = make([]string, 0)
empty := true
for l.value != zNewline && l.value != zEOF {
if l.err {
return nil, &ParseError{f, errstr, l}, ""
}
switch l.value {
case zString:
empty = false
if len(l.token) > 255 {
// split up tokens that are larger than 255 into 255-chunks
sx := []string{}
p, i := 0, 255
for {
if i <= len(l.token) {
sx = append(sx, l.token[p:i])
} else {
sx = append(sx, l.token[p:])
break
} // Build the slice
p, i = p+255, i+255 s := make([]string, 0)
} quote := false
s = append(s, sx...) empty := false
break for l.value != zNewline && l.value != zEOF {
} if l.err {
s = append(s, l.token)
case zBlank:
if quote {
// zBlank can only be seen in between txt parts.
return nil, &ParseError{f, errstr, l}, ""
}
case zQuote:
if empty && quote {
s = append(s, "")
}
quote = !quote
empty = true
default:
return nil, &ParseError{f, errstr, l}, ""
}
l = <-c
}
if quote {
return nil, &ParseError{f, errstr, l}, "" return nil, &ParseError{f, errstr, l}, ""
} }
case false: // Unquoted text record switch l.value {
s = make([]string, 1) case zString:
for l.value != zNewline && l.value != zEOF { empty = false
if l.err { if len(l.token) > 255 {
return s, &ParseError{f, errstr, l}, "" // split up tokens that are larger than 255 into 255-chunks
sx := []string{}
p, i := 0, 255
for {
if i <= len(l.token) {
sx = append(sx, l.token[p:i])
} else {
sx = append(sx, l.token[p:])
break
}
p, i = p+255, i+255
}
s = append(s, sx...)
break
} }
s[0] += l.token
l = <-c s = append(s, l.token)
case zBlank:
if quote {
// zBlank can only be seen in between txt parts.
return nil, &ParseError{f, errstr, l}, ""
}
case zQuote:
if empty && quote {
s = append(s, "")
}
quote = !quote
empty = true
default:
return nil, &ParseError{f, errstr, l}, ""
} }
l = <-c
}
if quote {
return nil, &ParseError{f, errstr, l}, ""
} }
return s, nil, l.comment return s, nil, l.comment
} }
@ -2027,9 +2016,12 @@ func setUINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr.Hdr = h rr.Hdr = h
s, e, c1 := endingToTxtSlice(c, "bad UINFO Uinfo", f) s, e, c1 := endingToTxtSlice(c, "bad UINFO Uinfo", f)
if e != nil { if e != nil {
return nil, e, "" return nil, e, c1
} }
rr.Uinfo = s[0] // silently discard anything above if ln := len(s); ln == 0 {
return rr, nil, c1
}
rr.Uinfo = s[0] // silently discard anything after the first character-string
return rr, nil, c1 return rr, nil, c1
} }

View file

@ -339,7 +339,7 @@ func (srv *Server) ListenAndServe() error {
network := "tcp" network := "tcp"
if srv.Net == "tcp4-tls" { if srv.Net == "tcp4-tls" {
network = "tcp4" network = "tcp4"
} else if srv.Net == "tcp6" { } else if srv.Net == "tcp6-tls" {
network = "tcp6" network = "tcp6"
} }
@ -389,7 +389,9 @@ func (srv *Server) ActivateAndServe() error {
if srv.UDPSize == 0 { if srv.UDPSize == 0 {
srv.UDPSize = MinMsgSize srv.UDPSize = MinMsgSize
} }
if t, ok := pConn.(*net.UDPConn); ok { // Check PacketConn interface's type is valid and value
// is not nil
if t, ok := pConn.(*net.UDPConn); ok && t != nil {
if e := setUDPSocketOptions(t); e != nil { if e := setUDPSocketOptions(t); e != nil {
return e return e
} }

View file

@ -60,16 +60,15 @@ func (rr *SIG) Sign(k crypto.Signer, m *Msg) ([]byte, error) {
} }
rr.Signature = toBase64(signature) rr.Signature = toBase64(signature)
sig := string(signature)
buf = append(buf, sig...) buf = append(buf, signature...)
if len(buf) > int(^uint16(0)) { if len(buf) > int(^uint16(0)) {
return nil, ErrBuf return nil, ErrBuf
} }
// Adjust sig data length // Adjust sig data length
rdoff := len(mbuf) + 1 + 2 + 2 + 4 rdoff := len(mbuf) + 1 + 2 + 2 + 4
rdlen := binary.BigEndian.Uint16(buf[rdoff:]) rdlen := binary.BigEndian.Uint16(buf[rdoff:])
rdlen += uint16(len(sig)) rdlen += uint16(len(signature))
binary.BigEndian.PutUint16(buf[rdoff:], rdlen) binary.BigEndian.PutUint16(buf[rdoff:], rdlen)
// Adjust additional count // Adjust additional count
adc := binary.BigEndian.Uint16(buf[10:]) adc := binary.BigEndian.Uint16(buf[10:])

View file

@ -9,7 +9,6 @@ import (
"encoding/binary" "encoding/binary"
"encoding/hex" "encoding/hex"
"hash" "hash"
"io"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@ -124,7 +123,7 @@ func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, s
default: default:
return nil, "", ErrKeyAlg return nil, "", ErrKeyAlg
} }
io.WriteString(h, string(buf)) h.Write(buf)
t.MAC = hex.EncodeToString(h.Sum(nil)) t.MAC = hex.EncodeToString(h.Sum(nil))
t.MACSize = uint16(len(t.MAC) / 2) // Size is half! t.MACSize = uint16(len(t.MAC) / 2) // Size is half!

19
vendor/github.com/miekg/dns/types.go generated vendored
View file

@ -480,12 +480,6 @@ func appendDomainNameByte(s []byte, b byte) []byte {
func appendTXTStringByte(s []byte, b byte) []byte { func appendTXTStringByte(s []byte, b byte) []byte {
switch b { switch b {
case '\t':
return append(s, '\\', 't')
case '\r':
return append(s, '\\', 'r')
case '\n':
return append(s, '\\', 'n')
case '"', '\\': case '"', '\\':
return append(s, '\\', b) return append(s, '\\', b)
} }
@ -525,17 +519,8 @@ func nextByte(b []byte, offset int) (byte, int) {
return dddToByte(b[offset+1:]), 4 return dddToByte(b[offset+1:]), 4
} }
} }
// not \ddd, maybe a control char // not \ddd, just an RFC 1035 "quoted" character
switch b[offset+1] { return b[offset+1], 2
case 't':
return '\t', 2
case 'r':
return '\r', 2
case 'n':
return '\n', 2
default:
return b[offset+1], 2
}
} }
type SPF struct { type SPF struct {

26
vendor/github.com/miekg/dns/udp.go generated vendored
View file

@ -1,10 +1,9 @@
// +build !windows,!plan9 // +build !windows
package dns package dns
import ( import (
"net" "net"
"syscall"
) )
// SessionUDP holds the remote address and the associated // SessionUDP holds the remote address and the associated
@ -17,29 +16,6 @@ type SessionUDP struct {
// RemoteAddr returns the remote network address. // RemoteAddr returns the remote network address.
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
func setUDPSocketOptions(conn *net.UDPConn) error {
sa, err := getUDPSocketName(conn)
if err != nil {
return err
}
switch sa.(type) {
case *syscall.SockaddrInet6:
v6only, err := getUDPSocketOptions6Only(conn)
if err != nil {
return err
}
setUDPSocketOptions6(conn)
if !v6only {
setUDPSocketOptions4(conn)
}
case *syscall.SockaddrInet4:
setUDPSocketOptions4(conn)
}
return nil
}
// ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a // ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
// net.UDPAddr. // net.UDPAddr.
func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) { func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {

View file

@ -1,4 +1,4 @@
// +build linux // +build linux,!appengine
package dns package dns
@ -15,6 +15,29 @@ import (
"syscall" "syscall"
) )
// setUDPSocketOptions sets the UDP socket options.
// This function is implemented on a per platform basis. See udp_*.go for more details
func setUDPSocketOptions(conn *net.UDPConn) error {
sa, err := getUDPSocketName(conn)
if err != nil {
return err
}
switch sa.(type) {
case *syscall.SockaddrInet6:
v6only, err := getUDPSocketOptions6Only(conn)
if err != nil {
return err
}
setUDPSocketOptions6(conn)
if !v6only {
setUDPSocketOptions4(conn)
}
case *syscall.SockaddrInet4:
setUDPSocketOptions4(conn)
}
return nil
}
// setUDPSocketOptions4 prepares the v4 socket for sessions. // setUDPSocketOptions4 prepares the v4 socket for sessions.
func setUDPSocketOptions4(conn *net.UDPConn) error { func setUDPSocketOptions4(conn *net.UDPConn) error {
file, err := conn.File() file, err := conn.File()
@ -22,14 +45,17 @@ func setUDPSocketOptions4(conn *net.UDPConn) error {
return err return err
} }
if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IP, syscall.IP_PKTINFO, 1); err != nil { if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IP, syscall.IP_PKTINFO, 1); err != nil {
file.Close()
return err return err
} }
// Calling File() above results in the connection becoming blocking, we must fix that. // Calling File() above results in the connection becoming blocking, we must fix that.
// See https://github.com/miekg/dns/issues/279 // See https://github.com/miekg/dns/issues/279
err = syscall.SetNonblock(int(file.Fd()), true) err = syscall.SetNonblock(int(file.Fd()), true)
if err != nil { if err != nil {
file.Close()
return err return err
} }
file.Close()
return nil return nil
} }
@ -40,12 +66,15 @@ func setUDPSocketOptions6(conn *net.UDPConn) error {
return err return err
} }
if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_RECVPKTINFO, 1); err != nil { if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_RECVPKTINFO, 1); err != nil {
file.Close()
return err return err
} }
err = syscall.SetNonblock(int(file.Fd()), true) err = syscall.SetNonblock(int(file.Fd()), true)
if err != nil { if err != nil {
file.Close()
return err return err
} }
file.Close()
return nil return nil
} }
@ -59,8 +88,10 @@ func getUDPSocketOptions6Only(conn *net.UDPConn) (bool, error) {
// dual stack. See http://stackoverflow.com/questions/1618240/how-to-support-both-ipv4-and-ipv6-connections // dual stack. See http://stackoverflow.com/questions/1618240/how-to-support-both-ipv4-and-ipv6-connections
v6only, err := syscall.GetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY) v6only, err := syscall.GetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY)
if err != nil { if err != nil {
file.Close()
return false, err return false, err
} }
file.Close()
return v6only == 1, nil return v6only == 1, nil
} }
@ -69,5 +100,6 @@ func getUDPSocketName(conn *net.UDPConn) (syscall.Sockaddr, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer file.Close()
return syscall.Getsockname(int(file.Fd())) return syscall.Getsockname(int(file.Fd()))
} }

View file

@ -1,17 +0,0 @@
// +build !linux,!plan9
package dns
import (
"net"
"syscall"
)
// These do nothing. See udp_linux.go for an example of how to implement this.
// We tried to adhire to some kind of naming scheme.
func setUDPSocketOptions4(conn *net.UDPConn) error { return nil }
func setUDPSocketOptions6(conn *net.UDPConn) error { return nil }
func getUDPSocketOptions6Only(conn *net.UDPConn) (bool, error) { return false, nil }
func getUDPSocketName(conn *net.UDPConn) (syscall.Sockaddr, error) { return nil, nil }

View file

@ -1,34 +0,0 @@
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
}

View file

@ -8,6 +8,8 @@ type SessionUDP struct {
raddr *net.UDPAddr raddr *net.UDPAddr
} }
func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
// ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a // ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
// net.UDPAddr. // net.UDPAddr.
func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) { func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
@ -25,10 +27,3 @@ func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, e
return n, err return n, err
} }
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
func setUDPSocketOptions(conn *net.UDPConn) error {
return nil
}

34
vendor/github.com/miekg/dns/zmsg.go generated vendored
View file

@ -221,7 +221,7 @@ func (rr *DNAME) pack(msg []byte, off int, compression map[string]int, compress
return off, err return off, err
} }
headerEnd := off headerEnd := off
off, err = PackDomainName(rr.Target, msg, off, compression, compress) off, err = PackDomainName(rr.Target, msg, off, compression, false)
if err != nil { if err != nil {
return off, err return off, err
} }
@ -447,7 +447,7 @@ func (rr *KX) pack(msg []byte, off int, compression map[string]int, compress boo
if err != nil { if err != nil {
return off, err return off, err
} }
off, err = PackDomainName(rr.Exchanger, msg, off, compression, compress) off, err = PackDomainName(rr.Exchanger, msg, off, compression, false)
if err != nil { if err != nil {
return off, err return off, err
} }
@ -539,7 +539,7 @@ func (rr *LP) pack(msg []byte, off int, compression map[string]int, compress boo
if err != nil { if err != nil {
return off, err return off, err
} }
off, err = PackDomainName(rr.Fqdn, msg, off, compression, compress) off, err = PackDomainName(rr.Fqdn, msg, off, compression, false)
if err != nil { if err != nil {
return off, err return off, err
} }
@ -679,7 +679,7 @@ func (rr *NAPTR) pack(msg []byte, off int, compression map[string]int, compress
if err != nil { if err != nil {
return off, err return off, err
} }
off, err = PackDomainName(rr.Replacement, msg, off, compression, compress) off, err = PackDomainName(rr.Replacement, msg, off, compression, false)
if err != nil { if err != nil {
return off, err return off, err
} }
@ -753,7 +753,7 @@ func (rr *NSAPPTR) pack(msg []byte, off int, compression map[string]int, compres
return off, err return off, err
} }
headerEnd := off headerEnd := off
off, err = PackDomainName(rr.Ptr, msg, off, compression, compress) off, err = PackDomainName(rr.Ptr, msg, off, compression, false)
if err != nil { if err != nil {
return off, err return off, err
} }
@ -767,7 +767,7 @@ func (rr *NSEC) pack(msg []byte, off int, compression map[string]int, compress b
return off, err return off, err
} }
headerEnd := off headerEnd := off
off, err = PackDomainName(rr.NextDomain, msg, off, compression, compress) off, err = PackDomainName(rr.NextDomain, msg, off, compression, false)
if err != nil { if err != nil {
return off, err return off, err
} }
@ -905,11 +905,11 @@ func (rr *PX) pack(msg []byte, off int, compression map[string]int, compress boo
if err != nil { if err != nil {
return off, err return off, err
} }
off, err = PackDomainName(rr.Map822, msg, off, compression, compress) off, err = PackDomainName(rr.Map822, msg, off, compression, false)
if err != nil { if err != nil {
return off, err return off, err
} }
off, err = PackDomainName(rr.Mapx400, msg, off, compression, compress) off, err = PackDomainName(rr.Mapx400, msg, off, compression, false)
if err != nil { if err != nil {
return off, err return off, err
} }
@ -963,11 +963,11 @@ func (rr *RP) pack(msg []byte, off int, compression map[string]int, compress boo
return off, err return off, err
} }
headerEnd := off headerEnd := off
off, err = PackDomainName(rr.Mbox, msg, off, compression, compress) off, err = PackDomainName(rr.Mbox, msg, off, compression, false)
if err != nil { if err != nil {
return off, err return off, err
} }
off, err = PackDomainName(rr.Txt, msg, off, compression, compress) off, err = PackDomainName(rr.Txt, msg, off, compression, false)
if err != nil { if err != nil {
return off, err return off, err
} }
@ -1009,7 +1009,7 @@ func (rr *RRSIG) pack(msg []byte, off int, compression map[string]int, compress
if err != nil { if err != nil {
return off, err return off, err
} }
off, err = PackDomainName(rr.SignerName, msg, off, compression, compress) off, err = PackDomainName(rr.SignerName, msg, off, compression, false)
if err != nil { if err != nil {
return off, err return off, err
} }
@ -1073,7 +1073,7 @@ func (rr *SIG) pack(msg []byte, off int, compression map[string]int, compress bo
if err != nil { if err != nil {
return off, err return off, err
} }
off, err = PackDomainName(rr.SignerName, msg, off, compression, compress) off, err = PackDomainName(rr.SignerName, msg, off, compression, false)
if err != nil { if err != nil {
return off, err return off, err
} }
@ -1181,7 +1181,7 @@ func (rr *SRV) pack(msg []byte, off int, compression map[string]int, compress bo
if err != nil { if err != nil {
return off, err return off, err
} }
off, err = PackDomainName(rr.Target, msg, off, compression, compress) off, err = PackDomainName(rr.Target, msg, off, compression, false)
if err != nil { if err != nil {
return off, err return off, err
} }
@ -1243,11 +1243,11 @@ func (rr *TALINK) pack(msg []byte, off int, compression map[string]int, compress
return off, err return off, err
} }
headerEnd := off headerEnd := off
off, err = PackDomainName(rr.PreviousName, msg, off, compression, compress) off, err = PackDomainName(rr.PreviousName, msg, off, compression, false)
if err != nil { if err != nil {
return off, err return off, err
} }
off, err = PackDomainName(rr.NextName, msg, off, compression, compress) off, err = PackDomainName(rr.NextName, msg, off, compression, false)
if err != nil { if err != nil {
return off, err return off, err
} }
@ -1261,7 +1261,7 @@ func (rr *TKEY) pack(msg []byte, off int, compression map[string]int, compress b
return off, err return off, err
} }
headerEnd := off headerEnd := off
off, err = PackDomainName(rr.Algorithm, msg, off, compression, compress) off, err = PackDomainName(rr.Algorithm, msg, off, compression, false)
if err != nil { if err != nil {
return off, err return off, err
} }
@ -1333,7 +1333,7 @@ func (rr *TSIG) pack(msg []byte, off int, compression map[string]int, compress b
return off, err return off, err
} }
headerEnd := off headerEnd := off
off, err = PackDomainName(rr.Algorithm, msg, off, compression, compress) off, err = PackDomainName(rr.Algorithm, msg, off, compression, false)
if err != nil { if err != nil {
return off, err return off, err
} }

6
vendor/vendor.json vendored
View file

@ -508,10 +508,10 @@
"revisionTime": "2015-04-06T19:39:34+02:00" "revisionTime": "2015-04-06T19:39:34+02:00"
}, },
{ {
"checksumSHA1": "Wahi4g/9XiHhSLAJ+8jskg71PCU=", "checksumSHA1": "wJxkqZ80Ux6+klKr1+3erSZjVnQ=",
"path": "github.com/miekg/dns", "path": "github.com/miekg/dns",
"revision": "58f52c57ce9df13460ac68200cef30a008b9c468", "revision": "672033dedc09500ca4d340760d0b80b9c0b198bd",
"revisionTime": "2016-10-18T06:08:08Z" "revisionTime": "2017-02-13T20:16:50Z"
}, },
{ {
"checksumSHA1": "3YJklSuzSE1Rt8A+2dhiWSmf/fw=", "checksumSHA1": "3YJklSuzSE1Rt8A+2dhiWSmf/fw=",