diff --git a/dnstp-server/src/main.rs b/dnstp-server/src/main.rs index 1f3dd28..7769d08 100644 --- a/dnstp-server/src/main.rs +++ b/dnstp-server/src/main.rs @@ -1,3 +1,5 @@ +//! DNS server component for processing requests and replying with DNS records + use clap::Parser; use std::{thread}; @@ -9,6 +11,7 @@ use std::net::SocketAddr; use dnstplib::net::socket::DNSSocket; use dnstplib::processor::RequestProcesor; +/// Command-line arguments for configuring the server #[derive(Parser, Debug)] #[command(author, version, about, long_about = None)] struct Args { diff --git a/dnstp/src/byte.rs b/dnstp/src/byte.rs index 2db7700..b85533e 100644 --- a/dnstp/src/byte.rs +++ b/dnstp/src/byte.rs @@ -1,18 +1,24 @@ +//! Utility functions for operating on bytes +/// 8-bit mask for wiping out bits past a byte. Formatted as a 32-bit number const BYTEMASK_32: u32 = 0b11111111; +/// 8-bit mask for wiping out bits past a byte. Formatted as a 16-bit number const BYTEMASK_16: u16 = 0b11111111; +/// Take two sequential bytes starting from idx in buffer and return a concatenated 2 byte number pub fn two_byte_extraction(buffer: &[u8], idx: usize) -> u16 { ((buffer[idx] as u16) << 8) | buffer[idx + 1] as u16 } +/// Take a 2 byte number and split it in to it's two 8 bit halves pub fn two_byte_split(num: u16) -> (u8, u8) { ((num >> 8) as u8, (num & BYTEMASK_16) as u8) } +/// Split a 32 bit number into it's 8-bit quartered components pub fn four_byte_split(num: u32) -> (u8, u8, u8, u8) { ((num >> 24) as u8, diff --git a/dnstp/src/message/answer.rs b/dnstp/src/message/answer.rs index 2e2a2b9..2a852c7 100644 --- a/dnstp/src/message/answer.rs +++ b/dnstp/src/message/answer.rs @@ -1,5 +1,5 @@ use crate::byte::{four_byte_split, two_byte_split}; -use crate::message::question::{QClass, QType}; +use crate::message::question::{DNSQuestion, QClass, QType}; use crate::string::encode_domain_name; #[derive(Ord, PartialOrd, Eq, PartialEq, Debug)] @@ -14,7 +14,7 @@ pub struct DNSAnswer { impl DNSAnswer { - pub fn to_bytes(& self) -> Vec + pub fn to_bytes(&self) -> Vec { let mut ret = encode_domain_name(&self.name); @@ -40,4 +40,16 @@ impl DNSAnswer { return ret } +} + +pub fn answers_to_bytes(answers: &Vec) -> Vec +{ + let mut ret = Vec::with_capacity(20); + + for a in answers + { + ret.append(&mut a.to_bytes()); + } + + ret } \ No newline at end of file diff --git a/dnstp/src/message/header.rs b/dnstp/src/message/header.rs index 230fce5..85baa35 100644 --- a/dnstp/src/message/header.rs +++ b/dnstp/src/message/header.rs @@ -2,14 +2,17 @@ use std::convert::TryFrom; use crate::byte::apply_split_bytes; use crate::message::header::Direction::Response; +/// Size in bytes for a DNS message pub const HEADER_SIZE: usize = 12; +/// Flag for whether the message represents a request or a response #[derive(Ord, PartialOrd, Eq, PartialEq, Debug, Copy, Clone)] pub enum Direction { Request = 0, Response = 1 } +/// Operation code for describing the purpose of the message #[derive(Ord, PartialOrd, Eq, PartialEq, Debug, Copy, Clone)] pub enum Opcode { Query = 0, @@ -32,6 +35,7 @@ impl TryFrom for Opcode { } } +/// What is the status of the request or response, what was the nature of the error, if encountered #[derive(Ord, PartialOrd, Eq, PartialEq, Debug, Copy, Clone)] pub enum ResponseCode { NoError = 0, @@ -68,17 +72,23 @@ impl TryFrom for ResponseCode { } } +/// Represents a header including flag fields and record counts #[derive(Ord, PartialOrd, Eq, PartialEq, Debug)] pub struct DNSHeader { + /// Random ID for associating responses with requests pub id: u16, + /// Is the message a request or the associated response pub direction: Direction, + /// What is the message function, e.g query, reverse DNS query pub opcode: Opcode, pub authoritative: bool, pub truncation: bool, pub recursion_desired: bool, pub recursion_available: bool, pub valid_zeroes: bool, + /// Status of the request or response pub response: ResponseCode, + /// Number of questions being made, should be the same in both the request and response pub question_count: u16, pub answer_record_count: u16, pub authority_record_count: u16, @@ -86,6 +96,7 @@ pub struct DNSHeader { } impl DNSHeader { + /// Serialise a header memory structure back into bytes for putting on the wire pub fn to_bytes(&self) -> [u8; 12] { let mut header_bytes: [u8; 12] = [0; 12]; diff --git a/dnstp/src/message/response.rs b/dnstp/src/message/response.rs index 3f0dd9f..79c2454 100644 --- a/dnstp/src/message/response.rs +++ b/dnstp/src/message/response.rs @@ -1,5 +1,5 @@ use std::net::SocketAddr; -use crate::message::answer::DNSAnswer; +use crate::message::answer::{answers_to_bytes, DNSAnswer}; use crate::message::header::DNSHeader; use crate::message::question::{DNSQuestion, questions_to_bytes}; @@ -17,8 +17,10 @@ impl DNSResponse { { let mut header_bytes = self.header.to_bytes().to_vec(); let mut body_bytes = questions_to_bytes(&self.questions); + let mut answer_bytes = answers_to_bytes(&self.answers); header_bytes.append(&mut body_bytes); + header_bytes.append(&mut answer_bytes); return header_bytes }