domain_core/iana/
opcode.rs

1//! DNS OpCodes
2
3use std::cmp;
4use std::convert;
5use std::fmt;
6use std::hash;
7
8
9/// DNS OpCodes.
10///
11/// The opcode specifies the kind of query to be performed.
12///
13/// The opcode is initially defined in RFC 1035. All currently assigned
14/// values can be found in the [IANA registry]. This type is complete as of
15/// 2019-01-28.
16///
17/// [IANA registry]: http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-5
18#[derive(Clone, Copy, Debug)]
19pub enum Opcode {
20    /// A standard query.
21    ///
22    /// This query requests all records matching the name, class, and record
23    /// type given in the query’s question section.
24    ///
25    /// This value is defined in RFC 1035.
26    Query,
27
28    /// An inverse query (IQUERY) (obsolete).
29    ///
30    /// The idea behind inverse queries was to provide a single answer and
31    /// ask the DNS for all the questions that would lead to this answer.
32    /// This kind of query has always been optional, was never widely
33    /// supported, and has therefore been declared obsolete.
34    ///
35    /// This value was defined in RFC 1035 and obsoleted by RFC 3425.
36    IQuery,
37
38    /// A server status request.
39    ///
40    /// This value is defined in RFC 1035. The status request itself was
41    /// defined as experimental and ‘to be defined’ in RFC 1034 and seems
42    /// to never have been mentioned ever again.
43    Status,
44
45    /// A NOTIFY query.
46    ///
47    /// NOTIFY queries allow master servers to inform slave servers when a
48    /// zone has changed.
49    ///
50    /// This value and the NOTIFY query are defined in RFC 1996.
51    Notify,
52
53    /// An UPDATE query.
54    ///
55    /// The UPDATE query can be used to alter zone content managed by a
56    /// master server.
57    ///
58    /// This value and the UPDATE query are defined in RFC 2136.
59    Update,
60
61    /// DNS Stateful operations (DSO).
62    ///
63    /// This value is defined in draft-ietf-dnsop-session-signal.
64    Dso,
65
66    /// A raw integer opcode value.
67    ///
68    /// When converting to an `u8`, only the lower four bits are used.
69    Int(u8)
70}
71
72impl Opcode {
73    /// Creates an Opcode value from an integer value.
74    ///
75    /// Only considers the lower four bits of `value`.
76    pub fn from_int(value: u8) -> Opcode {
77        use self::Opcode::*;
78
79        match value & 0x0F {
80            0 => Query,
81            1 => IQuery,
82            2 => Status,
83            4 => Notify,
84            5 => Update,
85            6 => Dso,
86            value => Int(value)
87        }
88    }
89
90    /// Returns the integer value for this opcode.
91    pub fn to_int(self) -> u8 {
92        use self::Opcode::*;
93
94        match self {
95            Query => 0,
96            IQuery => 1,
97            Status => 2,
98            Notify => 4,
99            Update => 5,
100            Dso => 6,
101            Int(value) => value & 0x0F
102        }
103    }
104}
105
106
107//--- From
108
109impl convert::From<u8> for Opcode {
110    fn from(value: u8) -> Opcode { Opcode::from_int(value) }
111}
112
113impl convert::From<Opcode> for u8 {
114    fn from(value: Opcode) -> u8 { Opcode::to_int(value) }
115}
116
117
118//--- Display
119
120impl fmt::Display for Opcode {
121    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
122        use self::Opcode::*;
123
124        match *self {
125            Query => "QUERY".fmt(f),
126            IQuery => "IQUERY".fmt(f),
127            Status => "STATUS".fmt(f),
128            Notify => "NOTIFY".fmt(f),
129            Update => "UPDATE".fmt(f),
130            Dso => "DSO".fmt(f),
131            Int(value) => {
132                match Opcode::from_int(value) {
133                    Int(value) => value.fmt(f),
134                    value => value.fmt(f)
135                }
136            }
137        }
138    }
139}
140
141
142//--- PartialEq and Eq
143
144impl cmp::PartialEq for Opcode {
145    fn eq(&self, other: &Opcode) -> bool {
146        self.to_int() == other.to_int()
147    }
148}
149
150impl cmp::PartialEq<u8> for Opcode {
151    fn eq(&self, other: &u8) -> bool {
152        self.to_int() == *other
153    }
154}
155
156impl cmp::PartialEq<Opcode> for u8 {
157    fn eq(&self, other: &Opcode) -> bool {
158        *self == other.to_int()
159    }
160}
161
162impl cmp::Eq for Opcode { }
163
164
165//--- PartialCmp and Cmp
166
167impl cmp::PartialOrd for Opcode {
168    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
169        self.to_int().partial_cmp(&other.to_int())
170    }
171}
172
173impl cmp::PartialOrd<u8> for Opcode {
174    fn partial_cmp(&self, other: &u8) -> Option<cmp::Ordering> {
175        self.to_int().partial_cmp(other)
176    }
177}
178
179impl cmp::PartialOrd<Opcode> for u8 {
180    fn partial_cmp(&self, other: &Opcode) -> Option<cmp::Ordering> {
181        self.partial_cmp(&other.to_int())
182    }
183}
184
185impl cmp::Ord for Opcode {
186    fn cmp(&self, other: &Self) -> cmp::Ordering {
187        self.to_int().cmp(&other.to_int())
188    }
189}
190
191
192//--- Hash
193
194impl hash::Hash for Opcode {
195    fn hash<H: hash::Hasher>(&self, state: &mut H) {
196        self.to_int().hash(state)
197    }
198}