1#[derive(Copy, Clone)]
3#[repr(C)]
4pub struct DnsHeader {
5 id: [u8; 2],
6 flags: [u8; 2],
7 question_count: [u8; 2],
8 answer_count: [u8; 2],
9 name_server_count: [u8; 2],
10 additional_records_count: [u8; 2],
11}
12
13impl DnsHeader {
14 #[inline(always)]
15 pub(crate) fn from_bytes_mut(bytes: &mut [u8]) -> &mut Self {
16 unsafe { &mut *(bytes.as_mut_ptr() as *mut Self) }
17 }
18
19 #[inline(always)]
20 pub(crate) fn from_bytes(bytes: &[u8]) -> &Self {
21 unsafe { & *(bytes.as_ptr() as *const Self) }
22 }
23
24 #[inline(always)]
26 pub fn id(&self) -> u16 {
27 u16::from_be_bytes(self.id)
28 }
29
30 #[inline(always)]
32 pub fn kind(&self) -> DnsHeaderKind {
33 if (self.flags[0] & 0b10000000) == 0 {
34 DnsHeaderKind::Query
35 } else {
36 DnsHeaderKind::Response
37 }
38 }
39
40 #[inline(always)]
42 pub fn opcode(&self) -> DnsHeaderOpcode {
43 (self.flags[0] & 0b01111000).into()
44 }
45
46 #[inline(always)]
48 pub fn authoritative_answer(&self) -> bool {
49 (self.flags[0] & 0b00000100) != 0
50 }
51
52 #[inline(always)]
54 pub fn truncated(&self) -> bool {
55 (self.flags[0] & 0b00000010) != 0
56 }
57
58 #[inline(always)]
60 pub fn recursion_desired(&self) -> bool {
61 (self.flags[0] & 0b00000001) != 0
62 }
63
64 #[inline(always)]
66 pub fn recursion_available(&self) -> bool {
67 (self.flags[1] & 0b10000000) != 0
68 }
69
70 #[inline(always)]
72 pub fn response_code(&self) -> DnsHeaderResponseCode {
73 (self.flags[1] & 0b00001111).into()
74 }
75
76 #[inline(always)]
78 pub fn question_count(&self) -> u16 {
79 u16::from_be_bytes(self.question_count)
80 }
81
82 #[inline(always)]
84 pub fn answer_count(&self) -> u16 {
85 u16::from_be_bytes(self.answer_count)
86 }
87
88 #[inline(always)]
90 pub fn name_server_count(&self) -> u16 {
91 u16::from_be_bytes(self.name_server_count)
92 }
93
94 #[inline(always)]
96 pub fn additional_records_count(&self) -> u16 {
97 u16::from_be_bytes(self.additional_records_count)
98 }
99
100 #[inline(always)]
102 pub fn set_id(&mut self, id: u16) {
103 self.id = id.to_be_bytes();
104 }
105
106 #[inline(always)]
108 pub fn set_kind(&mut self, kind: DnsHeaderKind) {
109 match kind {
110 DnsHeaderKind::Query => self.flags[0] &= 0b01111111,
111 DnsHeaderKind::Response => self.flags[0] |= 0b10000000,
112 }
113 }
114
115 #[inline(always)]
117 pub fn set_opcode(&mut self, opcode: DnsHeaderOpcode) {
118 self.flags[0] &= 0b10000111;
119 self.flags[0] |= (u8::from(opcode) & 0b0000_1111) << 3;
120 }
121
122 #[inline(always)]
124 pub fn set_authoritative_answer(&mut self, authoritative_answer: bool) {
125 if authoritative_answer {
126 self.flags[0] |= 0b00000100;
127 } else {
128 self.flags[0] &= 0b11111011;
129 }
130 }
131
132 #[inline(always)]
134 pub fn set_truncated(&mut self, truncated: bool) {
135 if truncated {
136 self.flags[0] |= 0b00000010;
137 } else {
138 self.flags[0] &= 0b11111101;
139 }
140 }
141
142 #[inline(always)]
144 pub fn set_recursion_desired(&mut self, recursion_desired: bool) {
145 if recursion_desired {
146 self.flags[0] |= 0b00000001;
147 } else {
148 self.flags[0] &= 0b11111110;
149 }
150 }
151
152 #[inline(always)]
154 pub fn set_recursion_available(&mut self, recursion_available: bool) {
155 if recursion_available {
156 self.flags[1] |= 0b10000000;
157 } else {
158 self.flags[1] &= 0b01111111;
159 }
160 }
161
162 #[inline(always)]
164 pub fn set_response_code(&mut self, response_code: DnsHeaderResponseCode) {
165 self.flags[1] &= 0b11110000;
166 self.flags[1] |= u8::from(response_code) & 0b00001111;
167 }
168
169 #[inline(always)]
170 pub(crate) fn set_question_count(&mut self, question_count: u16) {
171 self.question_count = question_count.to_be_bytes();
172 }
173
174 #[inline(always)]
175 pub(crate) fn set_answer_count(&mut self, answer_count: u16) {
176 self.answer_count = answer_count.to_be_bytes();
177 }
178
179 #[inline(always)]
180 pub(crate) fn set_name_server_count(&mut self, name_server_count: u16) {
181 self.name_server_count = name_server_count.to_be_bytes();
182 }
183
184 #[inline(always)]
185 pub(crate) fn set_additional_records_count(&mut self, additional_records_count: u16) {
186 self.additional_records_count = additional_records_count.to_be_bytes();
187 }
188}
189
190impl core::fmt::Debug for DnsHeader {
191 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
192 f.debug_struct("Header")
193 .field("id", &self.id())
194 .field("kind", &self.kind())
195 .field("opcode", &self.opcode())
196 .field("authoritative_answer", &self.authoritative_answer())
197 .field("truncated", &self.truncated())
198 .field("recursion_desired", &self.recursion_desired())
199 .field("recursion_available", &self.recursion_available())
200 .field("response_code", &self.response_code())
201 .field("question_count", &self.question_count())
202 .field("answer_count", &self.answer_count())
203 .field("name_server_count", &self.name_server_count())
204 .field("additional_records_count", &self.additional_records_count())
205 .finish()
206 }
207}
208
209#[derive(Copy, Clone, Debug, PartialEq)]
211pub enum DnsHeaderKind {
212 Query,
214 Response,
216}
217
218#[derive(Copy, Clone, Debug, PartialEq)]
220pub enum DnsHeaderOpcode {
221 Query,
222 InverseQuery,
223 Status,
224 Notify,
225 Update,
226 Reserved(u8),
227}
228
229impl From<u8> for DnsHeaderOpcode {
230 fn from(value: u8) -> Self {
231 match value {
232 0 => DnsHeaderOpcode::Query,
233 1 => DnsHeaderOpcode::InverseQuery,
234 2 => DnsHeaderOpcode::Status,
235 4 => DnsHeaderOpcode::Notify,
236 5 => DnsHeaderOpcode::Update,
237 _ => DnsHeaderOpcode::Reserved(value),
238 }
239 }
240}
241
242impl From<DnsHeaderOpcode> for u8 {
243 fn from(value: DnsHeaderOpcode) -> Self {
244 match value {
245 DnsHeaderOpcode::Query => 0,
246 DnsHeaderOpcode::InverseQuery => 1,
247 DnsHeaderOpcode::Status => 2,
248 DnsHeaderOpcode::Notify => 4,
249 DnsHeaderOpcode::Update => 5,
250 DnsHeaderOpcode::Reserved(value) => value,
251 }
252 }
253}
254
255#[derive(Copy, Clone, Debug, PartialEq)]
257pub enum DnsHeaderResponseCode {
258 NoError,
259 FormatError,
260 ServerFailure,
261 NonExistentDomain,
262 NotImplemented,
263 Refused,
264 ExistentDomain,
265 ExistentRrSet,
266 NonExistentRrSet,
267 NotAuthoritative,
268 NotZone,
269 BadOptVersionOrBadSignature,
270 BadKey,
271 BadTime,
272 BadMode,
273 BadName,
274 BadAlg,
275 Reserved(u8),
276}
277
278impl From<DnsHeaderResponseCode> for u8 {
279 fn from(r: DnsHeaderResponseCode) -> Self {
280 match r {
281 DnsHeaderResponseCode::NoError => 0,
282 DnsHeaderResponseCode::FormatError => 1,
283 DnsHeaderResponseCode::ServerFailure => 2,
284 DnsHeaderResponseCode::NonExistentDomain => 3,
285 DnsHeaderResponseCode::NotImplemented => 4,
286 DnsHeaderResponseCode::Refused => 5,
287 DnsHeaderResponseCode::ExistentDomain => 6,
288 DnsHeaderResponseCode::ExistentRrSet => 7,
289 DnsHeaderResponseCode::NonExistentRrSet => 8,
290 DnsHeaderResponseCode::NotAuthoritative => 9,
291 DnsHeaderResponseCode::NotZone => 10,
292 DnsHeaderResponseCode::BadOptVersionOrBadSignature => 16,
293 DnsHeaderResponseCode::BadKey => 17,
294 DnsHeaderResponseCode::BadTime => 18,
295 DnsHeaderResponseCode::BadMode => 19,
296 DnsHeaderResponseCode::BadName => 20,
297 DnsHeaderResponseCode::BadAlg => 21,
298 DnsHeaderResponseCode::Reserved(n) => n,
299 }
300 }
301}
302
303impl From<u8> for DnsHeaderResponseCode {
304 fn from(n: u8) -> Self {
305 match n {
306 0 => DnsHeaderResponseCode::NoError,
307 1 => DnsHeaderResponseCode::FormatError,
308 2 => DnsHeaderResponseCode::ServerFailure,
309 3 => DnsHeaderResponseCode::NonExistentDomain,
310 4 => DnsHeaderResponseCode::NotImplemented,
311 5 => DnsHeaderResponseCode::Refused,
312 6 => DnsHeaderResponseCode::ExistentDomain,
313 7 => DnsHeaderResponseCode::ExistentRrSet,
314 8 => DnsHeaderResponseCode::NonExistentRrSet,
315 9 => DnsHeaderResponseCode::NotAuthoritative,
316 10 => DnsHeaderResponseCode::NotZone,
317 16 => DnsHeaderResponseCode::BadOptVersionOrBadSignature,
318 17 => DnsHeaderResponseCode::BadKey,
319 18 => DnsHeaderResponseCode::BadTime,
320 19 => DnsHeaderResponseCode::BadMode,
321 20 => DnsHeaderResponseCode::BadName,
322 21 => DnsHeaderResponseCode::BadAlg,
323 n => DnsHeaderResponseCode::Reserved(n),
324 }
325 }
326}