doh_dns/
error.rs

1//! Errors returned by DoH servers.
2use crate::status::RCode;
3use std::{error::Error, fmt};
4
5/// Errors returned before or after making a DNS request over HTTPS.
6#[derive(Debug)]
7pub enum DnsError {
8    /// An error occurred before making the request. This can when a name is of
9    /// the wrong format, connecting to servers, or parsing the server response.
10    Query(QueryError),
11    /// An error returned by the DNS server with regards to the name being queried. It
12    /// occurs after a successful request/response. An example is a name that does not
13    /// exist.
14    Status(RCode),
15    /// An error returned when an attempt to query a record type that does not exist.
16    InvalidRecordType,
17    /// An error when trying to setup an empty list of servers to query.
18    NoServers,
19}
20
21impl fmt::Display for DnsError {
22    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23        match *self {
24            DnsError::Query(ref e) => write!(f, "query error: {}", e),
25            DnsError::Status(ref e) => write!(f, "DNS response error: {}", e),
26            DnsError::InvalidRecordType => write!(f, "Invalid record type"),
27            DnsError::NoServers => write!(f, "no servers given to resolve query"),
28        }
29    }
30}
31
32impl Error for DnsError {
33    fn source(&self) -> Option<&(dyn Error + 'static)> {
34        None
35    }
36}
37
38/// Errors returned in the process of generating requests and reading responsed from DoH
39/// servers. Google's HTTP response codes can be seen at <https://developers.google.com/speed/public-dns/docs/doh>
40/// and Cloudflare's at <https://developers.cloudflare.com/1.1.1.1/dns-over-https/request-structure>.
41#[derive(Debug)]
42pub enum QueryError {
43    /// This error occurs if the name to be resolved cannot be encoded.
44    InvalidName(String),
45    /// This error occurs if there is a problem building the query URL.
46    InvalidEndpoint(String),
47    /// This error occurs if there is a problem connecting to the server.
48    Connection(String),
49    /// This error occurs if there is a problem reading a response from the server.
50    ReadResponse(String),
51    /// This error occurs if there is a problem parsing the JSON response from the server.
52    ParseResponse(String),
53    /// Unknown error. This occurs if the server returns an unexpected result.
54    Unknown,
55    /// *HTTP Error: 400 Bad Request.*
56    /// Problems parsing the GET parameters, or an invalid DNS request message.
57    BadRequest400,
58    /// *HTTP Error: 413 Payload Too Large.*
59    /// An RFC 8484 POST request body exceeded the 512 byte maximum message size.
60    PayloadTooLarge413,
61    /// *HTTP Error: 414 URI Too Long.*
62    /// The GET query header was too large or the dns parameter had a Base64Url
63    /// encoded DNS message exceeding the 512 byte maximum message size.
64    UriTooLong414,
65    /// *HTTP Error: 415 Unsupported Media Type.*
66    /// The POST body did not have an application/dns-message Content-Type header.
67    UnsupportedMediaType415,
68    /// *HTTP Error: 429 Too Many Requests.*
69    /// The client has sent too many requests in a given amount of time.
70    TooManyRequests429,
71    /// *HTTP Error: 500 Internal Server Error.*
72    /// Google Public DNS internal DoH errors.
73    InternalServerError500,
74    /// *HTTP Error: 501 Not Implemented.*
75    /// Only GET and POST methods are implemented, other methods get this error.
76    NotImplemented501,
77    /// *HTTP Error: 502 Bad Gateway.*
78    /// The DoH service could not contact Google Public DNS resolvers.
79    BadGateway502,
80    /// *HTTP Error: 504.*
81    /// Resolver timeout while waiting for the query response.
82    ResolverTimeout504,
83}
84
85impl fmt::Display for QueryError {
86    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87        match *self {
88            QueryError::InvalidName(ref e) => write!(f, "invalid server name given: {}", e),
89            QueryError::InvalidEndpoint(ref e) => write!(f, "invalid endpoint: {}", e),
90            QueryError::Connection(ref e) => write!(f, "connection error: {}", e),
91            QueryError::ReadResponse(ref e) => write!(f, "error reading response: {}", e),
92            QueryError::ParseResponse(ref e) => write!(f, "error parsing response: {}", e),
93            QueryError::Unknown => write!(f, "unknown query error"),
94            QueryError::BadRequest400 => write!(
95                f,
96                "Problems parsing the GET parameters, or an invalid DNS request message"
97            ),
98            QueryError::PayloadTooLarge413 => write!(
99                f,
100                "An RFC 8484 POST request body exceeded the 512 byte maximum message size"
101            ),
102            QueryError::UriTooLong414 => write!(
103                f,
104                "The GET query header was too large or the dns parameter had a Base64Url encoded DNS message exceeding the 512 byte maximum message size"
105            ),
106            QueryError::UnsupportedMediaType415 => write!(
107                f,
108                "The POST body did not have an application/dns-message Content-Type header"
109            ),
110            QueryError::TooManyRequests429 => write!(
111                f,
112                "The client has sent too many requests in a given amount of time"
113            ),
114            QueryError::InternalServerError500 => write!(
115                f,
116                "Google Public DNS internal DoH errors"
117            ),
118            QueryError::NotImplemented501 => write!(
119                f,
120                "Only GET and POST methods are implemented, other methods get this error"
121            ),
122            QueryError::BadGateway502 => write!(
123                f,
124                "The DoH service could not contact Google Public DNS resolvers"
125            ),
126            QueryError::ResolverTimeout504 => write!(
127                f,
128                "Resolver timeout while waiting for the query response"
129            ),
130        }
131    }
132}
133
134impl Error for QueryError {
135    fn source(&self) -> Option<&(dyn Error + 'static)> {
136        None
137    }
138}