Skip to main content

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}