hickory_proto/op/response_code.rs
1/*
2 * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17// there is not much to format in this file, and we don't want rustfmt to mess up the comments
18
19//! All defined response codes in DNS
20
21use core::fmt::{self, Display, Formatter};
22
23#[cfg(feature = "serde")]
24use serde::{Deserialize, Serialize};
25
26/// The status code of the response to a query.
27///
28/// [RFC 1035, DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION, November 1987](https://tools.ietf.org/html/rfc1035)
29///
30/// ```text
31/// RCODE Response code - this 4 bit field is set as part of
32/// responses. The values have the following
33/// interpretation:
34///
35/// 0 No error condition
36///
37/// 1 Format error - The name server was
38/// unable to interpret the query.
39///
40/// 2 Server failure - The name server was
41/// unable to process this query due to a
42/// problem with the name server.
43///
44/// 3 Name Error - Meaningful only for
45/// responses from an authoritative name
46/// server, this code signifies that the
47/// domain name referenced in the query does
48/// not exist.
49///
50/// 4 Not Implemented - The name server does
51/// not support the requested kind of query.
52///
53/// 5 Refused - The name server refuses to
54/// perform the specified operation for
55/// policy reasons. For example, a name
56/// server may not wish to provide the
57/// information to the particular requester,
58/// or a name server may not wish to perform
59/// a particular operation (e.g., zone
60/// transfer) for particular data.
61///
62/// 6-15 Reserved for future use.
63/// ```
64#[derive(Debug, Eq, PartialEq, PartialOrd, Copy, Clone, Hash)]
65#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
66#[allow(dead_code)]
67pub enum ResponseCode {
68 /// No Error [RFC 1035](https://tools.ietf.org/html/rfc1035)
69 NoError,
70
71 /// Format Error [RFC 1035](https://tools.ietf.org/html/rfc1035)
72 FormErr,
73
74 /// Server Failure [RFC 1035](https://tools.ietf.org/html/rfc1035)
75 ServFail,
76
77 /// Non-Existent Domain [RFC 1035](https://tools.ietf.org/html/rfc1035)
78 NXDomain,
79
80 /// Not Implemented [RFC 1035](https://tools.ietf.org/html/rfc1035)
81 NotImp,
82
83 /// Query Refused [RFC 1035](https://tools.ietf.org/html/rfc1035)
84 Refused,
85
86 /// Name Exists when it should not [RFC 2136](https://tools.ietf.org/html/rfc2136)
87 YXDomain,
88
89 /// RR Set Exists when it should not [RFC 2136](https://tools.ietf.org/html/rfc2136)
90 YXRRSet,
91
92 /// RR Set that should exist does not [RFC 2136](https://tools.ietf.org/html/rfc2136)
93 NXRRSet,
94
95 /// Server Not Authoritative for zone [RFC 2136](https://tools.ietf.org/html/rfc2136)
96 /// or Not Authorized [RFC 8945](https://www.rfc-editor.org/rfc/rfc8945)
97 NotAuth,
98
99 /// Name not contained in zone [RFC 2136](https://tools.ietf.org/html/rfc2136)
100 NotZone,
101
102 /// Bad OPT Version [RFC 6891](https://tools.ietf.org/html/rfc6891#section-9)
103 BADVERS,
104
105 /// TSIG Signature Failure [RFC 8945](https://www.rfc-editor.org/rfc/rfc8945)
106 BADSIG,
107
108 /// Key not recognized [RFC 8945](https://www.rfc-editor.org/rfc/rfc8945)
109 BADKEY,
110
111 /// Signature out of time window [RFC 8945](https://www.rfc-editor.org/rfc/rfc8945)
112 BADTIME,
113
114 /// Bad TKEY Mode [RFC 2930](https://tools.ietf.org/html/rfc2930#section-2.6)
115 BADMODE,
116
117 /// Duplicate key name [RFC 2930](https://tools.ietf.org/html/rfc2930#section-2.6)
118 BADNAME,
119
120 /// Algorithm not supported [RFC 2930](https://tools.ietf.org/html/rfc2930#section-2.6)
121 BADALG,
122
123 /// Bad Truncation [RFC 4635](https://tools.ietf.org/html/rfc4635#section-4)
124 BADTRUNC,
125
126 /// Bad/missing server cookie [draft-ietf-dnsop-cookies](https://tools.ietf.org/html/draft-ietf-dnsop-cookies-10)
127 BADCOOKIE,
128 // 24-3840 Unassigned
129 // 3841-4095 Reserved for Private Use [RFC6895]
130 // 4096-65534 Unassigned
131 // 65535 Reserved, can be allocated by Standards Action [RFC6895]
132 /// An unknown or unregistered response code was received.
133 Unknown(u16),
134}
135
136impl ResponseCode {
137 /// returns the lower 4 bits of the response code (for the original header portion of the code)
138 pub fn low(self) -> u8 {
139 (u16::from(self) & 0x000F) as u8
140 }
141
142 /// returns the high 8 bits for the EDNS portion of the response code
143 pub fn high(self) -> u8 {
144 ((u16::from(self) & 0x0FF0) >> 4) as u8
145 }
146
147 /// DNS can not store the entire space of ResponseCodes in 4 bit space of the Header, this function
148 /// allows for a initial value of the first 4 bits to be set.
149 ///
150 /// After the EDNS is read, the entire ResponseCode (12 bits) can be reconstructed for the full ResponseCode.
151 pub fn from_low(low: u8) -> Self {
152 ((u16::from(low)) & 0x000F).into()
153 }
154
155 /// Combines the EDNS high and low from the Header to produce the Extended ResponseCode
156 pub fn from(high: u8, low: u8) -> Self {
157 ((u16::from(high) << 4) | ((u16::from(low)) & 0x000F)).into()
158 }
159
160 /// Transforms the response code into the human message
161 pub fn to_str(self) -> &'static str {
162 match self {
163 Self::NoError => "No Error",
164 Self::FormErr => "Form Error", // 1 FormErr Format Error [RFC1035]
165 Self::ServFail => "Server Failure", // 2 ServFail Server Failure [RFC1035]
166 Self::NXDomain => "Non-Existent Domain", // 3 NXDomain Non-Existent Domain [RFC1035]
167 Self::NotImp => "Not Implemented", // 4 NotImp Not Implemented [RFC1035]
168 Self::Refused => "Query Refused", // 5 Refused Query Refused [RFC1035]
169 Self::YXDomain => "Name should not exist", // 6 YXDomain Name Exists when it should not [RFC2136][RFC6672]
170 Self::YXRRSet => "RR Set should not exist", // 7 YXRRSet RR Set Exists when it should not [RFC2136]
171 Self::NXRRSet => "RR Set does not exist", // 8 NXRRSet RR Set that should exist does not [RFC2136]
172 Self::NotAuth => "Not authorized", // 9 NotAuth Server Not Authoritative for zone [RFC2136]
173 Self::NotZone => "Name not in zone", // 10 NotZone Name not contained in zone [RFC2136]
174 Self::BADVERS => "Bad option versions", // 16 BADVERS Bad OPT Version [RFC6891]
175 Self::BADSIG => "TSIG Failure", // 16 BADSIG TSIG Signature Failure [RFC2845]
176 Self::BADKEY => "Key not recognized", // 17 BADKEY Key not recognized [RFC2845]
177 Self::BADTIME => "Signature out of time window", // 18 BADTIME Signature out of time window [RFC2845]
178 Self::BADMODE => "Bad TKEY mode", // 19 BADMODE Bad TKEY Mode [RFC2930]
179 Self::BADNAME => "Duplicate key name", // 20 BADNAME Duplicate key name [RFC2930]
180 Self::BADALG => "Algorithm not supported", // 21 BADALG Algorithm not supported [RFC2930]
181 Self::BADTRUNC => "Bad truncation", // 22 BADTRUNC Bad Truncation [RFC4635]
182 Self::BADCOOKIE => "Bad server cookie", // 23 BADCOOKIE (TEMPORARY - registered 2015-07-26, expires 2016-07-26) Bad/missing server cookie [draft-ietf-dnsop-cookies]
183 Self::Unknown(_) => "Unknown response code",
184 }
185 }
186}
187
188impl Default for ResponseCode {
189 fn default() -> Self {
190 Self::NoError
191 }
192}
193
194impl Display for ResponseCode {
195 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
196 f.write_str(self.to_str())
197 }
198}
199
200/// Convert from `ResponseCode` to `u16`
201///
202/// ```
203/// use hickory_proto::op::response_code::ResponseCode;
204///
205/// let var: ResponseCode = From::from(0);
206/// assert_eq!(ResponseCode::NoError, var);
207///
208/// let var: ResponseCode = 0.into();
209/// assert_eq!(ResponseCode::NoError, var);
210/// ```
211impl From<ResponseCode> for u16 {
212 fn from(rt: ResponseCode) -> Self {
213 match rt {
214 ResponseCode::NoError => 0, // 0 NoError No Error [RFC1035]
215 ResponseCode::FormErr => 1, // 1 FormErr Format Error [RFC1035]
216 ResponseCode::ServFail => 2, // 2 ServFail Server Failure [RFC1035]
217 ResponseCode::NXDomain => 3, // 3 NXDomain Non-Existent Domain [RFC1035]
218 ResponseCode::NotImp => 4, // 4 NotImp Not Implemented [RFC1035]
219 ResponseCode::Refused => 5, // 5 Refused Query Refused [RFC1035]
220 ResponseCode::YXDomain => 6, // 6 YXDomain Name Exists when it should not [RFC2136][RFC6672]
221 ResponseCode::YXRRSet => 7, // 7 YXRRSet RR Set Exists when it should not [RFC2136]
222 ResponseCode::NXRRSet => 8, // 8 NXRRSet RR Set that should exist does not [RFC2136]
223 ResponseCode::NotAuth => 9, // 9 NotAuth Server Not Authoritative for zone [RFC2136]
224 ResponseCode::NotZone => 10, // 10 NotZone Name not contained in zone [RFC2136]
225 //
226 // 11-15 Unassigned
227 //
228 // 16 BADVERS Bad OPT Version [RFC6891]
229 // 16 BADSIG TSIG Signature Failure [RFC2845]
230 ResponseCode::BADVERS | ResponseCode::BADSIG => 16,
231 ResponseCode::BADKEY => 17, // 17 BADKEY Key not recognized [RFC2845]
232 ResponseCode::BADTIME => 18, // 18 BADTIME Signature out of time window [RFC2845]
233 ResponseCode::BADMODE => 19, // 19 BADMODE Bad TKEY Mode [RFC2930]
234 ResponseCode::BADNAME => 20, // 20 BADNAME Duplicate key name [RFC2930]
235 ResponseCode::BADALG => 21, // 21 BADALG Algorithm not supported [RFC2930]
236 ResponseCode::BADTRUNC => 22, // 22 BADTRUNC Bad Truncation [RFC4635]
237 // 23 BADCOOKIE (TEMPORARY - registered 2015-07-26, expires 2016-07-26) Bad/missing server cookie [draft-ietf-dnsop-cookies]
238 ResponseCode::BADCOOKIE => 23,
239 ResponseCode::Unknown(code) => code,
240 }
241 }
242}
243
244/// Convert from `u16` to `ResponseCode`
245///
246/// ```
247/// use hickory_proto::op::response_code::ResponseCode;
248///
249/// let var: u16 = From::from(ResponseCode::NoError);
250/// assert_eq!(0, var);
251///
252/// let var: u16 = ResponseCode::NoError.into();
253/// assert_eq!(0, var);
254/// ```
255impl From<u16> for ResponseCode {
256 #[allow(clippy::unimplemented)]
257 fn from(value: u16) -> Self {
258 match value {
259 0 => Self::NoError, // 0 NoError No Error [RFC1035]
260 1 => Self::FormErr, // 1 FormErr Format Error [RFC1035]
261 2 => Self::ServFail, // 2 ServFail Server Failure [RFC1035]
262 3 => Self::NXDomain, // 3 NXDomain Non-Existent Domain [RFC1035]
263 4 => Self::NotImp, // 4 NotImp Not Implemented [RFC1035]
264 5 => Self::Refused, // 5 Refused Query Refused [RFC1035]
265 6 => Self::YXDomain, // 6 YXDomain Name Exists when it should not [RFC2136][RFC6672]
266 7 => Self::YXRRSet, // 7 YXRRSet RR Set Exists when it should not [RFC2136]
267 8 => Self::NXRRSet, // 8 NXRRSet RR Set that should exist does not [RFC2136]
268 9 => Self::NotAuth, // 9 NotAuth Server Not Authoritative for zone [RFC2136]
269 10 => Self::NotZone, // 10 NotZone Name not contained in zone [RFC2136]
270 // this looks to be backwards compat for 4 bit ResponseCodes.
271 // 16 BADVERS Bad OPT Version [RFC6891]
272 // 16 => ResponseCode::BADVERS,
273 16 => Self::BADSIG, // 16 BADSIG TSIG Signature Failure [RFC2845]
274 17 => Self::BADKEY, // 17 BADKEY Key not recognized [RFC2845]
275 18 => Self::BADTIME, // 18 BADTIME Signature out of time window [RFC2845]
276 19 => Self::BADMODE, // 19 BADMODE Bad TKEY Mode [RFC2930]
277 20 => Self::BADNAME, // 20 BADNAME Duplicate key name [RFC2930]
278 21 => Self::BADALG, // 21 BADALG Algorithm not supported [RFC2930]
279 22 => Self::BADTRUNC, // 22 BADTRUNC Bad Truncation [RFC4635]
280 23 => Self::BADCOOKIE, // 23 BADCOOKIE (TEMPORARY - registered 2015-07-26, expires 2016-07-26) Bad/missing server cookie [draft-ietf-dnsop-cookies]
281 code => Self::Unknown(code),
282 }
283 }
284}