Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
language: go
go:
- 1.6
- 1.7
- 1.8
- master
Expand Down
12 changes: 7 additions & 5 deletions resolver_miekg.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"sync"

"github.com/miekg/dns"
"strings"
)

// NewMiekgDNSResolver returns new instance of Resolver
Expand Down Expand Up @@ -66,7 +67,7 @@ func (r *MiekgDNSResolver) LookupTXT(name string) ([]string, error) {
txts := make([]string, 0, len(res.Answer))
for _, a := range res.Answer {
if r, ok := a.(*dns.TXT); ok {
txts = append(txts, r.Txt...)
txts = append(txts, strings.Join(r.Txt,""))
}
}
return txts, nil
Expand All @@ -91,7 +92,7 @@ func (r *MiekgDNSResolver) LookupTXTStrict(name string) ([]string, error) {
txts := make([]string, 0, len(res.Answer))
for _, a := range res.Answer {
if r, ok := a.(*dns.TXT); ok {
txts = append(txts, r.Txt...)
txts = append(txts, strings.Join(r.Txt,""))
}
}
return txts, nil
Expand Down Expand Up @@ -134,9 +135,10 @@ func matchIP(rrs []dns.RR, matcher IPMatcherFunc) (bool, error) {
// If any address matches, the mechanism matches
func (r *MiekgDNSResolver) MatchIP(name string, matcher IPMatcherFunc) (bool, error) {
var wg sync.WaitGroup
hits := make(chan hit)
qTypes := []uint16{dns.TypeA, dns.TypeAAAA}
hits := make(chan hit, len(qTypes))

for _, qType := range []uint16{dns.TypeA, dns.TypeAAAA} {
for _, qType := range qTypes {
wg.Add(1)
go func(qType uint16) {
defer wg.Done()
Expand Down Expand Up @@ -184,7 +186,7 @@ func (r *MiekgDNSResolver) MatchMX(name string, matcher IPMatcherFunc) (bool, er
}

var wg sync.WaitGroup
hits := make(chan hit)
hits := make(chan hit, len(res.Answer))

for _, rr := range res.Answer {
mx, ok := rr.(*dns.MX)
Expand Down
44 changes: 43 additions & 1 deletion resolver_miekg_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,52 @@
package spf

import "testing"
import (
"testing"

"github.com/miekg/dns"
)

func TestMiekgDNSResolver(t *testing.T) {
_, e := NewMiekgDNSResolver("8.8.8.8") // invalid TCP address, no port specified
if e == nil {
t.Errorf(`want "address 8.8.8.8: missing port in address"`)
}
}

func TestMiekgDNSResolver_LookupTXTStrict_Multiline(t *testing.T) {
dns.HandleFunc("multiline.test.", zone(map[uint16][]string{
dns.TypeTXT: {
`multiline.test. 0 IN TXT "v=spf1 ip4:10.0.0.1 ip4:10.0.0" ".2 -all"`,
},
}))
defer dns.HandleRemove("multiline.test.")

r, e := testResolver.LookupTXTStrict("multiline.test.")

if e != nil {
t.Fatal(e)
}

if len(r) != 1 {
t.Errorf("want 1 got %d", len(r))
}
}

func TestMiekgDNSResolver_LookupTXT_Multiline(t *testing.T) {
dns.HandleFunc("multiline.test.", zone(map[uint16][]string{
dns.TypeTXT: {
`multiline.test. 0 IN TXT "v=spf1 ip4:10.0.0.1 ip4:10.0.0" ".2 -all"`,
},
}))
defer dns.HandleRemove("multiline.test.")

r, e := testResolver.LookupTXT("multiline.test.")

if e != nil {
t.Fatal(e)
}

if len(r) != 1 {
t.Errorf("want 1 got %d", len(r))
}
}
46 changes: 24 additions & 22 deletions resolver_std.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ import (
// DNSResolver implements Resolver using local DNS
type DNSResolver struct{}

func errDNS(e error) error {
if e == nil {
return nil
}
func isNoHost(e error) bool {
if dnsErr, ok := e.(*net.DNSError); ok {
// That is the most reliable way I found to detect Permerror
// https://github.com/golang/go/blob/master/src/net/dnsclient.go#L43
Expand All @@ -25,8 +22,27 @@ func errDNS(e error) error {
// the mechanism continues as if the server returned no error (RCODE
// 0) and zero answer records.
if dnsErr.Err == "no such host" {
return nil
return true
}
if dnsErr.Err == "dnsquery: DNS name does not exist." {
return true
}
if dnsErr.Err == "dnsquery: DNS record does not exist." {
return true
}
if dnsErr.Err == "dnsquery: No records found for given DNS query." {
return true
}
}
return false
}

func errDNS(e error) error {
if e == nil {
return nil
}
if isNoHost(e) {
return nil
}
return ErrDNSTemperror
}
Expand All @@ -36,23 +52,9 @@ func errDNS(e error) error {
func (r *DNSResolver) LookupTXTStrict(name string) ([]string, error) {
txts, err := net.LookupTXT(name)

if dnsErr, ok := err.(*net.DNSError); ok {
// That is the most reliable way I found to detect Permerror
// https://github.com/golang/go/blob/master/src/net/dnsclient.go#L43
// Upon RCODE 3 return code we should return None result and pretend no
// From RFC7208:
// Several mechanisms rely on information fetched from the DNS. For
// these DNS queries, except where noted, if the DNS server returns an
// error (RCODE other than 0 or 3) or the query times out, the
// mechanism stops and the topmost check_host() returns "temperror".
// If the server returns "Name Error" (RCODE 3), then evaluation of
// the mechanism continues as if the server returned no error (RCODE
// 0) and zero answer records.
if dnsErr.Err == "no such host" {
return nil, ErrDNSPermerror
}
if isNoHost(err) {
return nil, ErrDNSPermerror
}

err = errDNS(err)
if err != nil {
return nil, err
Expand Down Expand Up @@ -117,7 +119,7 @@ func (r *DNSResolver) MatchMX(name string, matcher IPMatcherFunc) (bool, error)
}

var wg sync.WaitGroup
hits := make(chan hit)
hits := make(chan hit, len(mxs))

for _, mx := range mxs {
wg.Add(1)
Expand Down