diff --git a/internal/netxlite/classify.go b/internal/netxlite/classify.go index 4e0b1b2370..00eec6770d 100644 --- a/internal/netxlite/classify.go +++ b/internal/netxlite/classify.go @@ -248,11 +248,17 @@ const ( // unexported errors used by the Go standard library. var ( ErrOODNSNoSuchHost = fmt.Errorf("ooniresolver: %s", DNSNoSuchHostSuffix) - ErrOODNSRefused = errors.New("ooniresolver: refused") ErrOODNSMisbehaving = fmt.Errorf("ooniresolver: %s", DNSServerMisbehavingSuffix) ErrOODNSNoAnswer = fmt.Errorf("ooniresolver: %s", DNSNoAnswerSuffix) ) +// These errors are not part of the Go standard library but we can +// return them in our custom resolvers. +var ( + ErrOODNSRefused = errors.New("ooniresolver: refused") + ErrOODNSServfail = errors.New("ooniresolver: servfail") +) + // classifyResolverError maps DNS resolution errors to // OONI failure strings. // @@ -278,6 +284,9 @@ func classifyResolverError(err error) string { if errors.Is(err, ErrOODNSRefused) { return FailureDNSRefusedError // not in MK } + if errors.Is(err, ErrOODNSServfail) { + return FailureDNSServfailError + } return classifyGenericError(err) } diff --git a/internal/netxlite/classify_test.go b/internal/netxlite/classify_test.go index 22c4949d43..69f1d16ab7 100644 --- a/internal/netxlite/classify_test.go +++ b/internal/netxlite/classify_test.go @@ -269,6 +269,12 @@ func TestClassifyResolverError(t *testing.T) { } }) + t.Run("for servfail", func(t *testing.T) { + if classifyResolverError(ErrOODNSServfail) != FailureDNSServfailError { + t.Fatal("unexpected result") + } + }) + t.Run("for another kind of error", func(t *testing.T) { if classifyResolverError(io.EOF) != FailureEOFError { t.Fatal("unexpected result") diff --git a/internal/netxlite/dnsdecoder.go b/internal/netxlite/dnsdecoder.go index 6a08e0a261..ee0b564afe 100644 --- a/internal/netxlite/dnsdecoder.go +++ b/internal/netxlite/dnsdecoder.go @@ -22,6 +22,8 @@ func (d *DNSDecoderMiekg) parseReply(data []byte) (*dns.Msg, error) { return nil, ErrOODNSNoSuchHost case dns.RcodeRefused: return nil, ErrOODNSRefused + case dns.RcodeServerFailure: + return nil, ErrOODNSServfail default: return nil, ErrOODNSMisbehaving } diff --git a/internal/netxlite/dnsdecoder_test.go b/internal/netxlite/dnsdecoder_test.go index c3e12895ba..9915502aa9 100644 --- a/internal/netxlite/dnsdecoder_test.go +++ b/internal/netxlite/dnsdecoder_test.go @@ -47,6 +47,18 @@ func TestDNSDecoder(t *testing.T) { } }) + t.Run("Servfail", func(t *testing.T) { + d := &DNSDecoderMiekg{} + data, err := d.DecodeLookupHost( + dns.TypeA, dnsGenReplyWithError(t, dns.TypeA, dns.RcodeServerFailure)) + if !errors.Is(err, ErrOODNSServfail) { + t.Fatal("not the error we expected", err) + } + if data != nil { + t.Fatal("expected nil data here") + } + }) + t.Run("no address", func(t *testing.T) { d := &DNSDecoderMiekg{} data, err := d.DecodeLookupHost(dns.TypeA, dnsGenLookupHostReplySuccess(t, dns.TypeA)) diff --git a/internal/netxlite/dnsencoder_test.go b/internal/netxlite/dnsencoder_test.go index 10257f0802..fabdd89f73 100644 --- a/internal/netxlite/dnsencoder_test.go +++ b/internal/netxlite/dnsencoder_test.go @@ -8,7 +8,6 @@ import ( ) func TestDNSEncoder(t *testing.T) { - t.Run("encode A", func(t *testing.T) { e := &DNSEncoderMiekg{} data, err := e.Encode("x.org", dns.TypeA, false) diff --git a/internal/netxlite/errno.go b/internal/netxlite/errno.go index 509cbeca62..456d86b6a8 100644 --- a/internal/netxlite/errno.go +++ b/internal/netxlite/errno.go @@ -1,5 +1,5 @@ // Code generated by go generate; DO NOT EDIT. -// Generated: 2022-04-12 11:15:59.316541 +0200 CEST m=+0.537932501 +// Generated: 2022-05-13 19:09:07.343096 +0200 CEST m=+0.512294417 package netxlite @@ -26,6 +26,7 @@ const ( FailureDNSNonRecoverableFailure = "dns_non_recoverable_failure" FailureDNSRefusedError = "dns_refused_error" FailureDNSServerMisbehaving = "dns_server_misbehaving" + FailureDNSServfailError = "dns_servfail_error" FailureDNSTemporaryFailure = "dns_temporary_failure" FailureDestinationAddressRequired = "destination_address_required" FailureEOFError = "eof_error" @@ -75,6 +76,7 @@ var failuresMap = map[string]string{ "dns_nxdomain_error": "dns_nxdomain_error", "dns_refused_error": "dns_refused_error", "dns_server_misbehaving": "dns_server_misbehaving", + "dns_servfail_error": "dns_servfail_error", "dns_temporary_failure": "dns_temporary_failure", "eof_error": "eof_error", "generic_timeout_error": "generic_timeout_error", diff --git a/internal/netxlite/internal/generrno/main.go b/internal/netxlite/internal/generrno/main.go index 6a878ceb3c..8de21437a2 100644 --- a/internal/netxlite/internal/generrno/main.go +++ b/internal/netxlite/internal/generrno/main.go @@ -158,6 +158,7 @@ var Specs = []*ErrorSpec{ NewLibraryError("DNS_refused_error"), NewLibraryError("DNS_server_misbehaving"), NewLibraryError("DNS_no_answer"), + NewLibraryError("DNS_servfail_error"), NewLibraryError("EOF_error"), NewLibraryError("generic_timeout_error"), NewLibraryError("QUIC_incompatible_version"),