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 {
servAddr := net.JoinHostPort(server, conf.Port)
for _, suffix := range conf.Search {
response, err = lookup(name, qtype, client, servAddr, suffix, false)
for _, lname := range conf.NameList(name) {
response, err = lookup(lname, qtype, client, servAddr, false)
if err != nil {
log.
With("server", server).
With("name", name).
With("suffix", suffix).
With("reason", err).
Warn("DNS resolution failed.")
continue
@ -194,22 +193,12 @@ func lookupAll(name string, qtype uint16) (*dns.Msg, error) {
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)
}
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{}
lname := strings.Join([]string{name, suffix}, ".")
msg.SetQuestion(dns.Fqdn(lname), queryType)
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
client.Net = "tcp"
}
return lookup(name, queryType, client, servAddr, suffix, !edns)
return lookup(lname, queryType, client, servAddr, !edns)
}
if err != nil {
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
@ -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
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

View file

@ -300,6 +300,18 @@ func tcpMsgLen(t io.Reader) (int, error) {
if err != nil {
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 {
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))
return int(n), err
}
n, err = co.Conn.(*net.UDPConn).Write(p)
n, err = co.Conn.Write(p)
return n, err
}

View file

@ -97,3 +97,35 @@ func ClientConfigFromFile(resolvconf string) (*ClientConfig, error) {
}
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"
"encoding/hex"
"errors"
"io"
)
// 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()
switch selector {
case 0:
io.WriteString(h, string(cert.Raw))
h.Write(cert.Raw)
return hex.EncodeToString(h.Sum(nil)), nil
case 1:
io.WriteString(h, string(cert.RawSubjectPublicKeyInfo))
h.Write(cert.RawSubjectPublicKeyInfo)
return hex.EncodeToString(h.Sum(nil)), nil
}
case 2:
h := sha512.New()
switch selector {
case 0:
io.WriteString(h, string(cert.Raw))
h.Write(cert.Raw)
return hex.EncodeToString(h.Sum(nil)), nil
case 1:
io.WriteString(h, string(cert.RawSubjectPublicKeyInfo))
h.Write(cert.RawSubjectPublicKeyInfo)
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.
// 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.
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.Hdr = RR_Header{z, TypeTSIG, ClassANY, 0, 0}
t.Algorithm = algo
t.Fudge = 300
t.Fudge = fudge
t.TimeSigned = uint64(timesigned)
t.OrigId = dns.Id
dns.Extra = append(dns.Extra, t)

View file

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

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

@ -4,6 +4,7 @@ import (
"encoding/binary"
"encoding/hex"
"errors"
"fmt"
"net"
"strconv"
)
@ -19,6 +20,7 @@ const (
EDNS0SUBNET = 0x8 // client-subnet (RFC6891)
EDNS0EXPIRE = 0x9 // EDNS0 expire
EDNS0COOKIE = 0xa // EDNS0 Cookie
EDNS0TCPKEEPALIVE = 0xb // EDNS0 tcp keep alive (RFC7828)
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)
@ -195,7 +197,7 @@ func (e *EDNS0_NSID) String() string { return string(e.Nsid) }
// e := new(dns.EDNS0_SUBNET)
// e.Code = dns.EDNS0SUBNET
// 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.Address = net.ParseIP("127.0.0.1").To4() // for IPv4
// // e.Address = net.ParseIP("2001:7b8:32a::2") // for IPV6
@ -540,3 +542,56 @@ func (e *EDNS0_LOCAL) unpack(b []byte) error {
}
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/rand"
"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
var (
@ -66,11 +53,45 @@ var (
// dns.Id = func() uint16 { return 3 }
var Id func() uint16 = id
var (
idLock sync.Mutex
idRand *rand.Rand
)
// id returns a 16 bits random number to be used as a
// message id. The random provided should be good enough.
func id() uint16 {
id32 := rand.Uint32()
return uint16(id32)
idLock.Lock()
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).
@ -203,12 +224,6 @@ func packDomainName(s string, msg []byte, off int, compression map[string]int, c
bs[j] = bs[j+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] == '.'
bsFresh = false
@ -335,10 +350,6 @@ Loop:
fallthrough
case '"', '\\':
s = append(s, '\\', b)
case '\t':
s = append(s, '\\', 't')
case '\r':
s = append(s, '\\', 'r')
default:
if b < 32 || b >= 127 { // unprintable use \DDD
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]) {
msg[offset] = dddToByte(bs[i:])
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 {
msg[offset] = bs[i]
}
@ -508,12 +513,6 @@ func unpackTxtString(msg []byte, offset int) (string, int, error) {
switch b {
case '"', '\\':
s = append(s, '\\', b)
case '\t':
s = append(s, `\t`...)
case '\r':
s = append(s, `\r`...)
case '\n':
s = append(s, `\n`...)
default:
if b < 32 || b > 127 { // unprintable
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 {
return err
}
if off == len(msg) {
return ErrTruncated
}
dns.Id = dh.Id
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.Rcode = int(dh.Bits & 0xF)
if off == len(msg) {
return ErrTruncated
}
// Optimistically use the count given to us in the header
dns.Question = make([]Question, 0, int(dh.Qdcount))

View file

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

View file

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

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

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

View file

@ -64,20 +64,19 @@ func endingToString(c chan lex, errstr, f string) (string, *ParseError, string)
return s, nil, l.comment
}
// A remainder of the rdata with embedded spaces, return the parsed string slice (sans the spaces)
// or an error
// A remainder of the rdata with embedded spaces, split on unquoted whitespace
// and return the parsed string slice or an error
func endingToTxtSlice(c chan lex, errstr, f string) ([]string, *ParseError, string) {
// Get the remaining data until we see a zNewline
quote := false
l := <-c
var s []string
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
// Build the slice
s := make([]string, 0)
quote := false
empty := false
for l.value != zNewline && l.value != zEOF {
if l.err {
return nil, &ParseError{f, errstr, l}, ""
@ -123,16 +122,6 @@ func endingToTxtSlice(c chan lex, errstr, f string) ([]string, *ParseError, stri
if quote {
return nil, &ParseError{f, errstr, l}, ""
}
case false: // Unquoted text record
s = make([]string, 1)
for l.value != zNewline && l.value != zEOF {
if l.err {
return s, &ParseError{f, errstr, l}, ""
}
s[0] += l.token
l = <-c
}
}
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
s, e, c1 := endingToTxtSlice(c, "bad UINFO Uinfo", f)
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
}

View file

@ -339,7 +339,7 @@ func (srv *Server) ListenAndServe() error {
network := "tcp"
if srv.Net == "tcp4-tls" {
network = "tcp4"
} else if srv.Net == "tcp6" {
} else if srv.Net == "tcp6-tls" {
network = "tcp6"
}
@ -389,7 +389,9 @@ func (srv *Server) ActivateAndServe() error {
if srv.UDPSize == 0 {
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 {
return e
}

View file

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

View file

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

17
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 {
switch b {
case '\t':
return append(s, '\\', 't')
case '\r':
return append(s, '\\', 'r')
case '\n':
return append(s, '\\', 'n')
case '"', '\\':
return append(s, '\\', b)
}
@ -525,17 +519,8 @@ func nextByte(b []byte, offset int) (byte, int) {
return dddToByte(b[offset+1:]), 4
}
}
// not \ddd, maybe a control char
switch b[offset+1] {
case 't':
return '\t', 2
case 'r':
return '\r', 2
case 'n':
return '\n', 2
default:
// not \ddd, just an RFC 1035 "quoted" character
return b[offset+1], 2
}
}
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
import (
"net"
"syscall"
)
// SessionUDP holds the remote address and the associated
@ -17,29 +16,6 @@ type SessionUDP struct {
// 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
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
// net.UDPAddr.
func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {

View file

@ -1,4 +1,4 @@
// +build linux
// +build linux,!appengine
package dns
@ -15,6 +15,29 @@ import (
"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.
func setUDPSocketOptions4(conn *net.UDPConn) error {
file, err := conn.File()
@ -22,14 +45,17 @@ func setUDPSocketOptions4(conn *net.UDPConn) error {
return err
}
if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IP, syscall.IP_PKTINFO, 1); err != nil {
file.Close()
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 {
file.Close()
return err
}
file.Close()
return nil
}
@ -40,12 +66,15 @@ func setUDPSocketOptions6(conn *net.UDPConn) error {
return err
}
if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_RECVPKTINFO, 1); err != nil {
file.Close()
return err
}
err = syscall.SetNonblock(int(file.Fd()), true)
if err != nil {
file.Close()
return err
}
file.Close()
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
v6only, err := syscall.GetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY)
if err != nil {
file.Close()
return false, err
}
file.Close()
return v6only == 1, nil
}
@ -69,5 +100,6 @@ func getUDPSocketName(conn *net.UDPConn) (syscall.Sockaddr, error) {
if err != nil {
return nil, err
}
defer file.Close()
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
}
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) {
@ -25,10 +27,3 @@ func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, e
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
}
headerEnd := off
off, err = PackDomainName(rr.Target, msg, off, compression, compress)
off, err = PackDomainName(rr.Target, msg, off, compression, false)
if err != nil {
return off, err
}
@ -447,7 +447,7 @@ func (rr *KX) pack(msg []byte, off int, compression map[string]int, compress boo
if err != nil {
return off, err
}
off, err = PackDomainName(rr.Exchanger, msg, off, compression, compress)
off, err = PackDomainName(rr.Exchanger, msg, off, compression, false)
if err != nil {
return off, err
}
@ -539,7 +539,7 @@ func (rr *LP) pack(msg []byte, off int, compression map[string]int, compress boo
if err != nil {
return off, err
}
off, err = PackDomainName(rr.Fqdn, msg, off, compression, compress)
off, err = PackDomainName(rr.Fqdn, msg, off, compression, false)
if err != nil {
return off, err
}
@ -679,7 +679,7 @@ func (rr *NAPTR) pack(msg []byte, off int, compression map[string]int, compress
if err != nil {
return off, err
}
off, err = PackDomainName(rr.Replacement, msg, off, compression, compress)
off, err = PackDomainName(rr.Replacement, msg, off, compression, false)
if err != nil {
return off, err
}
@ -753,7 +753,7 @@ func (rr *NSAPPTR) pack(msg []byte, off int, compression map[string]int, compres
return off, err
}
headerEnd := off
off, err = PackDomainName(rr.Ptr, msg, off, compression, compress)
off, err = PackDomainName(rr.Ptr, msg, off, compression, false)
if err != nil {
return off, err
}
@ -767,7 +767,7 @@ func (rr *NSEC) pack(msg []byte, off int, compression map[string]int, compress b
return off, err
}
headerEnd := off
off, err = PackDomainName(rr.NextDomain, msg, off, compression, compress)
off, err = PackDomainName(rr.NextDomain, msg, off, compression, false)
if err != nil {
return off, err
}
@ -905,11 +905,11 @@ func (rr *PX) pack(msg []byte, off int, compression map[string]int, compress boo
if err != nil {
return off, err
}
off, err = PackDomainName(rr.Map822, msg, off, compression, compress)
off, err = PackDomainName(rr.Map822, msg, off, compression, false)
if err != nil {
return off, err
}
off, err = PackDomainName(rr.Mapx400, msg, off, compression, compress)
off, err = PackDomainName(rr.Mapx400, msg, off, compression, false)
if err != nil {
return off, err
}
@ -963,11 +963,11 @@ func (rr *RP) pack(msg []byte, off int, compression map[string]int, compress boo
return off, err
}
headerEnd := off
off, err = PackDomainName(rr.Mbox, msg, off, compression, compress)
off, err = PackDomainName(rr.Mbox, msg, off, compression, false)
if err != nil {
return off, err
}
off, err = PackDomainName(rr.Txt, msg, off, compression, compress)
off, err = PackDomainName(rr.Txt, msg, off, compression, false)
if err != nil {
return off, err
}
@ -1009,7 +1009,7 @@ func (rr *RRSIG) pack(msg []byte, off int, compression map[string]int, compress
if err != nil {
return off, err
}
off, err = PackDomainName(rr.SignerName, msg, off, compression, compress)
off, err = PackDomainName(rr.SignerName, msg, off, compression, false)
if err != nil {
return off, err
}
@ -1073,7 +1073,7 @@ func (rr *SIG) pack(msg []byte, off int, compression map[string]int, compress bo
if err != nil {
return off, err
}
off, err = PackDomainName(rr.SignerName, msg, off, compression, compress)
off, err = PackDomainName(rr.SignerName, msg, off, compression, false)
if err != nil {
return off, err
}
@ -1181,7 +1181,7 @@ func (rr *SRV) pack(msg []byte, off int, compression map[string]int, compress bo
if err != nil {
return off, err
}
off, err = PackDomainName(rr.Target, msg, off, compression, compress)
off, err = PackDomainName(rr.Target, msg, off, compression, false)
if err != nil {
return off, err
}
@ -1243,11 +1243,11 @@ func (rr *TALINK) pack(msg []byte, off int, compression map[string]int, compress
return off, err
}
headerEnd := off
off, err = PackDomainName(rr.PreviousName, msg, off, compression, compress)
off, err = PackDomainName(rr.PreviousName, msg, off, compression, false)
if err != nil {
return off, err
}
off, err = PackDomainName(rr.NextName, msg, off, compression, compress)
off, err = PackDomainName(rr.NextName, msg, off, compression, false)
if err != nil {
return off, err
}
@ -1261,7 +1261,7 @@ func (rr *TKEY) pack(msg []byte, off int, compression map[string]int, compress b
return off, err
}
headerEnd := off
off, err = PackDomainName(rr.Algorithm, msg, off, compression, compress)
off, err = PackDomainName(rr.Algorithm, msg, off, compression, false)
if err != nil {
return off, err
}
@ -1333,7 +1333,7 @@ func (rr *TSIG) pack(msg []byte, off int, compression map[string]int, compress b
return off, err
}
headerEnd := off
off, err = PackDomainName(rr.Algorithm, msg, off, compression, compress)
off, err = PackDomainName(rr.Algorithm, msg, off, compression, false)
if err != nil {
return off, err
}

6
vendor/vendor.json vendored
View file

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