use crate::{read_u16_be, read_u8, write_u16_be, DnsError, DnsOpCode, DnsResponseCode};
use fixed_buffer::FixedBuf;
#[allow(clippy::struct_excessive_bools)]
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct DnsMessageHeader {
pub id: u16,
pub is_response: bool,
pub op_code: DnsOpCode,
pub authoritative_answer: bool,
pub truncated: bool,
pub recursion_desired: bool,
pub recursion_available: bool,
pub response_code: DnsResponseCode,
pub question_count: u16,
pub answer_count: u16,
pub name_server_count: u16,
pub additional_count: u16,
}
impl DnsMessageHeader {
pub fn read<const N: usize>(buf: &mut FixedBuf<N>) -> Result<Self, DnsError> {
let id = read_u16_be(buf)?;
let b = read_u8(buf)?;
let is_response = (b >> 7) == 1;
let op_code = DnsOpCode::new((b >> 3) & 0xF);
let authoritative_answer = ((b >> 2) & 1) == 1;
let truncated = ((b >> 1) & 1) == 1;
let recursion_desired = (b & 1) == 1;
let b = read_u8(buf)?;
let recursion_available = (b >> 7) == 1;
let response_code = DnsResponseCode::new(b & 0xF);
let question_count = read_u16_be(buf)?;
let answer_count = read_u16_be(buf)?;
let name_server_count = read_u16_be(buf)?;
let additional_count = read_u16_be(buf)?;
Ok(Self {
id,
is_response,
op_code,
authoritative_answer,
truncated,
recursion_desired,
recursion_available,
response_code,
question_count,
answer_count,
name_server_count,
additional_count,
})
}
pub fn write<const N: usize>(&self, out: &mut FixedBuf<N>) -> Result<(), DnsError> {
let bytes: [u8; 2] = self.id.to_be_bytes();
out.write_bytes(&bytes)
.map_err(|_| DnsError::ResponseBufferFull)?;
let b = (u8::from(self.is_response) << 7)
| (self.op_code.num() << 3)
| (u8::from(self.authoritative_answer) << 2)
| (u8::from(self.truncated) << 1)
| u8::from(self.recursion_desired);
out.write_bytes(&[b])
.map_err(|_| DnsError::ResponseBufferFull)?;
let b = (u8::from(self.recursion_available) << 7) | self.response_code.num();
out.write_bytes(&[b])
.map_err(|_| DnsError::ResponseBufferFull)?;
for count in [
self.question_count,
self.answer_count,
self.name_server_count,
self.additional_count,
] {
write_u16_be(out, count)?;
}
Ok(())
}
}