fix(netxlite): map additional GetAddrInfoW errors (#521)
On Windows, GetAddrInfoW is a syscall and the Go resolver does not attempt to map errors beyond WSA_HOST_NOT_FOUND, which becomes "no such host", which we map to "dns_nxdomain_error". See https://github.com/golang/go/blob/go1.17.1/src/net/lookup_windows.go#L16. To map more GetAddrInfoW errors, thus, we need to enhance our error classifier to have system specific errors. Then, we need to filter for the WSA errors that are most likely to pop up and map them to OONI failures. Those are three: - WSANO_DATA which we have from our own UDP resolver as well and which we can map to `dns_no_answer` - WSANO_RECOVERY which we don't have but existed for MK so we will use `dns_non_recoverable_failure`, which was an MK error - WSATRY_AGAIN which likewise we map to the error that MK used to emit, so `dns_temporary_failure` This diff should address https://github.com/ooni/probe/issues/1467.
This commit is contained in:
parent
9523753b87
commit
9967803c31
15 changed files with 1648 additions and 221 deletions
|
|
@ -1,25 +1,13 @@
|
|||
// Code generated by go generate; DO NOT EDIT.
|
||||
// Generated: 2021-09-28 18:13:54.361886 +0200 CEST m=+0.453564501
|
||||
// Generated: 2021-09-29 10:33:56.711301 +0200 CEST m=+0.645971001
|
||||
|
||||
package netxlite
|
||||
|
||||
//go:generate go run ./internal/generrno/
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// This enumeration lists the failures defined at
|
||||
// https://github.com/ooni/spec/blob/master/data-formats/df-007-errors.md
|
||||
const (
|
||||
//
|
||||
// System errors
|
||||
//
|
||||
FailureConnectionRefused = "connection_refused"
|
||||
FailureConnectionReset = "connection_reset"
|
||||
FailureHostUnreachable = "host_unreachable"
|
||||
FailureTimedOut = "timed_out"
|
||||
FailureAddressFamilyNotSupported = "address_family_not_supported"
|
||||
FailureAddressInUse = "address_in_use"
|
||||
FailureAddressNotAvailable = "address_not_available"
|
||||
|
|
@ -27,10 +15,24 @@ const (
|
|||
FailureBadAddress = "bad_address"
|
||||
FailureBadFileDescriptor = "bad_file_descriptor"
|
||||
FailureConnectionAborted = "connection_aborted"
|
||||
FailureConnectionAlreadyClosed = "connection_already_closed"
|
||||
FailureConnectionAlreadyInProgress = "connection_already_in_progress"
|
||||
FailureConnectionRefused = "connection_refused"
|
||||
FailureConnectionReset = "connection_reset"
|
||||
FailureDNSBogonError = "dns_bogon_error"
|
||||
FailureDNSNXDOMAINError = "dns_nxdomain_error"
|
||||
FailureDNSNoAnswer = "dns_no_answer"
|
||||
FailureDNSNonRecoverableFailure = "dns_non_recoverable_failure"
|
||||
FailureDNSRefusedError = "dns_refused_error"
|
||||
FailureDNSServerMisbehaving = "dns_server_misbehaving"
|
||||
FailureDNSTemporaryFailure = "dns_temporary_failure"
|
||||
FailureDestinationAddressRequired = "destination_address_required"
|
||||
FailureEOFError = "eof_error"
|
||||
FailureGenericTimeoutError = "generic_timeout_error"
|
||||
FailureHostUnreachable = "host_unreachable"
|
||||
FailureInterrupted = "interrupted"
|
||||
FailureInvalidArgument = "invalid_argument"
|
||||
FailureJSONParseError = "json_parse_error"
|
||||
FailureMessageSize = "message_size"
|
||||
FailureNetworkDown = "network_down"
|
||||
FailureNetworkReset = "network_reset"
|
||||
|
|
@ -42,34 +44,18 @@ const (
|
|||
FailureOperationWouldBlock = "operation_would_block"
|
||||
FailurePermissionDenied = "permission_denied"
|
||||
FailureProtocolNotSupported = "protocol_not_supported"
|
||||
FailureQUICIncompatibleVersion = "quic_incompatible_version"
|
||||
FailureSSLFailedHandshake = "ssl_failed_handshake"
|
||||
FailureSSLInvalidCertificate = "ssl_invalid_certificate"
|
||||
FailureSSLInvalidHostname = "ssl_invalid_hostname"
|
||||
FailureSSLUnknownAuthority = "ssl_unknown_authority"
|
||||
FailureTimedOut = "timed_out"
|
||||
FailureWrongProtocolType = "wrong_protocol_type"
|
||||
|
||||
//
|
||||
// Library errors
|
||||
//
|
||||
FailureDNSBogonError = "dns_bogon_error"
|
||||
FailureDNSNXDOMAINError = "dns_nxdomain_error"
|
||||
FailureDNSRefusedError = "dns_refused_error"
|
||||
FailureDNSServerMisbehaving = "dns_server_misbehaving"
|
||||
FailureDNSNoAnswer = "dns_no_answer"
|
||||
FailureEOFError = "eof_error"
|
||||
FailureGenericTimeoutError = "generic_timeout_error"
|
||||
FailureQUICIncompatibleVersion = "quic_incompatible_version"
|
||||
FailureSSLFailedHandshake = "ssl_failed_handshake"
|
||||
FailureSSLInvalidHostname = "ssl_invalid_hostname"
|
||||
FailureSSLUnknownAuthority = "ssl_unknown_authority"
|
||||
FailureSSLInvalidCertificate = "ssl_invalid_certificate"
|
||||
FailureJSONParseError = "json_parse_error"
|
||||
FailureConnectionAlreadyClosed = "connection_already_closed"
|
||||
)
|
||||
|
||||
// failureMap lists all failures so we can match them
|
||||
// when they are wrapped by quic.TransportError.
|
||||
var failuresMap = map[string]string{
|
||||
"connection_refused": "connection_refused",
|
||||
"connection_reset": "connection_reset",
|
||||
"host_unreachable": "host_unreachable",
|
||||
"timed_out": "timed_out",
|
||||
"address_family_not_supported": "address_family_not_supported",
|
||||
"address_in_use": "address_in_use",
|
||||
"address_not_available": "address_not_available",
|
||||
|
|
@ -77,10 +63,24 @@ var failuresMap = map[string]string{
|
|||
"bad_address": "bad_address",
|
||||
"bad_file_descriptor": "bad_file_descriptor",
|
||||
"connection_aborted": "connection_aborted",
|
||||
"connection_already_closed": "connection_already_closed",
|
||||
"connection_already_in_progress": "connection_already_in_progress",
|
||||
"connection_refused": "connection_refused",
|
||||
"connection_reset": "connection_reset",
|
||||
"destination_address_required": "destination_address_required",
|
||||
"dns_bogon_error": "dns_bogon_error",
|
||||
"dns_no_answer": "dns_no_answer",
|
||||
"dns_non_recoverable_failure": "dns_non_recoverable_failure",
|
||||
"dns_nxdomain_error": "dns_nxdomain_error",
|
||||
"dns_refused_error": "dns_refused_error",
|
||||
"dns_server_misbehaving": "dns_server_misbehaving",
|
||||
"dns_temporary_failure": "dns_temporary_failure",
|
||||
"eof_error": "eof_error",
|
||||
"generic_timeout_error": "generic_timeout_error",
|
||||
"host_unreachable": "host_unreachable",
|
||||
"interrupted": "interrupted",
|
||||
"invalid_argument": "invalid_argument",
|
||||
"json_parse_error": "json_parse_error",
|
||||
"message_size": "message_size",
|
||||
"network_down": "network_down",
|
||||
"network_reset": "network_reset",
|
||||
|
|
@ -92,86 +92,11 @@ var failuresMap = map[string]string{
|
|||
"operation_would_block": "operation_would_block",
|
||||
"permission_denied": "permission_denied",
|
||||
"protocol_not_supported": "protocol_not_supported",
|
||||
"wrong_protocol_type": "wrong_protocol_type",
|
||||
"dns_bogon_error": "dns_bogon_error",
|
||||
"dns_nxdomain_error": "dns_nxdomain_error",
|
||||
"dns_refused_error": "dns_refused_error",
|
||||
"dns_server_misbehaving": "dns_server_misbehaving",
|
||||
"dns_no_answer": "dns_no_answer",
|
||||
"eof_error": "eof_error",
|
||||
"generic_timeout_error": "generic_timeout_error",
|
||||
"quic_incompatible_version": "quic_incompatible_version",
|
||||
"ssl_failed_handshake": "ssl_failed_handshake",
|
||||
"ssl_invalid_certificate": "ssl_invalid_certificate",
|
||||
"ssl_invalid_hostname": "ssl_invalid_hostname",
|
||||
"ssl_unknown_authority": "ssl_unknown_authority",
|
||||
"ssl_invalid_certificate": "ssl_invalid_certificate",
|
||||
"json_parse_error": "json_parse_error",
|
||||
"connection_already_closed": "connection_already_closed",
|
||||
}
|
||||
|
||||
// classifySyscallError converts a syscall error to the
|
||||
// proper OONI error. Returns the OONI error string
|
||||
// on success, an empty string otherwise.
|
||||
func classifySyscallError(err error) string {
|
||||
var errno syscall.Errno
|
||||
if !errors.As(err, &errno) {
|
||||
return ""
|
||||
}
|
||||
switch errno {
|
||||
case ECONNREFUSED:
|
||||
return FailureConnectionRefused
|
||||
case ECONNRESET:
|
||||
return FailureConnectionReset
|
||||
case EHOSTUNREACH:
|
||||
return FailureHostUnreachable
|
||||
case ETIMEDOUT:
|
||||
return FailureTimedOut
|
||||
case EAFNOSUPPORT:
|
||||
return FailureAddressFamilyNotSupported
|
||||
case EADDRINUSE:
|
||||
return FailureAddressInUse
|
||||
case EADDRNOTAVAIL:
|
||||
return FailureAddressNotAvailable
|
||||
case EISCONN:
|
||||
return FailureAlreadyConnected
|
||||
case EFAULT:
|
||||
return FailureBadAddress
|
||||
case EBADF:
|
||||
return FailureBadFileDescriptor
|
||||
case ECONNABORTED:
|
||||
return FailureConnectionAborted
|
||||
case EALREADY:
|
||||
return FailureConnectionAlreadyInProgress
|
||||
case EDESTADDRREQ:
|
||||
return FailureDestinationAddressRequired
|
||||
case EINTR:
|
||||
return FailureInterrupted
|
||||
case EINVAL:
|
||||
return FailureInvalidArgument
|
||||
case EMSGSIZE:
|
||||
return FailureMessageSize
|
||||
case ENETDOWN:
|
||||
return FailureNetworkDown
|
||||
case ENETRESET:
|
||||
return FailureNetworkReset
|
||||
case ENETUNREACH:
|
||||
return FailureNetworkUnreachable
|
||||
case ENOBUFS:
|
||||
return FailureNoBufferSpace
|
||||
case ENOPROTOOPT:
|
||||
return FailureNoProtocolOption
|
||||
case ENOTSOCK:
|
||||
return FailureNotASocket
|
||||
case ENOTCONN:
|
||||
return FailureNotConnected
|
||||
case EWOULDBLOCK:
|
||||
return FailureOperationWouldBlock
|
||||
case EACCES:
|
||||
return FailurePermissionDenied
|
||||
case EPROTONOSUPPORT:
|
||||
return FailureProtocolNotSupported
|
||||
case EPROTOTYPE:
|
||||
return FailureWrongProtocolType
|
||||
}
|
||||
return ""
|
||||
"timed_out": "timed_out",
|
||||
"wrong_protocol_type": "wrong_protocol_type",
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue