/src/hickory-dns/crates/proto/src/error.rs
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2015-2020 Benjamin Fry <benjaminfry@me.com> |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or |
4 | | // https://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or |
5 | | // https://opensource.org/licenses/MIT>, at your option. This file may not be |
6 | | // copied, modified, or distributed except according to those terms. |
7 | | |
8 | | //! Error types for the crate |
9 | | |
10 | | #![deny(missing_docs)] |
11 | | |
12 | | use alloc::borrow::ToOwned; |
13 | | use alloc::boxed::Box; |
14 | | use alloc::string::{String, ToString}; |
15 | | use alloc::sync::Arc; |
16 | | use alloc::vec::Vec; |
17 | | use core::cmp::Ordering; |
18 | | use core::fmt; |
19 | | #[cfg(feature = "std")] |
20 | | use std::{io, sync}; |
21 | | |
22 | | #[cfg(feature = "backtrace")] |
23 | | pub use backtrace::Backtrace as ExtBacktrace; |
24 | | use enum_as_inner::EnumAsInner; |
25 | | #[cfg(feature = "backtrace")] |
26 | | use once_cell::sync::Lazy; |
27 | | use thiserror::Error; |
28 | | use tracing::debug; |
29 | | |
30 | | #[cfg(feature = "__dnssec")] |
31 | | use crate::dnssec::Proof; |
32 | | #[cfg(any(feature = "dnssec-aws-lc-rs", feature = "dnssec-ring"))] |
33 | | use crate::dnssec::ring_like::Unspecified; |
34 | | use crate::op::{Header, Query, ResponseCode}; |
35 | | use crate::rr::{Record, RecordType, rdata::SOA, resource::RecordRef}; |
36 | | use crate::serialize::binary::DecodeError; |
37 | | use crate::xfer::DnsResponse; |
38 | | |
39 | | /// Boolean for checking if backtrace is enabled at runtime |
40 | | #[cfg(feature = "backtrace")] |
41 | | pub static ENABLE_BACKTRACE: Lazy<bool> = Lazy::new(|| { |
42 | | use std::env; |
43 | | let bt = env::var("RUST_BACKTRACE"); |
44 | | matches!(bt.as_ref().map(|s| s as &str), Ok("full") | Ok("1")) |
45 | | }); |
46 | | |
47 | | /// Generate a backtrace |
48 | | /// |
49 | | /// If RUST_BACKTRACE is 1 or full then this will return Some(Backtrace), otherwise, NONE. |
50 | | #[cfg(feature = "backtrace")] |
51 | | #[macro_export] |
52 | | macro_rules! trace { |
53 | | () => {{ |
54 | | use $crate::ExtBacktrace as Backtrace; |
55 | | |
56 | | if *$crate::ENABLE_BACKTRACE { |
57 | | Some(Backtrace::new()) |
58 | | } else { |
59 | | None |
60 | | } |
61 | | }}; |
62 | | } |
63 | | |
64 | | /// An alias for results returned by functions of this crate |
65 | | pub(crate) type ProtoResult<T> = ::core::result::Result<T, ProtoError>; |
66 | | |
67 | | /// The error kind for errors that get returned in the crate |
68 | 0 | #[derive(Debug, EnumAsInner, Error)] Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_bad_query_count Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_bad_query_count_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_bad_query_count Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_bad_query_count Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_busy Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_canceled Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_canceled_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_canceled Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_canceled Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_character_data_too_long Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_character_data_too_long_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_character_data_too_long Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_character_data_too_long Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_label_overlaps_with_other Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_label_overlaps_with_other_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_label_overlaps_with_other Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_label_overlaps_with_other Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_nsec Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_nsec_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_nsec Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_nsec Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_dns_key_protocol_not3 Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_dns_key_protocol_not3_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_dns_key_protocol_not3 Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_dns_key_protocol_not3 Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_domain_name_too_long Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_domain_name_too_long_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_domain_name_too_long Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_domain_name_too_long Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_edns_name_not_root Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_edns_name_not_root_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_edns_name_not_root Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_edns_name_not_root Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_form_error Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_form_error_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_form_error Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_form_error Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_incorrect_r_data_length_read Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_incorrect_r_data_length_read_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_incorrect_r_data_length_read Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_incorrect_r_data_length_read Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_label_bytes_too_long Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_label_bytes_too_long_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_label_bytes_too_long Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_label_bytes_too_long Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_pointer_not_prior_to_label Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_pointer_not_prior_to_label_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_pointer_not_prior_to_label Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_pointer_not_prior_to_label Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_max_buffer_size_exceeded Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_max_buffer_size_exceeded_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_max_buffer_size_exceeded Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_max_buffer_size_exceeded Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_max_record_limit_exceeded Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_max_record_limit_exceeded_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_max_record_limit_exceeded Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_max_record_limit_exceeded Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_message Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_message_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_message Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_message Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_msg Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_msg_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_msg Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_msg Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_no_connections Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_not_all_records_written Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_not_all_records_written_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_not_all_records_written Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_not_all_records_written Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_no_records_found Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_no_records_found_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_no_records_found Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_no_records_found Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_unknown_algorithm_type_value Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_unknown_algorithm_type_value_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_unknown_algorithm_type_value Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_unknown_algorithm_type_value Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_unknown_digest_type_value Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_unknown_digest_type_value_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_unknown_digest_type_value Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_unknown_digest_type_value Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_unknown_dns_class_str Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_unknown_dns_class_str_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_unknown_dns_class_str Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_unknown_dns_class_str Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_unknown_dns_class_value Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_unknown_dns_class_value_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_unknown_dns_class_value Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_unknown_dns_class_value Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_unknown_record_type_str Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_unknown_record_type_str_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_unknown_record_type_str Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_unknown_record_type_str Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_unknown_record_type_value Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_unknown_record_type_value_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_unknown_record_type_value Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_unknown_record_type_value Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_unrecognized_label_code Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_unrecognized_label_code_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_unrecognized_label_code Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_unrecognized_label_code Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_unrecognized_nsec3_flags Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_unrecognized_nsec3_flags_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_unrecognized_nsec3_flags Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_unrecognized_nsec3_flags Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_unrecognized_csync_flags Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_unrecognized_csync_flags_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_unrecognized_csync_flags Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_unrecognized_csync_flags Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_io Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_io_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_io Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_io Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_poisoned Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_request_refused Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_response_code Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_response_code_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_response_code Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_response_code Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_ring Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_ring_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_ring Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_ring Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_timer Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_timeout Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_url_parsing Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_url_parsing_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_url_parsing Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_url_parsing Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_utf8 Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_utf8_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_utf8 Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_utf8 Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_from_utf8 Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_from_utf8_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_from_utf8 Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_from_utf8 Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_parse_int Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_parse_int_mut Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::as_parse_int Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::into_parse_int Unexecuted instantiation: <hickory_proto::error::ProtoErrorKind>::is_query_case_mismatch |
69 | | #[non_exhaustive] |
70 | | pub enum ProtoErrorKind { |
71 | | /// Query count is not one |
72 | | #[error("there should only be one query per request, got: {0}")] |
73 | | BadQueryCount(usize), |
74 | | |
75 | | /// The underlying resource is too busy |
76 | | /// |
77 | | /// This is a signal that an internal resource is too busy. The intended action should be tried |
78 | | /// again, ideally after waiting for a little while for the situation to improve. Alternatively, |
79 | | /// the action could be tried on another resource (for example, in a name server pool). |
80 | | #[error("resource too busy")] |
81 | | Busy, |
82 | | |
83 | | /// An error caused by a canceled future |
84 | | #[error("future was canceled: {0:?}")] |
85 | | Canceled(futures_channel::oneshot::Canceled), |
86 | | |
87 | | /// Character data length exceeded the limit |
88 | | #[non_exhaustive] |
89 | | #[error("char data length exceeds {max}: {len}")] |
90 | | CharacterDataTooLong { |
91 | | /// Specified maximum |
92 | | max: usize, |
93 | | /// Actual length |
94 | | len: usize, |
95 | | }, |
96 | | |
97 | | /// Overlapping labels |
98 | | #[non_exhaustive] |
99 | | #[error("overlapping labels name {label} other {other}")] |
100 | | LabelOverlapsWithOther { |
101 | | /// Start of the label that is overlaps |
102 | | label: usize, |
103 | | /// Start of the other label |
104 | | other: usize, |
105 | | }, |
106 | | |
107 | | /// No Records and there is a corresponding DNSSEC Proof for NSEC |
108 | | #[cfg(feature = "__dnssec")] |
109 | | #[non_exhaustive] |
110 | | #[error("DNSSEC Negative Record Response for {query}, {proof}")] |
111 | | Nsec { |
112 | | /// Query for which the NSEC was returned |
113 | | query: Box<Query>, |
114 | | /// Response for which the NSEC was returned |
115 | | response: Box<DnsResponse>, |
116 | | /// DNSSEC proof of the record |
117 | | proof: Proof, |
118 | | }, |
119 | | |
120 | | /// DNS protocol version doesn't have the expected version 3 |
121 | | #[error("dns key value unknown, must be 3: {0}")] |
122 | | DnsKeyProtocolNot3(u8), |
123 | | |
124 | | /// A domain name was too long |
125 | | #[error("name label data exceed 255: {0}")] |
126 | | DomainNameTooLong(usize), |
127 | | |
128 | | /// EDNS resource record label is not the root label, although required |
129 | | #[error("edns resource record label must be the root label (.): {0}")] |
130 | | EdnsNameNotRoot(crate::rr::Name), |
131 | | |
132 | | /// Format error in Message Parsing |
133 | | #[error("message format error: {error}")] |
134 | | FormError { |
135 | | /// Header of the bad Message |
136 | | header: Header, |
137 | | /// Error that occurred while parsing the Message |
138 | | error: Box<ProtoError>, |
139 | | }, |
140 | | |
141 | | /// The length of rdata read was not as expected |
142 | | #[non_exhaustive] |
143 | | #[error("incorrect rdata length read: {read} expected: {len}")] |
144 | | IncorrectRDataLengthRead { |
145 | | /// The amount of read data |
146 | | read: usize, |
147 | | /// The expected length of the data |
148 | | len: usize, |
149 | | }, |
150 | | |
151 | | /// Label bytes exceeded the limit of 63 |
152 | | #[error("label bytes exceed 63: {0}")] |
153 | | LabelBytesTooLong(usize), |
154 | | |
155 | | /// Pointer points to an index within or after the current name |
156 | | #[non_exhaustive] |
157 | | #[error("label points to data not prior to idx: {idx} ptr: {ptr}")] |
158 | | PointerNotPriorToLabel { |
159 | | /// index of the label containing this pointer |
160 | | idx: usize, |
161 | | /// location to which the pointer is directing |
162 | | ptr: u16, |
163 | | }, |
164 | | |
165 | | /// The maximum buffer size was exceeded |
166 | | #[error("maximum buffer size exceeded: {0}")] |
167 | | MaxBufferSizeExceeded(usize), |
168 | | |
169 | | /// Maximum record limit was exceeded |
170 | | #[error("maximum record limit for {record_type} exceeded: {count} records")] |
171 | | MaxRecordLimitExceeded { |
172 | | /// number of records |
173 | | count: usize, |
174 | | /// The record type that triggered the error. |
175 | | record_type: RecordType, |
176 | | }, |
177 | | |
178 | | /// An error with an arbitrary message, referenced as &'static str |
179 | | #[error("{0}")] |
180 | | Message(&'static str), |
181 | | |
182 | | /// An error with an arbitrary message, stored as String |
183 | | #[error("{0}")] |
184 | | Msg(String), |
185 | | |
186 | | /// No resolvers available |
187 | | #[error("no connections available")] |
188 | | NoConnections, |
189 | | |
190 | | /// Not all records were able to be written |
191 | | #[non_exhaustive] |
192 | | #[error("not all records could be written, wrote: {count}")] |
193 | | NotAllRecordsWritten { |
194 | | /// Number of records that were written before the error |
195 | | count: usize, |
196 | | }, |
197 | | |
198 | | /// No records were found for a query |
199 | | #[error("no records found for {:?}", .0.query)] |
200 | | NoRecordsFound(NoRecords), |
201 | | |
202 | | /// An unknown algorithm type was found |
203 | | #[error("algorithm type value unknown: {0}")] |
204 | | UnknownAlgorithmTypeValue(u8), |
205 | | |
206 | | /// An unknown digest type was found |
207 | | #[error("digest type value unknown: {0}")] |
208 | | UnknownDigestTypeValue(u8), |
209 | | |
210 | | /// An unknown dns class was found |
211 | | #[error("dns class string unknown: {0}")] |
212 | | UnknownDnsClassStr(String), |
213 | | |
214 | | /// An unknown dns class value was found |
215 | | #[error("dns class value unknown: {0}")] |
216 | | UnknownDnsClassValue(u16), |
217 | | |
218 | | /// An unknown record type string was found |
219 | | #[error("record type string unknown: {0}")] |
220 | | UnknownRecordTypeStr(String), |
221 | | |
222 | | /// An unknown record type value was found |
223 | | #[error("record type value unknown: {0}")] |
224 | | UnknownRecordTypeValue(u16), |
225 | | |
226 | | /// An unrecognized label code was found |
227 | | #[error("unrecognized label code: {0:b}")] |
228 | | UnrecognizedLabelCode(u8), |
229 | | |
230 | | /// Unrecognized nsec3 flags were found |
231 | | #[error("nsec3 flags should be 0b0000000*: {0:b}")] |
232 | | UnrecognizedNsec3Flags(u8), |
233 | | |
234 | | /// Unrecognized csync flags were found |
235 | | #[error("csync flags should be 0b000000**: {0:b}")] |
236 | | UnrecognizedCsyncFlags(u16), |
237 | | |
238 | | // foreign |
239 | | /// An error got returned from IO |
240 | | #[cfg(feature = "std")] |
241 | | #[error("io error: {0}")] |
242 | | Io(Arc<io::Error>), |
243 | | |
244 | | /// Any sync poised error |
245 | | #[error("lock poisoned error")] |
246 | | Poisoned, |
247 | | |
248 | | /// A request was Refused due to some access check |
249 | | #[error("request refused")] |
250 | | RequestRefused, |
251 | | |
252 | | /// Received an error response code from the server |
253 | | #[error("error response: {0}")] |
254 | | ResponseCode(ResponseCode), |
255 | | |
256 | | /// A ring error |
257 | | #[cfg(feature = "__dnssec")] |
258 | | #[error("ring error: {0}")] |
259 | | Ring(#[from] Unspecified), |
260 | | |
261 | | /// A tokio timer error |
262 | | #[error("timer error")] |
263 | | Timer, |
264 | | |
265 | | /// A request timed out |
266 | | #[error("request timed out")] |
267 | | Timeout, |
268 | | |
269 | | /// An url parsing error |
270 | | #[error("url parsing error")] |
271 | | UrlParsing(#[from] url::ParseError), |
272 | | |
273 | | /// A utf8 parsing error |
274 | | #[error("error parsing utf8 string")] |
275 | | Utf8(#[from] core::str::Utf8Error), |
276 | | |
277 | | /// A utf8 parsing error |
278 | | #[error("error parsing utf8 string")] |
279 | | FromUtf8(#[from] alloc::string::FromUtf8Error), |
280 | | |
281 | | /// An int parsing error |
282 | | #[error("error parsing int")] |
283 | | ParseInt(#[from] core::num::ParseIntError), |
284 | | |
285 | | /// A Quinn (Quic) connection error occurred |
286 | | #[cfg(feature = "__quic")] |
287 | | #[error("error creating quic connection: {0}")] |
288 | | QuinnConnect(#[from] quinn::ConnectError), |
289 | | |
290 | | /// A Quinn (QUIC) connection error occurred |
291 | | #[cfg(feature = "__quic")] |
292 | | #[error("error with quic connection: {0}")] |
293 | | QuinnConnection(#[from] quinn::ConnectionError), |
294 | | |
295 | | /// A Quinn (QUIC) write error occurred |
296 | | #[cfg(feature = "__quic")] |
297 | | #[error("error writing to quic connection: {0}")] |
298 | | QuinnWriteError(#[from] quinn::WriteError), |
299 | | |
300 | | /// A Quinn (QUIC) read error occurred |
301 | | #[cfg(feature = "__quic")] |
302 | | #[error("error writing to quic read: {0}")] |
303 | | QuinnReadError(#[from] quinn::ReadExactError), |
304 | | |
305 | | /// A Quinn (QUIC) stream error occurred |
306 | | #[cfg(feature = "__quic")] |
307 | | #[error("referenced a closed QUIC stream: {0}")] |
308 | | QuinnStreamError(#[from] quinn::ClosedStream), |
309 | | |
310 | | /// A Quinn (QUIC) configuration error occurred |
311 | | #[cfg(feature = "__quic")] |
312 | | #[error("error constructing quic configuration: {0}")] |
313 | | QuinnConfigError(#[from] quinn::ConfigError), |
314 | | |
315 | | /// QUIC TLS config must include an AES-128-GCM cipher suite |
316 | | #[cfg(feature = "__quic")] |
317 | | #[error("QUIC TLS config must include an AES-128-GCM cipher suite")] |
318 | | QuinnTlsConfigError(#[from] quinn::crypto::rustls::NoInitialCipherSuite), |
319 | | |
320 | | /// Unknown QUIC stream used |
321 | | #[cfg(feature = "__quic")] |
322 | | #[error("an unknown quic stream was used")] |
323 | | QuinnUnknownStreamError, |
324 | | |
325 | | /// A quic message id should always be 0 |
326 | | #[cfg(feature = "__quic")] |
327 | | #[error("quic messages should always be 0, got: {0}")] |
328 | | QuicMessageIdNot0(u16), |
329 | | |
330 | | /// A Rustls error occurred |
331 | | #[cfg(feature = "__tls")] |
332 | | #[error("rustls construction error: {0}")] |
333 | | RustlsError(#[from] rustls::Error), |
334 | | |
335 | | /// Case randomization is enabled, and a server did not echo a query name back with the same |
336 | | /// case. |
337 | | #[error("case of query name in response did not match")] |
338 | | QueryCaseMismatch, |
339 | | } |
340 | | |
341 | | impl From<NoRecords> for ProtoErrorKind { |
342 | 0 | fn from(no_records: NoRecords) -> Self { |
343 | 0 | Self::NoRecordsFound(no_records) |
344 | 0 | } |
345 | | } |
346 | | |
347 | | /// Response where no records were found |
348 | | #[derive(Clone, Debug)] |
349 | | #[non_exhaustive] |
350 | | pub struct NoRecords { |
351 | | /// The query for which no records were found. |
352 | | pub query: Box<Query>, |
353 | | /// If an SOA is present, then this is an authoritative response or a referral to another nameserver, see the negative_type field. |
354 | | pub soa: Option<Box<Record<SOA>>>, |
355 | | /// Nameservers may be present in addition to or in lieu of an SOA for a referral |
356 | | /// The tuple struct layout is vec[(Nameserver, [vec of glue records])] |
357 | | pub ns: Option<Arc<[ForwardNSData]>>, |
358 | | /// negative ttl, as determined from DnsResponse::negative_ttl |
359 | | /// this will only be present if the SOA was also present. |
360 | | pub negative_ttl: Option<u32>, |
361 | | /// ResponseCode, if `NXDOMAIN`, the domain does not exist (and no other types). |
362 | | /// If `NoError`, then the domain exists but there exist either other types at the same label, or subzones of that label. |
363 | | pub response_code: ResponseCode, |
364 | | /// Authority records from the query. These are important to preserve for DNSSEC validation. |
365 | | pub authorities: Option<Arc<[Record]>>, |
366 | | } |
367 | | |
368 | | impl NoRecords { |
369 | | /// Construct a new [`NoRecords`] from a query and a response code |
370 | 0 | pub fn new(query: impl Into<Box<Query>>, response_code: ResponseCode) -> Self { |
371 | 0 | Self { |
372 | 0 | query: query.into(), |
373 | 0 | soa: None, |
374 | 0 | ns: None, |
375 | 0 | negative_ttl: None, |
376 | 0 | response_code, |
377 | 0 | authorities: None, |
378 | 0 | } |
379 | 0 | } |
380 | | } |
381 | | |
382 | | impl From<AuthorityData> for NoRecords { |
383 | 0 | fn from(value: AuthorityData) -> Self { |
384 | 0 | let response_code = match value.is_nx_domain() { |
385 | 0 | true => ResponseCode::NXDomain, |
386 | 0 | false => ResponseCode::NoError, |
387 | | }; |
388 | | |
389 | 0 | Self { |
390 | 0 | query: value.query, |
391 | 0 | soa: value.soa, |
392 | 0 | ns: None, |
393 | 0 | negative_ttl: None, |
394 | 0 | response_code, |
395 | 0 | authorities: value.authorities, |
396 | 0 | } |
397 | 0 | } |
398 | | } |
399 | | |
400 | | /// Data from the authority section of a response. |
401 | | #[derive(Clone, Debug)] |
402 | | pub struct AuthorityData { |
403 | | /// Query |
404 | | pub query: Box<Query>, |
405 | | /// SOA |
406 | | pub soa: Option<Box<Record<SOA>>>, |
407 | | /// No records found? |
408 | | no_records_found: bool, |
409 | | /// IS nx domain? |
410 | | nx_domain: bool, |
411 | | /// Authority records |
412 | | pub authorities: Option<Arc<[Record]>>, |
413 | | } |
414 | | |
415 | | impl AuthorityData { |
416 | | /// Construct a new AuthorityData |
417 | 0 | pub fn new( |
418 | 0 | query: Box<Query>, |
419 | 0 | soa: Option<Box<Record<SOA>>>, |
420 | 0 | no_records_found: bool, |
421 | 0 | nx_domain: bool, |
422 | 0 | authorities: Option<Arc<[Record]>>, |
423 | 0 | ) -> Self { |
424 | 0 | Self { |
425 | 0 | query, |
426 | 0 | soa, |
427 | 0 | no_records_found, |
428 | 0 | nx_domain, |
429 | 0 | authorities, |
430 | 0 | } |
431 | 0 | } |
432 | | |
433 | | /// are there records? |
434 | 0 | pub fn is_no_records_found(&self) -> bool { |
435 | 0 | self.no_records_found |
436 | 0 | } |
437 | | |
438 | | /// is this nxdomain? |
439 | 0 | pub fn is_nx_domain(&self) -> bool { |
440 | 0 | self.nx_domain |
441 | 0 | } |
442 | | } |
443 | | |
444 | | /// Data needed to process a NS-record-based referral. |
445 | | #[derive(Clone, Debug)] |
446 | | pub struct ForwardNSData { |
447 | | /// The referant NS record |
448 | | pub ns: Record, |
449 | | /// Any glue records associated with the referant NS record. |
450 | | pub glue: Arc<[Record]>, |
451 | | } |
452 | | |
453 | | /// The error type for errors that get returned in the crate |
454 | | #[derive(Error, Clone, Debug)] |
455 | | #[non_exhaustive] |
456 | | pub struct ProtoError { |
457 | | /// Kind of error that occurred |
458 | | pub kind: ProtoErrorKind, |
459 | | /// Backtrace to the source of the error |
460 | | #[cfg(feature = "backtrace")] |
461 | | pub backtrack: Option<ExtBacktrace>, |
462 | | } |
463 | | |
464 | | impl ProtoError { |
465 | | /// Get the kind of the error |
466 | | #[inline] |
467 | 3.13k | pub fn kind(&self) -> &ProtoErrorKind { |
468 | 3.13k | &self.kind |
469 | 3.13k | } <hickory_proto::error::ProtoError>::kind Line | Count | Source | 467 | 24 | pub fn kind(&self) -> &ProtoErrorKind { | 468 | 24 | &self.kind | 469 | 24 | } |
<hickory_proto::error::ProtoError>::kind Line | Count | Source | 467 | 3.10k | pub fn kind(&self) -> &ProtoErrorKind { | 468 | 3.10k | &self.kind | 469 | 3.10k | } |
|
470 | | |
471 | | /// If this is a ProtoErrorKind::Busy |
472 | | #[inline] |
473 | 0 | pub fn is_busy(&self) -> bool { |
474 | 0 | matches!(self.kind, ProtoErrorKind::Busy) |
475 | 0 | } |
476 | | |
477 | | /// Returns true if this error represents NoConnections |
478 | | #[inline] |
479 | 0 | pub fn is_no_connections(&self) -> bool { |
480 | 0 | matches!(self.kind, ProtoErrorKind::NoConnections) |
481 | 0 | } |
482 | | |
483 | | /// Returns true if the domain does not exist |
484 | | #[inline] |
485 | 0 | pub fn is_nx_domain(&self) -> bool { |
486 | 0 | matches!( |
487 | 0 | self.kind, |
488 | | ProtoErrorKind::NoRecordsFound(NoRecords { |
489 | | response_code: ResponseCode::NXDomain, |
490 | | .. |
491 | | }) |
492 | | ) |
493 | 0 | } |
494 | | |
495 | | /// Returns true if the error represents NoRecordsFound |
496 | | #[inline] |
497 | 0 | pub fn is_no_records_found(&self) -> bool { |
498 | 0 | matches!(self.kind, ProtoErrorKind::NoRecordsFound { .. }) |
499 | 0 | } |
500 | | |
501 | | /// Returns the SOA record, if the error contains one |
502 | | #[inline] |
503 | 0 | pub fn into_soa(self) -> Option<Box<Record<SOA>>> { |
504 | 0 | match self.kind { |
505 | 0 | ProtoErrorKind::NoRecordsFound(NoRecords { soa, .. }) => soa, |
506 | 0 | _ => None, |
507 | | } |
508 | 0 | } |
509 | | |
510 | | /// Returns true if this is a std::io::Error |
511 | | #[inline] |
512 | | #[cfg(feature = "std")] |
513 | 0 | pub fn is_io(&self) -> bool { |
514 | 0 | matches!(self.kind, ProtoErrorKind::Io(..)) |
515 | 0 | } |
516 | | |
517 | | #[cfg(feature = "std")] |
518 | 0 | pub(crate) fn as_dyn(&self) -> &(dyn std::error::Error + 'static) { |
519 | 0 | self |
520 | 0 | } |
521 | | |
522 | | /// A conversion to determine if the response is an error |
523 | 0 | pub fn from_response(response: DnsResponse) -> Result<DnsResponse, Self> { |
524 | | use ResponseCode::*; |
525 | 0 | debug!("response: {}", *response); |
526 | | |
527 | 0 | match response.response_code() { |
528 | 0 | Refused => Err(Self::from(ProtoErrorKind::RequestRefused)), |
529 | 0 | code @ ServFail |
530 | 0 | | code @ FormErr |
531 | 0 | | code @ NotImp |
532 | 0 | | code @ YXDomain |
533 | 0 | | code @ YXRRSet |
534 | 0 | | code @ NXRRSet |
535 | 0 | | code @ NotAuth |
536 | 0 | | code @ NotZone |
537 | 0 | | code @ BADVERS |
538 | 0 | | code @ BADSIG |
539 | 0 | | code @ BADKEY |
540 | 0 | | code @ BADTIME |
541 | 0 | | code @ BADMODE |
542 | 0 | | code @ BADNAME |
543 | 0 | | code @ BADALG |
544 | 0 | | code @ BADTRUNC |
545 | 0 | | code @ BADCOOKIE => Err(Self::from(ProtoErrorKind::ResponseCode(code))), |
546 | | // Some NXDOMAIN responses contain CNAME referrals, that will not be an error |
547 | 0 | code @ NXDomain | |
548 | | // No answers are available, CNAME referrals are not failures |
549 | 0 | code @ NoError |
550 | 0 | if !response.contains_answer() && !response.truncated() => { |
551 | | // TODO: if authoritative, this is cacheable, store a TTL (currently that requires time, need a "now" here) |
552 | | // let valid_until = if response.authoritative() { now + response.negative_ttl() }; |
553 | 0 | let soa = response.soa().as_ref().map(RecordRef::to_owned); |
554 | 0 |
|
555 | 0 | // Collect any referral nameservers and associated glue records |
556 | 0 | let mut referral_name_servers = vec![]; |
557 | 0 | for ns in response.authorities().iter().filter(|ns| ns.record_type() == RecordType::NS) { |
558 | 0 | let glue = response |
559 | 0 | .additionals() |
560 | 0 | .iter() |
561 | 0 | .filter_map(|record| { |
562 | 0 | if let Some(ns_data) = ns.data().as_ns() { |
563 | 0 | if *record.name() == **ns_data && |
564 | 0 | (record.data().as_a().is_some() || record.data().as_aaaa().is_some()) { |
565 | 0 | return Some(Record::to_owned(record)); |
566 | 0 | } |
567 | 0 | } |
568 | | |
569 | 0 | None |
570 | 0 | }) |
571 | 0 | .collect::<Vec<Record>>(); |
572 | 0 | referral_name_servers.push(ForwardNSData { ns: Record::to_owned(ns), glue: glue.into() }) |
573 | | } |
574 | | |
575 | 0 | let option_ns = if !referral_name_servers.is_empty() { |
576 | 0 | Some(referral_name_servers.into()) |
577 | | } else { |
578 | 0 | None |
579 | | }; |
580 | | |
581 | 0 | let authorities = if !response.authorities().is_empty() { |
582 | 0 | Some(response.authorities().to_owned().into()) |
583 | | } else { |
584 | 0 | None |
585 | | }; |
586 | | |
587 | 0 | let negative_ttl = response.negative_ttl(); |
588 | 0 | let query = response.into_message().take_queries().drain(..).next().unwrap_or_default(); |
589 | 0 |
|
590 | 0 | let error_kind = ProtoErrorKind::NoRecordsFound(NoRecords { |
591 | 0 | query: Box::new(query), |
592 | 0 | soa: soa.map(Box::new), |
593 | 0 | ns: option_ns, |
594 | 0 | negative_ttl, |
595 | 0 | response_code: code, |
596 | 0 | authorities, |
597 | 0 | }); |
598 | 0 |
|
599 | 0 | Err(Self::from(error_kind)) |
600 | | } |
601 | | NXDomain |
602 | | | NoError |
603 | 0 | | Unknown(_) => Ok(response), |
604 | | } |
605 | 0 | } |
606 | | |
607 | | /// Compare two errors to see if one contains a server response. |
608 | 0 | pub fn cmp_specificity(&self, other: &Self) -> Ordering { |
609 | 0 | let kind = self.kind(); |
610 | 0 | let other = other.kind(); |
611 | 0 |
|
612 | 0 | match (kind, other) { |
613 | | (ProtoErrorKind::NoRecordsFound { .. }, ProtoErrorKind::NoRecordsFound { .. }) => { |
614 | 0 | return Ordering::Equal; |
615 | | } |
616 | 0 | (ProtoErrorKind::NoRecordsFound { .. }, _) => return Ordering::Greater, |
617 | 0 | (_, ProtoErrorKind::NoRecordsFound { .. }) => return Ordering::Less, |
618 | 0 | _ => (), |
619 | 0 | } |
620 | 0 |
|
621 | 0 | match (kind, other) { |
622 | | #[cfg(feature = "std")] |
623 | 0 | (ProtoErrorKind::Io { .. }, ProtoErrorKind::Io { .. }) => return Ordering::Equal, |
624 | | #[cfg(feature = "std")] |
625 | 0 | (ProtoErrorKind::Io { .. }, _) => return Ordering::Greater, |
626 | | #[cfg(feature = "std")] |
627 | 0 | (_, ProtoErrorKind::Io { .. }) => return Ordering::Less, |
628 | 0 | _ => (), |
629 | 0 | } |
630 | 0 |
|
631 | 0 | match (kind, other) { |
632 | 0 | (ProtoErrorKind::Timeout, ProtoErrorKind::Timeout) => return Ordering::Equal, |
633 | 0 | (ProtoErrorKind::Timeout, _) => return Ordering::Greater, |
634 | 0 | (_, ProtoErrorKind::Timeout) => return Ordering::Less, |
635 | 0 | _ => (), |
636 | 0 | } |
637 | 0 |
|
638 | 0 | Ordering::Equal |
639 | 0 | } |
640 | | |
641 | | /// Whether the query should be retried after this error |
642 | 0 | pub fn should_retry(&self) -> bool { |
643 | 0 | !matches!( |
644 | 0 | self.kind(), |
645 | | ProtoErrorKind::NoConnections | ProtoErrorKind::NoRecordsFound { .. } |
646 | | ) |
647 | 0 | } |
648 | | |
649 | | /// Whether this error should count as an attempt |
650 | 0 | pub fn attempted(&self) -> bool { |
651 | 0 | !matches!(self.kind(), ProtoErrorKind::Busy) |
652 | 0 | } |
653 | | } |
654 | | |
655 | | impl fmt::Display for ProtoError { |
656 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
657 | 0 | cfg_if::cfg_if! { |
658 | 0 | if #[cfg(feature = "backtrace")] { |
659 | 0 | if let Some(backtrace) = &self.backtrack { |
660 | 0 | fmt::Display::fmt(&self.kind, f)?; |
661 | 0 | fmt::Debug::fmt(backtrace, f) |
662 | 0 | } else { |
663 | 0 | fmt::Display::fmt(&self.kind, f) |
664 | 0 | } |
665 | 0 | } else { |
666 | 0 | fmt::Display::fmt(&self.kind, f) |
667 | 0 | } |
668 | 0 | } |
669 | 0 | } |
670 | | } |
671 | | |
672 | | impl<E: Into<ProtoErrorKind>> From<E> for ProtoError { |
673 | 10.8k | fn from(error: E) -> Self { |
674 | 10.8k | Self { |
675 | 10.8k | kind: error.into(), |
676 | 10.8k | #[cfg(feature = "backtrace")] |
677 | 10.8k | backtrack: trace!(), |
678 | 10.8k | } |
679 | 10.8k | } <hickory_proto::error::ProtoError as core::convert::From<hickory_proto::error::ProtoErrorKind>>::from Line | Count | Source | 673 | 10.8k | fn from(error: E) -> Self { | 674 | 10.8k | Self { | 675 | 10.8k | kind: error.into(), | 676 | 10.8k | #[cfg(feature = "backtrace")] | 677 | 10.8k | backtrack: trace!(), | 678 | 10.8k | } | 679 | 10.8k | } |
Unexecuted instantiation: <hickory_proto::error::ProtoError as core::convert::From<url::parser::ParseError>>::from <hickory_proto::error::ProtoError as core::convert::From<alloc::string::FromUtf8Error>>::from Line | Count | Source | 673 | 23 | fn from(error: E) -> Self { | 674 | 23 | Self { | 675 | 23 | kind: error.into(), | 676 | 23 | #[cfg(feature = "backtrace")] | 677 | 23 | backtrack: trace!(), | 678 | 23 | } | 679 | 23 | } |
Unexecuted instantiation: <hickory_proto::error::ProtoError as core::convert::From<aws_lc_rs::error::Unspecified>>::from Unexecuted instantiation: <hickory_proto::error::ProtoError as core::convert::From<core::num::error::ParseIntError>>::from Unexecuted instantiation: <hickory_proto::error::ProtoError as core::convert::From<core::str::error::Utf8Error>>::from Unexecuted instantiation: <hickory_proto::error::ProtoError as core::convert::From<std::io::error::Error>>::from |
680 | | } |
681 | | |
682 | | impl From<DecodeError> for ProtoError { |
683 | 3.01k | fn from(err: DecodeError) -> Self { |
684 | 3.01k | match err { |
685 | 59 | DecodeError::PointerNotPriorToLabel { idx, ptr } => { |
686 | 59 | ProtoErrorKind::PointerNotPriorToLabel { idx, ptr } |
687 | | } |
688 | 0 | DecodeError::LabelBytesTooLong(len) => ProtoErrorKind::LabelBytesTooLong(len), |
689 | 94 | DecodeError::UnrecognizedLabelCode(code) => ProtoErrorKind::UnrecognizedLabelCode(code), |
690 | 2 | DecodeError::DomainNameTooLong(len) => ProtoErrorKind::DomainNameTooLong(len), |
691 | 79 | DecodeError::LabelOverlapsWithOther { label, other } => { |
692 | 79 | ProtoErrorKind::LabelOverlapsWithOther { label, other } |
693 | | } |
694 | 2.78k | _ => ProtoErrorKind::Msg(err.to_string()), |
695 | | } |
696 | 3.01k | .into() |
697 | 3.01k | } |
698 | | } |
699 | | |
700 | | impl From<&'static str> for ProtoError { |
701 | 518 | fn from(msg: &'static str) -> Self { |
702 | 518 | ProtoErrorKind::Message(msg).into() |
703 | 518 | } |
704 | | } |
705 | | |
706 | | impl From<String> for ProtoError { |
707 | 2.21k | fn from(msg: String) -> Self { |
708 | 2.21k | ProtoErrorKind::Msg(msg).into() |
709 | 2.21k | } |
710 | | } |
711 | | |
712 | | #[cfg(feature = "std")] |
713 | | impl From<io::Error> for ProtoErrorKind { |
714 | 0 | fn from(e: io::Error) -> Self { |
715 | 0 | match e.kind() { |
716 | 0 | io::ErrorKind::TimedOut => Self::Timeout, |
717 | 0 | _ => Self::Io(e.into()), |
718 | | } |
719 | 0 | } |
720 | | } |
721 | | |
722 | | #[cfg(feature = "std")] |
723 | | impl<T> From<sync::PoisonError<T>> for ProtoError { |
724 | 0 | fn from(_e: sync::PoisonError<T>) -> Self { |
725 | 0 | ProtoErrorKind::Poisoned.into() |
726 | 0 | } |
727 | | } |
728 | | |
729 | | #[cfg(feature = "std")] |
730 | | impl From<ProtoError> for io::Error { |
731 | 0 | fn from(e: ProtoError) -> Self { |
732 | 0 | match e.kind() { |
733 | 0 | ProtoErrorKind::Timeout => Self::new(io::ErrorKind::TimedOut, e), |
734 | 0 | _ => Self::other(e), |
735 | | } |
736 | 0 | } |
737 | | } |
738 | | |
739 | | impl From<ProtoError> for String { |
740 | 0 | fn from(e: ProtoError) -> Self { |
741 | 0 | e.to_string() |
742 | 0 | } |
743 | | } |
744 | | |
745 | | #[cfg(feature = "wasm-bindgen")] |
746 | | impl From<ProtoError> for wasm_bindgen_crate::JsValue { |
747 | | fn from(e: ProtoError) -> Self { |
748 | | js_sys::Error::new(&e.to_string()).into() |
749 | | } |
750 | | } |
751 | | |
752 | | impl Clone for ProtoErrorKind { |
753 | 0 | fn clone(&self) -> Self { |
754 | | use self::ProtoErrorKind::*; |
755 | 0 | match *self { |
756 | 0 | BadQueryCount(count) => BadQueryCount(count), |
757 | 0 | Busy => Busy, |
758 | 0 | Canceled(ref c) => Canceled(*c), |
759 | 0 | CharacterDataTooLong { max, len } => CharacterDataTooLong { max, len }, |
760 | 0 | LabelOverlapsWithOther { label, other } => LabelOverlapsWithOther { label, other }, |
761 | 0 | DnsKeyProtocolNot3(protocol) => DnsKeyProtocolNot3(protocol), |
762 | 0 | DomainNameTooLong(len) => DomainNameTooLong(len), |
763 | 0 | EdnsNameNotRoot(ref found) => EdnsNameNotRoot(found.clone()), |
764 | 0 | FormError { header, ref error } => FormError { |
765 | 0 | header, |
766 | 0 | error: error.clone(), |
767 | 0 | }, |
768 | 0 | IncorrectRDataLengthRead { read, len } => IncorrectRDataLengthRead { read, len }, |
769 | 0 | LabelBytesTooLong(len) => LabelBytesTooLong(len), |
770 | 0 | PointerNotPriorToLabel { idx, ptr } => PointerNotPriorToLabel { idx, ptr }, |
771 | 0 | MaxBufferSizeExceeded(max) => MaxBufferSizeExceeded(max), |
772 | 0 | MaxRecordLimitExceeded { count, record_type } => { |
773 | 0 | MaxRecordLimitExceeded { count, record_type } |
774 | | } |
775 | 0 | Message(msg) => Message(msg), |
776 | 0 | Msg(ref msg) => Msg(msg.clone()), |
777 | 0 | NoConnections => NoConnections, |
778 | 0 | NotAllRecordsWritten { count } => NotAllRecordsWritten { count }, |
779 | 0 | NoRecordsFound(ref inner) => NoRecordsFound(inner.clone()), |
780 | 0 | RequestRefused => RequestRefused, |
781 | 0 | ResponseCode(code) => ResponseCode(code), |
782 | | #[cfg(feature = "__dnssec")] |
783 | | Nsec { |
784 | 0 | ref query, |
785 | 0 | ref response, |
786 | 0 | proof, |
787 | 0 | } => Nsec { |
788 | 0 | query: query.clone(), |
789 | 0 | response: response.clone(), |
790 | 0 | proof, |
791 | 0 | }, |
792 | 0 | UnknownAlgorithmTypeValue(value) => UnknownAlgorithmTypeValue(value), |
793 | 0 | UnknownDigestTypeValue(value) => UnknownDigestTypeValue(value), |
794 | 0 | UnknownDnsClassStr(ref value) => UnknownDnsClassStr(value.clone()), |
795 | 0 | UnknownDnsClassValue(value) => UnknownDnsClassValue(value), |
796 | 0 | UnknownRecordTypeStr(ref value) => UnknownRecordTypeStr(value.clone()), |
797 | 0 | UnknownRecordTypeValue(value) => UnknownRecordTypeValue(value), |
798 | 0 | UnrecognizedLabelCode(value) => UnrecognizedLabelCode(value), |
799 | 0 | UnrecognizedNsec3Flags(flags) => UnrecognizedNsec3Flags(flags), |
800 | 0 | UnrecognizedCsyncFlags(flags) => UnrecognizedCsyncFlags(flags), |
801 | | #[cfg(feature = "std")] |
802 | 0 | Io(ref e) => Io(e.clone()), |
803 | 0 | Poisoned => Poisoned, |
804 | | #[cfg(feature = "__dnssec")] |
805 | 0 | Ring(ref _e) => Ring(Unspecified), |
806 | 0 | Timeout => Timeout, |
807 | 0 | Timer => Timer, |
808 | 0 | UrlParsing(ref e) => UrlParsing(*e), |
809 | 0 | Utf8(ref e) => Utf8(*e), |
810 | 0 | FromUtf8(ref e) => FromUtf8(e.clone()), |
811 | 0 | ParseInt(ref e) => ParseInt(e.clone()), |
812 | | #[cfg(feature = "__quic")] |
813 | | QuinnConnect(ref e) => QuinnConnect(e.clone()), |
814 | | #[cfg(feature = "__quic")] |
815 | | QuinnConnection(ref e) => QuinnConnection(e.clone()), |
816 | | #[cfg(feature = "__quic")] |
817 | | QuinnWriteError(ref e) => QuinnWriteError(e.clone()), |
818 | | #[cfg(feature = "__quic")] |
819 | | QuicMessageIdNot0(val) => QuicMessageIdNot0(val), |
820 | | #[cfg(feature = "__quic")] |
821 | | QuinnReadError(ref e) => QuinnReadError(e.clone()), |
822 | | #[cfg(feature = "__quic")] |
823 | | QuinnStreamError(ref e) => QuinnStreamError(e.clone()), |
824 | | #[cfg(feature = "__quic")] |
825 | | QuinnConfigError(ref e) => QuinnConfigError(e.clone()), |
826 | | #[cfg(feature = "__quic")] |
827 | | QuinnTlsConfigError(ref e) => QuinnTlsConfigError(e.clone()), |
828 | | #[cfg(feature = "__quic")] |
829 | | QuinnUnknownStreamError => QuinnUnknownStreamError, |
830 | | #[cfg(feature = "__tls")] |
831 | | RustlsError(ref e) => RustlsError(e.clone()), |
832 | 0 | QueryCaseMismatch => QueryCaseMismatch, |
833 | | } |
834 | 0 | } |
835 | | } |