Skip to main content

dns_message/
header.rs

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}