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}