use crate::{PacketFlag, OPCODE, RCODE};
use super::header::masks;
pub fn id(buffer: &[u8]) -> crate::Result<u16> {
buffer[..2]
.try_into()
.map(u16::from_be_bytes)
.map_err(|_| crate::SimpleDnsError::InvalidHeaderData)
}
pub fn questions(buffer: &[u8]) -> crate::Result<u16> {
buffer[4..6]
.try_into()
.map(u16::from_be_bytes)
.map_err(|_| crate::SimpleDnsError::InvalidHeaderData)
}
#[cfg(test)]
pub(crate) fn set_questions(buffer: &mut [u8], question_count: u16) {
buffer[4..6].copy_from_slice(&question_count.to_be_bytes());
}
pub fn answers(buffer: &[u8]) -> crate::Result<u16> {
buffer[6..8]
.try_into()
.map(u16::from_be_bytes)
.map_err(|_| crate::SimpleDnsError::InvalidHeaderData)
}
#[cfg(test)]
pub(crate) fn set_answers(buffer: &mut [u8], answers_count: u16) {
buffer[6..8].copy_from_slice(&answers_count.to_be_bytes());
}
pub fn name_servers(buffer: &[u8]) -> crate::Result<u16> {
buffer[8..10]
.try_into()
.map(u16::from_be_bytes)
.map_err(|_| crate::SimpleDnsError::InvalidHeaderData)
}
#[cfg(test)]
pub(crate) fn set_name_servers(buffer: &mut [u8], name_servers_count: u16) {
buffer[8..10].copy_from_slice(&name_servers_count.to_be_bytes());
}
pub fn additional_records(buffer: &[u8]) -> crate::Result<u16> {
buffer[10..12]
.try_into()
.map(u16::from_be_bytes)
.map_err(|_| crate::SimpleDnsError::InvalidHeaderData)
}
#[cfg(test)]
pub(crate) fn set_additional_records(buffer: &mut [u8], additional_records_count: u16) {
buffer[10..12].copy_from_slice(&additional_records_count.to_be_bytes());
}
#[allow(dead_code)]
pub(crate) fn set_flags(buffer: &mut [u8], flags: PacketFlag) -> crate::Result<()> {
let mut current_flags = buffer[2..4]
.try_into()
.map(u16::from_be_bytes)
.map_err(|_| crate::SimpleDnsError::InvalidHeaderData)?;
current_flags |= flags.bits();
buffer[2..4].copy_from_slice(¤t_flags.to_be_bytes());
Ok(())
}
#[allow(dead_code)]
pub(crate) fn remove_flags(buffer: &mut [u8], flags: PacketFlag) -> crate::Result<()> {
let mut current_flags = buffer[2..4]
.try_into()
.map(u16::from_be_bytes)
.map_err(|_| crate::SimpleDnsError::InvalidHeaderData)?;
current_flags ^= flags.bits();
buffer[2..4].copy_from_slice(¤t_flags.to_be_bytes());
Ok(())
}
pub fn has_flags(buffer: &[u8], flags: PacketFlag) -> crate::Result<bool> {
buffer[2..4]
.try_into()
.map(u16::from_be_bytes)
.map(|bits| PacketFlag::from_bits_truncate(bits).contains(flags))
.map_err(|_| crate::SimpleDnsError::InvalidHeaderData)
}
pub fn rcode(buffer: &[u8]) -> crate::Result<RCODE> {
buffer[2..4]
.try_into()
.map(u16::from_be_bytes)
.map(|flags| (flags & masks::RESPONSE_CODE_MASK).into())
.map_err(|_| crate::SimpleDnsError::InvalidHeaderData)
}
pub fn opcode(buffer: &[u8]) -> crate::Result<OPCODE> {
buffer[2..4]
.try_into()
.map(u16::from_be_bytes)
.map(|flags| ((flags & masks::OPCODE_MASK) >> masks::OPCODE_MASK.trailing_zeros()).into())
.map_err(|_| crate::SimpleDnsError::InvalidHeaderData)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn read_write_questions_count() {
let mut buffer = [0u8; 12];
set_questions(&mut buffer, 1);
assert_eq!(1, questions(&buffer).unwrap());
}
#[test]
fn read_write_answers_count() {
let mut buffer = [0u8; 12];
set_answers(&mut buffer, 1);
assert_eq!(1, answers(&buffer).unwrap());
}
#[test]
fn read_write_name_servers_count() {
let mut buffer = [0u8; 12];
set_name_servers(&mut buffer, 1);
assert_eq!(1, name_servers(&buffer).unwrap());
}
#[test]
fn read_write_additional_records_count() {
let mut buffer = [0u8; 12];
set_additional_records(&mut buffer, 1);
assert_eq!(1, additional_records(&buffer).unwrap());
}
}