domain_core/iana/
opt.rs

1//! DNS EDNS0 Option Codes (OPT)
2
3use std::cmp;
4use std::fmt;
5use std::hash;
6use bytes::BufMut;
7use ::bits::compose::Compose;
8use ::bits::parse::{Parse, Parser, ShortBuf};
9
10
11//------------ OptionCode ---------------------------------------------------
12
13/// DNS EDNS0 Option Codes (OPT).
14///
15/// The record data of OPT records is a sequence of options. The type of each
16/// of these options is given through an option code, a 16 bit value.
17///
18/// The currently assigned option codes can be found in the [IANA registry].
19/// The type is complete as of 2019-01-28.
20///
21/// [IANA registry]: http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-11
22#[derive(Clone, Copy, Debug)]
23pub enum OptionCode {
24    Llq,
25    Ul,
26    Nsid,
27    Dau,
28    Dhu,
29    N3u,
30    ClientSubnet,
31    Expire,
32    Cookie,
33    TcpKeepalive,
34    Padding,
35    Chain,
36    KeyTag,
37    DeviceId,
38
39    /// A raw class value given through its integer. 
40    Int(u16),
41}
42
43impl OptionCode {
44    /// Returns the option code for the given raw integer value.
45    pub fn from_int(value: u16) -> Self {
46        use self::OptionCode::*;
47
48        match value {
49            1 => Llq,
50            2 => Ul,
51            3 => Nsid,
52            5 => Dau,
53            6 => Dhu,
54            7 => N3u,
55            8 => ClientSubnet,
56            9 => Expire,
57            10 => Cookie,
58            11 => TcpKeepalive,
59            12 => Padding,
60            13 => Chain,
61            14 => KeyTag,
62            26946 => DeviceId,
63            _ => Int(value)
64        }
65    }
66
67    /// Returns the raw integer value for this option code.
68    pub fn to_int(self) -> u16 {
69        use self::OptionCode::*;
70
71        match self {
72            Llq => 1,
73            Ul => 2,
74            Nsid => 3,
75            Dau => 5,
76            Dhu => 6,
77            N3u => 7,
78            ClientSubnet => 8,
79            Expire => 9,
80            Cookie => 10,
81            TcpKeepalive => 11,
82            Padding => 12,
83            Chain => 13,
84            KeyTag => 14,
85            DeviceId => 26946,
86            Int(v) => v
87        }
88    }
89}
90
91
92//--- Parse and Compose
93
94impl Parse for OptionCode {
95    type Err = ShortBuf;
96
97    fn parse(parser: &mut Parser) -> Result<Self, Self::Err> {
98        u16::parse(parser).map(OptionCode::from_int)
99    }
100
101    fn skip(parser: &mut Parser) -> Result<(), Self::Err> {
102        u16::skip(parser)
103    }
104}
105
106impl Compose for OptionCode {
107    fn compose_len(&self) -> usize {
108        2
109    }
110
111    fn compose<B: BufMut>(&self, buf: &mut B) {
112        self.to_int().compose(buf)
113    }
114}
115
116
117//--- From
118
119impl From<u16> for OptionCode {
120    fn from(value: u16) -> Self {
121        OptionCode::from_int(value)
122    }
123}
124
125impl From<OptionCode> for u16 {
126    fn from(value: OptionCode) -> Self {
127        value.to_int()
128    }
129}
130
131
132//--- Display
133
134impl fmt::Display for OptionCode {
135    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
136        use self::OptionCode::*;
137
138        match *self {
139            Llq => "LLQ".fmt(f),
140            Ul => "UL".fmt(f),
141            Nsid => "NSID".fmt(f),
142            Dau => "DAU".fmt(f),
143            Dhu => "DHU".fmt(f),
144            N3u => "N3U".fmt(f),
145            ClientSubnet => "edns-client-subnet".fmt(f),
146            Expire => "EDNS EXPIRE".fmt(f),
147            Cookie => "COOKIE".fmt(f),
148            TcpKeepalive => "edns-tcp-keepalive".fmt(f),
149            Padding => "Padding".fmt(f),
150            Chain => "CHAIN".fmt(f),
151            KeyTag => "edns-key-tag".fmt(f),
152            DeviceId => "DeviceID".fmt(f),
153            Int(value) => {
154                match OptionCode::from_int(value) {
155                    Int(value) => value.fmt(f),
156                    value => value.fmt(f),
157                }
158            }
159        }
160    }
161}
162
163
164//--- PartialEq and Eq
165
166impl PartialEq for OptionCode {
167    fn eq(&self, other: &Self) -> bool {
168        self.to_int() == other.to_int()
169    }
170}
171
172impl PartialEq<u16> for OptionCode {
173    fn eq(&self, other: &u16) -> bool {
174        self.to_int() == *other
175    }
176}
177
178impl PartialEq<OptionCode> for u16 {
179    fn eq(&self, other: &OptionCode) -> bool {
180        *self == other.to_int()
181    }
182}
183
184impl Eq for OptionCode { }
185
186
187//--- PartialOrd and Ord
188
189impl PartialOrd for OptionCode {
190    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
191        self.to_int().partial_cmp(&other.to_int())
192    }
193}
194
195impl PartialOrd<u16> for OptionCode {
196    fn partial_cmp(&self, other: &u16) -> Option<cmp::Ordering> {
197        self.to_int().partial_cmp(other)
198    }
199}
200
201impl PartialOrd<OptionCode> for u16 {
202    fn partial_cmp(&self, other: &OptionCode) -> Option<cmp::Ordering> {
203        self.partial_cmp(&other.to_int())
204    }
205}
206
207impl Ord for OptionCode {
208    fn cmp(&self, other: &Self) -> cmp::Ordering {
209        self.to_int().cmp(&other.to_int())
210    }
211}
212
213
214//--- Hash
215
216impl hash::Hash for OptionCode {
217    fn hash<H: hash::Hasher>(&self, state: &mut H) {
218        self.to_int().hash(state)
219    }
220}
221