1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2pub struct Header {
3 pub id: u16,
4 pub flags: Flags,
5 pub qd_count: u16,
6 pub an_count: u16,
7 pub ns_count: u16,
8 pub ar_count: u16,
9}
10
11impl Header {
12 pub fn new(
13 id: u16,
14 flags: Flags,
15 qd_count: u16,
16 an_count: u16,
17 ns_count: u16,
18 ar_count: u16,
19 ) -> Self {
20 Self {
21 id,
22 flags,
23 qd_count,
24 an_count,
25 ns_count,
26 ar_count,
27 }
28 }
29}
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq)]
32pub struct Flags {
33 pub qr: QR,
34 pub op_code: OpCode,
35 pub aa: AA,
36 pub tc: TC,
37 pub rd: RD,
38 pub ra: RA,
39 pub z: Z,
40 pub ad: AD,
41 pub cd: CD,
42 pub r_code: RCode,
43}
44
45impl Flags {
46 pub fn new(
47 qr: QR,
48 op_code: OpCode,
49 aa: AA,
50 tc: TC,
51 rd: RD,
52 ra: RA,
53 z: Z,
54 ad: AD,
55 cd: CD,
56 r_code: RCode,
57 ) -> Self {
58 Self {
59 qr,
60 op_code,
61 aa,
62 tc,
63 rd,
64 ra,
65 z,
66 ad,
67 cd,
68 r_code,
69 }
70 }
71
72 pub fn from_flags_bytes(h: u8, l: u8) -> Self {
73 Flags::new(
74 QR::from_flags_byte(h),
75 OpCode::from_flags_byte(h),
76 AA::from_flags_byte(h),
77 TC::from_flags_byte(h),
78 RD::from_flags_byte(h),
79 RA::from_flags_byte(l),
80 Z::from_flags_byte(l),
81 AD::from_flags_byte(l),
82 CD::from_flags_byte(l),
83 RCode::from_flags_byte(l),
84 )
85 }
86
87 pub fn to_flags_bytes(&self) -> (u8, u8) {
88 let h: u8 = self.qr.to_flags_byte_bits()
89 | self.op_code.to_flags_byte_bits()
90 | self.aa.to_flags_byte_bits()
91 | self.tc.to_flags_byte_bits()
92 | self.rd.to_flags_byte_bits();
93
94 let l = self.ra.to_flags_byte_bits()
95 | self.z.to_flags_byte_bits()
96 | self.ad.to_flags_byte_bits()
97 | self.cd.to_flags_byte_bits()
98 | self.r_code.to_flags_byte_bits();
99
100 (h, l)
101 }
102}
103
104#[derive(Debug, Clone, Copy, PartialEq, Eq)]
105#[repr(u8)]
106pub enum QR {
107 Query = 0 << 7,
108 Response = 1 << 7,
109}
110
111impl QR {
112 pub fn from_flags_byte(byte: u8) -> Self {
113 if (byte & (1 << 7)) != 0 {
114 QR::Response
115 } else {
116 QR::Query
117 }
118 }
119
120 pub fn to_flags_byte_bits(self) -> u8 {
121 self as u8
122 }
123}
124
125#[derive(Debug, Clone, Copy, PartialEq, Eq)]
126#[repr(u8)]
127pub enum AA {
128 NonAuthoritative = 0 << 2,
129 Authoritative = 1 << 2,
130}
131
132impl AA {
133 pub fn from_flags_byte(byte: u8) -> Self {
134 if (byte & (1 << 2)) != 0 {
135 AA::Authoritative
136 } else {
137 AA::NonAuthoritative
138 }
139 }
140
141 pub fn to_flags_byte_bits(self) -> u8 {
142 self as u8
143 }
144}
145
146#[derive(Debug, Clone, Copy, PartialEq, Eq)]
147#[repr(u8)]
148pub enum TC {
149 NotTruncated = 0 << 1,
150 Truncated = 1 << 1,
151}
152
153impl TC {
154 pub fn from_flags_byte(byte: u8) -> Self {
155 if (byte & (1 << 1)) != 0 {
156 TC::Truncated
157 } else {
158 TC::NotTruncated
159 }
160 }
161
162 pub fn to_flags_byte_bits(self) -> u8 {
163 self as u8
164 }
165}
166
167#[derive(Debug, Clone, Copy, PartialEq, Eq)]
168#[repr(u8)]
169pub enum RD {
170 RecursionNotDesired = 0,
171 RecursionDesired = 1,
172}
173
174impl RD {
175 pub fn from_flags_byte(byte: u8) -> Self {
176 if (byte & 1) != 0 {
177 RD::RecursionDesired
178 } else {
179 RD::RecursionNotDesired
180 }
181 }
182
183 pub fn to_flags_byte_bits(self) -> u8 {
184 self as u8
185 }
186}
187
188#[derive(Debug, Clone, Copy, PartialEq, Eq)]
189#[repr(u8)]
190pub enum RA {
191 RecursionNotAvailable = 0 << 7,
192 RecursionAvailable = 1 << 7,
193}
194
195impl RA {
196 pub fn from_flags_byte(byte: u8) -> Self {
197 if (byte & (1 << 7)) != 0 {
198 RA::RecursionAvailable
199 } else {
200 RA::RecursionNotAvailable
201 }
202 }
203
204 pub fn to_flags_byte_bits(self) -> u8 {
205 self as u8
206 }
207}
208
209#[derive(Debug, Clone, Copy, PartialEq, Eq)]
210pub enum OpCode {
211 Query,
212 IQuery,
213 Status,
214 Notify,
215 Update,
216 Unassigned(u8),
217}
218
219impl OpCode {
220 pub fn from_flags_byte(byte: u8) -> Self {
221 let v = (byte >> 3) & 0b1111;
222 match v {
223 0 => OpCode::Query,
224 1 => OpCode::IQuery,
225 2 => OpCode::Status,
226 4 => OpCode::Notify,
227 5 => OpCode::Update,
228 other => OpCode::Unassigned(other),
229 }
230 }
231
232 pub fn to_flags_byte_bits(self) -> u8 {
233 let v = match self {
234 OpCode::Query => 0,
235 OpCode::IQuery => 1,
236 OpCode::Status => 2,
237 OpCode::Notify => 4,
238 OpCode::Update => 5,
239 OpCode::Unassigned(x) => x & 0b1111,
240 };
241 v << 3
242 }
243}
244
245#[derive(Debug, Clone, Copy, PartialEq, Eq)]
246pub enum RCode {
247 NoError,
248 FormErr,
249 ServFail,
250 NXDomain,
251 NotImp,
252 Refused,
253 YXDomain,
254 YXRRSet,
255 NXRRSet,
256 NotAuth,
257 NotZone,
258 Unassigned(u8),
259}
260
261impl RCode {
262 pub fn from_flags_byte(byte: u8) -> Self {
263 let v = byte & 0b1111;
264 match v {
265 0 => RCode::NoError,
266 1 => RCode::FormErr,
267 2 => RCode::ServFail,
268 3 => RCode::NXDomain,
269 4 => RCode::NotImp,
270 5 => RCode::Refused,
271 6 => RCode::YXDomain,
272 7 => RCode::YXRRSet,
273 8 => RCode::NXRRSet,
274 9 => RCode::NotAuth,
275 10 => RCode::NotZone,
276 other => RCode::Unassigned(other),
277 }
278 }
279
280 pub fn to_flags_byte_bits(self) -> u8 {
281 let v = match self {
282 RCode::NoError => 0,
283 RCode::FormErr => 1,
284 RCode::ServFail => 2,
285 RCode::NXDomain => 3,
286 RCode::NotImp => 4,
287 RCode::Refused => 5,
288 RCode::YXDomain => 6,
289 RCode::YXRRSet => 7,
290 RCode::NXRRSet => 8,
291 RCode::NotAuth => 9,
292 RCode::NotZone => 10,
293 RCode::Unassigned(x) => x & 0b1111,
294 };
295 v
296 }
297}
298
299#[derive(Debug, Clone, Copy, PartialEq, Eq)]
300#[repr(u8)]
301pub enum Z {
302 Reserved = 0 << 6,
303}
304
305impl Z {
306 pub fn from_flags_byte(_byte: u8) -> Self {
307 Z::Reserved
308 }
309
310 pub fn to_flags_byte_bits(self) -> u8 {
311 self as u8
312 }
313}
314
315#[derive(Debug, Clone, Copy, PartialEq, Eq)]
316#[repr(u8)]
317pub enum AD {
318 DataNotAuthenticated = 0 << 5,
319 DataAuthenticated = 1 << 5,
320}
321
322impl AD {
323 pub fn from_flags_byte(byte: u8) -> Self {
324 if (byte & (1 << 5)) != 0 {
325 AD::DataAuthenticated
326 } else {
327 AD::DataNotAuthenticated
328 }
329 }
330
331 pub fn to_flags_byte_bits(self) -> u8 {
332 self as u8
333 }
334}
335
336#[derive(Debug, Clone, Copy, PartialEq, Eq)]
337#[repr(u8)]
338pub enum CD {
339 CheckingEnabled = 0 << 4,
340 CheckingDisabled = 1 << 4,
341}
342
343impl CD {
344 pub fn from_flags_byte(byte: u8) -> Self {
345 if (byte & (1 << 4)) != 0 {
346 CD::CheckingDisabled
347 } else {
348 CD::CheckingEnabled
349 }
350 }
351
352 pub fn to_flags_byte_bits(self) -> u8 {
353 self as u8
354 }
355}