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