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, Default, 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 #[default]
70 NoError,
71
72 /// Format Error [RFC 1035](https://tools.ietf.org/html/rfc1035)
73 FormErr,
74
75 /// Server Failure [RFC 1035](https://tools.ietf.org/html/rfc1035)
76 ServFail,
77
78 /// Non-Existent Domain [RFC 1035](https://tools.ietf.org/html/rfc1035)
79 NXDomain,
80
81 /// Not Implemented [RFC 1035](https://tools.ietf.org/html/rfc1035)
82 NotImp,
83
84 /// Query Refused [RFC 1035](https://tools.ietf.org/html/rfc1035)
85 Refused,
86
87 /// Name Exists when it should not [RFC 2136](https://tools.ietf.org/html/rfc2136)
88 YXDomain,
89
90 /// RR Set Exists when it should not [RFC 2136](https://tools.ietf.org/html/rfc2136)
91 YXRRSet,
92
93 /// RR Set that should exist does not [RFC 2136](https://tools.ietf.org/html/rfc2136)
94 NXRRSet,
95
96 /// Server Not Authoritative for zone [RFC 2136](https://tools.ietf.org/html/rfc2136)
97 /// or Not Authorized [RFC 8945](https://www.rfc-editor.org/rfc/rfc8945)
98 NotAuth,
99
100 /// Name not contained in zone [RFC 2136](https://tools.ietf.org/html/rfc2136)
101 NotZone,
102
103 /// Bad OPT Version [RFC 6891](https://tools.ietf.org/html/rfc6891#section-9)
104 BADVERS,
105
106 /// TSIG Signature Failure [RFC 8945](https://www.rfc-editor.org/rfc/rfc8945)
107 BADSIG,
108
109 /// Key not recognized [RFC 8945](https://www.rfc-editor.org/rfc/rfc8945)
110 BADKEY,
111
112 /// Signature out of time window [RFC 8945](https://www.rfc-editor.org/rfc/rfc8945)
113 BADTIME,
114
115 /// Bad TKEY Mode [RFC 2930](https://tools.ietf.org/html/rfc2930#section-2.6)
116 BADMODE,
117
118 /// Duplicate key name [RFC 2930](https://tools.ietf.org/html/rfc2930#section-2.6)
119 BADNAME,
120
121 /// Algorithm not supported [RFC 2930](https://tools.ietf.org/html/rfc2930#section-2.6)
122 BADALG,
123
124 /// Bad Truncation [RFC 4635](https://tools.ietf.org/html/rfc4635#section-4)
125 BADTRUNC,
126
127 /// Bad/missing Server Cookie [RFC 7873](https://datatracker.ietf.org/doc/html/rfc7873)
128 BADCOOKIE,
129 // 24-3840 Unassigned
130 // 3841-4095 Reserved for Private Use [RFC6895]
131 // 4096-65534 Unassigned
132 // 65535 Reserved, can be allocated by Standards Action [RFC6895]
133 /// An unknown or unregistered response code was received.
134 Unknown(u16),
135}
136
137impl ResponseCode {
138 /// returns the lower 4 bits of the response code (for the original header portion of the code)
139 pub fn low(self) -> u8 {
140 (u16::from(self) & 0x000F) as u8
141 }
142
143 /// returns the high 8 bits for the EDNS portion of the response code
144 pub fn high(self) -> u8 {
145 ((u16::from(self) & 0x0FF0) >> 4) as u8
146 }
147
148 /// DNS can not store the entire space of ResponseCodes in 4 bit space of the Header, this function
149 /// allows for a initial value of the first 4 bits to be set.
150 ///
151 /// After the EDNS is read, the entire ResponseCode (12 bits) can be reconstructed for the full ResponseCode.
152 pub fn from_low(low: u8) -> Self {
153 ((u16::from(low)) & 0x000F).into()
154 }
155
156 /// Combines the EDNS high and low from the Header to produce the Extended ResponseCode
157 pub fn from(high: u8, low: u8) -> Self {
158 ((u16::from(high) << 4) | ((u16::from(low)) & 0x000F)).into()
159 }
160
161 /// Transforms the response code into the human message
162 pub fn to_str(self) -> &'static str {
163 match self {
164 Self::NoError => "No Error",
165 Self::FormErr => "Form Error", // 1 FormErr Format Error [RFC1035]
166 Self::ServFail => "Server Failure", // 2 ServFail Server Failure [RFC1035]
167 Self::NXDomain => "Non-Existent Domain", // 3 NXDomain Non-Existent Domain [RFC1035]
168 Self::NotImp => "Not Implemented", // 4 NotImp Not Implemented [RFC1035]
169 Self::Refused => "Query Refused", // 5 Refused Query Refused [RFC1035]
170 Self::YXDomain => "Name should not exist", // 6 YXDomain Name Exists when it should not [RFC2136][RFC6672]
171 Self::YXRRSet => "RR Set should not exist", // 7 YXRRSet RR Set Exists when it should not [RFC2136]
172 Self::NXRRSet => "RR Set does not exist", // 8 NXRRSet RR Set that should exist does not [RFC2136]
173 Self::NotAuth => "Not authorized", // 9 NotAuth Server Not Authoritative for zone [RFC2136]
174 Self::NotZone => "Name not in zone", // 10 NotZone Name not contained in zone [RFC2136]
175 Self::BADVERS => "Bad option versions", // 16 BADVERS Bad OPT Version [RFC6891]
176 Self::BADSIG => "TSIG Failure", // 16 BADSIG TSIG Signature Failure [RFC2845]
177 Self::BADKEY => "Key not recognized", // 17 BADKEY Key not recognized [RFC2845]
178 Self::BADTIME => "Signature out of time window", // 18 BADTIME Signature out of time window [RFC2845]
179 Self::BADMODE => "Bad TKEY mode", // 19 BADMODE Bad TKEY Mode [RFC2930]
180 Self::BADNAME => "Duplicate key name", // 20 BADNAME Duplicate key name [RFC2930]
181 Self::BADALG => "Algorithm not supported", // 21 BADALG Algorithm not supported [RFC2930]
182 Self::BADTRUNC => "Bad truncation", // 22 BADTRUNC Bad Truncation [RFC4635]
183 Self::BADCOOKIE => "Bad server cookie", // 23 BADCOOKIE Bad/missing Server Cookie [RFC7873]
184 Self::Unknown(_) => "Unknown response code",
185 }
186 }
187}
188
189impl Display for ResponseCode {
190 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
191 f.write_str(self.to_str())
192 }
193}
194
195/// Convert from `ResponseCode` to `u16`
196///
197/// ```
198/// use hickory_proto::op::ResponseCode;
199///
200/// let var: ResponseCode = From::from(0);
201/// assert_eq!(ResponseCode::NoError, var);
202///
203/// let var: ResponseCode = 0.into();
204/// assert_eq!(ResponseCode::NoError, var);
205/// ```
206impl From<ResponseCode> for u16 {
207 fn from(rt: ResponseCode) -> Self {
208 match rt {
209 ResponseCode::NoError => 0, // 0 NoError No Error [RFC1035]
210 ResponseCode::FormErr => 1, // 1 FormErr Format Error [RFC1035]
211 ResponseCode::ServFail => 2, // 2 ServFail Server Failure [RFC1035]
212 ResponseCode::NXDomain => 3, // 3 NXDomain Non-Existent Domain [RFC1035]
213 ResponseCode::NotImp => 4, // 4 NotImp Not Implemented [RFC1035]
214 ResponseCode::Refused => 5, // 5 Refused Query Refused [RFC1035]
215 ResponseCode::YXDomain => 6, // 6 YXDomain Name Exists when it should not [RFC2136][RFC6672]
216 ResponseCode::YXRRSet => 7, // 7 YXRRSet RR Set Exists when it should not [RFC2136]
217 ResponseCode::NXRRSet => 8, // 8 NXRRSet RR Set that should exist does not [RFC2136]
218 ResponseCode::NotAuth => 9, // 9 NotAuth Server Not Authoritative for zone [RFC2136]
219 ResponseCode::NotZone => 10, // 10 NotZone Name not contained in zone [RFC2136]
220 //
221 // 11-15 Unassigned
222 //
223 // 16 BADVERS Bad OPT Version [RFC6891]
224 // 16 BADSIG TSIG Signature Failure [RFC2845]
225 ResponseCode::BADVERS | ResponseCode::BADSIG => 16,
226 ResponseCode::BADKEY => 17, // 17 BADKEY Key not recognized [RFC2845]
227 ResponseCode::BADTIME => 18, // 18 BADTIME Signature out of time window [RFC2845]
228 ResponseCode::BADMODE => 19, // 19 BADMODE Bad TKEY Mode [RFC2930]
229 ResponseCode::BADNAME => 20, // 20 BADNAME Duplicate key name [RFC2930]
230 ResponseCode::BADALG => 21, // 21 BADALG Algorithm not supported [RFC2930]
231 ResponseCode::BADTRUNC => 22, // 22 BADTRUNC Bad Truncation [RFC4635]
232 ResponseCode::BADCOOKIE => 23, // 23 BADCOOKIE Bad/missing Server Cookie [RFC7873]
233 ResponseCode::Unknown(code) => code,
234 }
235 }
236}
237
238/// Convert from `u16` to `ResponseCode`
239///
240/// ```
241/// use hickory_proto::op::ResponseCode;
242///
243/// let var: u16 = From::from(ResponseCode::NoError);
244/// assert_eq!(0, var);
245///
246/// let var: u16 = ResponseCode::NoError.into();
247/// assert_eq!(0, var);
248/// ```
249impl From<u16> for ResponseCode {
250 fn from(value: u16) -> Self {
251 match value {
252 0 => Self::NoError, // 0 NoError No Error [RFC1035]
253 1 => Self::FormErr, // 1 FormErr Format Error [RFC1035]
254 2 => Self::ServFail, // 2 ServFail Server Failure [RFC1035]
255 3 => Self::NXDomain, // 3 NXDomain Non-Existent Domain [RFC1035]
256 4 => Self::NotImp, // 4 NotImp Not Implemented [RFC1035]
257 5 => Self::Refused, // 5 Refused Query Refused [RFC1035]
258 6 => Self::YXDomain, // 6 YXDomain Name Exists when it should not [RFC2136][RFC6672]
259 7 => Self::YXRRSet, // 7 YXRRSet RR Set Exists when it should not [RFC2136]
260 8 => Self::NXRRSet, // 8 NXRRSet RR Set that should exist does not [RFC2136]
261 9 => Self::NotAuth, // 9 NotAuth Server Not Authoritative for zone [RFC2136]
262 10 => Self::NotZone, // 10 NotZone Name not contained in zone [RFC2136]
263 // this looks to be backwards compat for 4 bit ResponseCodes.
264 // 16 BADVERS Bad OPT Version [RFC6891]
265 // 16 => ResponseCode::BADVERS,
266 16 => Self::BADSIG, // 16 BADSIG TSIG Signature Failure [RFC2845]
267 17 => Self::BADKEY, // 17 BADKEY Key not recognized [RFC2845]
268 18 => Self::BADTIME, // 18 BADTIME Signature out of time window [RFC2845]
269 19 => Self::BADMODE, // 19 BADMODE Bad TKEY Mode [RFC2930]
270 20 => Self::BADNAME, // 20 BADNAME Duplicate key name [RFC2930]
271 21 => Self::BADALG, // 21 BADALG Algorithm not supported [RFC2930]
272 22 => Self::BADTRUNC, // 22 BADTRUNC Bad Truncation [RFC4635]
273 23 => Self::BADCOOKIE, // 23 BADCOOKIE Bad/missing Server Cookie [RFC7873]
274 code => Self::Unknown(code),
275 }
276 }
277}