summaryrefslogtreecommitdiff
path: root/src/dns/packet/header.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/dns/packet/header.rs')
-rw-r--r--src/dns/packet/header.rs102
1 files changed, 102 insertions, 0 deletions
diff --git a/src/dns/packet/header.rs b/src/dns/packet/header.rs
new file mode 100644
index 0000000..2355ecb
--- /dev/null
+++ b/src/dns/packet/header.rs
@@ -0,0 +1,102 @@
+use super::{buffer::PacketBuffer, result::ResultCode};
+use crate::Result;
+
+#[derive(Clone, Debug)]
+pub struct DnsHeader {
+ pub id: u16, // 16 bits
+
+ pub recursion_desired: bool, // 1 bit
+ pub truncated_message: bool, // 1 bit
+ pub authoritative_answer: bool, // 1 bit
+ pub opcode: u8, // 4 bits
+ pub response: bool, // 1 bit
+
+ pub rescode: ResultCode, // 4 bits
+ pub checking_disabled: bool, // 1 bit
+ pub authed_data: bool, // 1 bit
+ pub z: bool, // 1 bit
+ pub recursion_available: bool, // 1 bit
+
+ pub questions: u16, // 16 bits
+ pub answers: u16, // 16 bits
+ pub authoritative_entries: u16, // 16 bits
+ pub resource_entries: u16, // 16 bits
+}
+
+impl DnsHeader {
+ pub fn new() -> Self {
+ Self {
+ id: 0,
+
+ recursion_desired: false,
+ truncated_message: false,
+ authoritative_answer: false,
+ opcode: 0,
+ response: false,
+
+ rescode: ResultCode::NOERROR,
+ checking_disabled: false,
+ authed_data: false,
+ z: false,
+ recursion_available: false,
+
+ questions: 0,
+ answers: 0,
+ authoritative_entries: 0,
+ resource_entries: 0,
+ }
+ }
+
+ pub fn read(&mut self, buffer: &mut PacketBuffer) -> Result<()> {
+ self.id = buffer.read_u16()?;
+ let flags = buffer.read_u16()?;
+ let a = (flags >> 8) as u8;
+ let b = (flags & 0xFF) as u8;
+ self.recursion_desired = (a & (1 << 0)) > 0;
+ self.truncated_message = (a & (1 << 1)) > 0;
+ self.authoritative_answer = (a & (1 << 2)) > 0;
+ self.opcode = (a >> 3) & 0x0F;
+ self.response = (a & (1 << 7)) > 0;
+
+ self.rescode = ResultCode::from_num(b & 0x0F);
+ self.checking_disabled = (b & (1 << 4)) > 0;
+ self.authed_data = (b & (1 << 5)) > 0;
+ self.z = (b & (1 << 6)) > 0;
+ self.recursion_available = (b & (1 << 7)) > 0;
+
+ self.questions = buffer.read_u16()?;
+ self.answers = buffer.read_u16()?;
+ self.authoritative_entries = buffer.read_u16()?;
+ self.resource_entries = buffer.read_u16()?;
+
+ // Return the constant header size
+ Ok(())
+ }
+
+ pub fn write(&self, buffer: &mut PacketBuffer) -> Result<()> {
+ buffer.write_u16(self.id)?;
+
+ buffer.write_u8(
+ (self.recursion_desired as u8)
+ | ((self.truncated_message as u8) << 1)
+ | ((self.authoritative_answer as u8) << 2)
+ | (self.opcode << 3)
+ | ((self.response as u8) << 7),
+ )?;
+
+ buffer.write_u8(
+ (self.rescode as u8)
+ | ((self.checking_disabled as u8) << 4)
+ | ((self.authed_data as u8) << 5)
+ | ((self.z as u8) << 6)
+ | ((self.recursion_available as u8) << 7),
+ )?;
+
+ buffer.write_u16(self.questions)?;
+ buffer.write_u16(self.answers)?;
+ buffer.write_u16(self.authoritative_entries)?;
+ buffer.write_u16(self.resource_entries)?;
+
+ Ok(())
+ }
+}