Skip to content

Commit

Permalink
update comments
Browse files Browse the repository at this point in the history
  • Loading branch information
lucavallin committed Jul 23, 2023
1 parent 88f0ad9 commit 46632be
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 84 deletions.
29 changes: 14 additions & 15 deletions src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ use crate::{
rc::ResultCode,
};

// IP of *a.root-servers.net*
/// IP of *a.root-servers.net*
const A_ROOT_SERVERS_IP: Ipv4Addr = Ipv4Addr::new(198, 41, 0, 4);
// UDP socket port for lookups
/// UDP socket port for lookups
const LOOKUP_SOCKET_PORT: u16 = 42069;

// This function takes a UDP socket as input.
// It receives a DNS query from the socket, and sends a response back.
// If an error occurs, it returns the error.
/// This function takes a UDP socket as input.
/// It receives a DNS query from the socket, and sends a response back.
/// If an error occurs, it returns the error.
pub fn handle_query(socket: &UdpSocket) -> Result<(), BufferError> {
let mut req_buffer = PacketBuffer::new();
let (_, src) = socket.recv_from(&mut req_buffer.buf)?;
Expand Down Expand Up @@ -66,10 +66,10 @@ pub fn handle_query(socket: &UdpSocket) -> Result<(), BufferError> {
Ok(())
}

// This function takes a domain name, a query type, and a server address as input.
// It creates a UDP socket, and sends a DNS query to the server.
// It then waits for a response from the server, and returns the response.
// If an error occurs, it returns the error.
/// This function takes a domain name, a query type, and a server address as input.
/// It creates a UDP socket, and sends a DNS query to the server.
/// It then waits for a response from the server, and returns the response.
/// If an error occurs, it returns the error.
fn lookup(
qname: &str,
qtype: QueryType,
Expand Down Expand Up @@ -97,12 +97,11 @@ fn lookup(
DnsPacket::from_buffer(&mut res_buffer)
}

// This function takes a domain name and a query type as input.
// It starts by looking up the name in the root servers, and then follows the chain of
// referrals until it finds the authoritative name server for the domain.
// It then looks up the domain name in the authoritative name server, and returns the
// result.
// If an error occurs, it returns the error.
/// This function takes a domain name and a query type as input.
/// It starts by looking up the name in the root servers, and then follows the chain of
/// referrals until it finds the authoritative name server for the domain.
/// It then looks up the domain name in the authoritative name server, and returns the
/// result. If an error occurs, it returns the error.
fn recursive_lookup(qname: &str, qtype: QueryType) -> Result<DnsPacket, BufferError> {
// For now we're always starting with *a.root-servers.net*.
let mut ns = A_ROOT_SERVERS_IP;
Expand Down
86 changes: 43 additions & 43 deletions src/header.rs
Original file line number Diff line number Diff line change
@@ -1,42 +1,42 @@
use crate::pb::{BufferError, PacketBuffer};
use crate::rc::ResultCode;

// This struct represents the DNS header and contains the following fields:
// - id: a 16-bit identifier assigned by the program that generates any kind of query or response
// - recursion_desired: a 1-bit field that specifies whether recursive query support is desired
// - truncated_message: a 1-bit field that specifies that this message was truncated due to length greater than that permitted on the transmission channel
// - authoritative_answer: a 1-bit field that specifies that the responding name server is an authority for the domain name in question section
// - opcode: a 4-bit field that specifies kind of query in this message
// - response: a 1-bit field that specifies whether this message is a response to a query or a query
// - rescode: a 4-bit field that specifies the response code
// - checking_disabled: a 1-bit field that specifies whether checking of query and response is disabled or not
// - authed_data: a 1-bit field that specifies whether all data in the response is authenticated
// - z: a 1-bit field that must be zero in all queries and responses
// - recursion_available: a 1-bit field that specifies whether recursive query support is available in the name server
// - questions: a 16-bit field that specifies the number of entries in the question section
// - answers: a 16-bit field that specifies the number of resource records in the answer section
// - authoritative_entries: a 16-bit field that specifies the number of name server resource records in the authority records section
// - resource_entries: a 16-bit field that specifies the number of resource records in the additional records section
/// This struct represents the DNS header and contains the following fields:
/// - id: a 16-bit identifier assigned by the program that generates any kind of query or response
/// - recursion_desired: a 1-bit field that specifies whether recursive query support is desired
/// - truncated_message: a 1-bit field that specifies that this message was truncated due to length greater than that permitted on the transmission channel
/// - authoritative_answer: a 1-bit field that specifies that the responding name server is an authority for the domain name in question section
/// - opcode: a 4-bit field that specifies kind of query in this message
/// - response: a 1-bit field that specifies whether this message is a response to a query or a query
/// - rescode: a 4-bit field that specifies the response code
/// - checking_disabled: a 1-bit field that specifies whether checking of query and response is disabled or not
/// - authed_data: a 1-bit field that specifies whether all data in the response is authenticated
/// - z: a 1-bit field that must be zero in all queries and responses
/// - recursion_available: a 1-bit field that specifies whether recursive query support is available in the name server
/// - questions: a 16-bit field that specifies the number of entries in the question section
/// - answers: a 16-bit field that specifies the number of resource records in the answer section
/// - authoritative_entries: a 16-bit field that specifies the number of name server resource records in the authority records section
/// - resource_entries: a 16-bit field that specifies the number of resource records in the additional records section
#[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
pub id: u16,

pub recursion_desired: bool,
pub truncated_message: bool,
pub authoritative_answer: bool,
pub opcode: u8,
pub response: bool,

pub rescode: ResultCode,
pub checking_disabled: bool,
pub authed_data: bool,
pub z: bool,
pub recursion_available: bool,

pub questions: u16,
pub answers: u16,
pub authoritative_entries: u16,
pub resource_entries: u16,
}

impl DnsHeader {
Expand Down Expand Up @@ -64,11 +64,11 @@ impl DnsHeader {
}
}

// This function reads the DNS header fields from a given PacketBuffer and updates the fields of the DnsHeader struct accordingly.
// It reads the id, flags, rescode, questions, answers, authoritative_entries, and resource_entries fields from the buffer.
// It then updates the corresponding fields in the DnsHeader struct with the values read from the buffer.
// Finally, it returns a Result indicating whether the read was successful or not.
// Notice: Bits are shifted by (position of the fields in the header + size of the field)
/// This function reads the DNS header fields from a given PacketBuffer and updates the fields of the DnsHeader struct accordingly.
/// It reads the id, flags, rescode, questions, answers, authoritative_entries, and resource_entries fields from the buffer.
/// It then updates the corresponding fields in the DnsHeader struct with the values read from the buffer.
/// Finally, it returns a Result indicating whether the read was successful or not.
/// Notice: Bits are shifted by (position of the fields in the header + size of the field)
pub fn read(&mut self, buffer: &mut PacketBuffer) -> Result<(), BufferError> {
self.id = buffer.read_u16()?;

Expand Down Expand Up @@ -97,10 +97,10 @@ impl DnsHeader {
Ok(())
}

// This function writes the DNS header fields to a given PacketBuffer.
// It writes the id, flags, rescode, questions, answers, authoritative_entries, and resource_entries fields to the buffer.
// Finally, it returns a Result indicating whether the write was successful or not.
// Notice: Bits are shifted by (position of the fields in the header + size of the field)
/// This function writes the DNS header fields to a given PacketBuffer.
/// It writes the id, flags, rescode, questions, answers, authoritative_entries, and resource_entries fields to the buffer.
/// Finally, it returns a Result indicating whether the write was successful or not.
/// Notice: Bits are shifted by (position of the fields in the header + size of the field)
pub fn write(&self, buffer: &mut PacketBuffer) -> Result<(), BufferError> {
buffer.write_u16(self.id)?;

Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ struct Args {
port: u16,
}

// Entry point of the program.
/// Entry point of the server.
fn main() -> Result<(), Box<dyn Error>> {
let args = Args::parse();

Expand Down
4 changes: 2 additions & 2 deletions src/packet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ impl DnsPacket {
}
}

// Reads a DNS packet from a buffer
/// Reads a DNS packet from a buffer
pub fn from_buffer(buffer: &mut PacketBuffer) -> Result<DnsPacket, BufferError> {
let mut result = DnsPacket::new();
result.header.read(buffer)?;
Expand All @@ -53,7 +53,7 @@ impl DnsPacket {
Ok(result)
}

// Writes a DNS packet to a buffer
/// Writes a DNS packet to a buffer
pub fn write(&mut self, buffer: &mut PacketBuffer) -> Result<(), BufferError> {
self.header.questions = self.questions.len() as u16;
self.header.answers = self.answers.len() as u16;
Expand Down
32 changes: 16 additions & 16 deletions src/pb.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// BufferError is an enum that represents the various errors that can occur
/// BufferError is an enum that represents the various errors that can occur
#[derive(thiserror::Error, Debug, Clone)]
pub enum BufferError {
#[error("End of buffer")]
Expand All @@ -11,15 +11,15 @@ pub enum BufferError {
GenericError(String),
}

// Implement the From trait for BufferError, so that we can use the ? operator
/// Implement the From trait for BufferError, so that we can use the ? operator
impl From<std::io::Error> for BufferError {
fn from(e: std::io::Error) -> Self {
BufferError::GenericError(e.to_string())
}
}

// The `PacketBuffer` struct is used to hold the contents of a DNS packet as a byte buffer,
// and provides methods for reading and manipulating the buffer contents.
/// The `PacketBuffer` struct is used to hold the contents of a DNS packet as a byte buffer,
/// and provides methods for reading and manipulating the buffer contents.
pub struct PacketBuffer {
pub buf: [u8; 512],
pub pos: usize,
Expand Down Expand Up @@ -188,8 +188,8 @@ impl PacketBuffer {
Ok(())
}

// The write function writes a single byte to the buffer at the current position.
// If the buffer is already full, it returns an EndOfBuffer error.
/// The write function writes a single byte to the buffer at the current position.
/// If the buffer is already full, it returns an EndOfBuffer error.
pub fn write(&mut self, val: u8) -> Result<(), BufferError> {
if self.pos >= 512 {
return Err(BufferError::EndOfBuffer);
Expand All @@ -199,26 +199,26 @@ impl PacketBuffer {
Ok(())
}

// write_u8 writes a single byte to the buffer at the current position.
/// write_u8 writes a single byte to the buffer at the current position.
pub fn write_u8(&mut self, val: u8) -> Result<(), BufferError> {
self.write(val)?;

Ok(())
}

// write_u16 writes two bytes to the buffer at the current position.
// The most significant byte is written first.
/// write_u16 writes two bytes to the buffer at the current position.
/// The most significant byte is written first.
pub fn write_u16(&mut self, val: u16) -> Result<(), BufferError> {
self.write((val >> 8) as u8)?;
self.write((val & 0xFF) as u8)?;

Ok(())
}

#[allow(clippy::identity_op)]
// write_u32 writes four bytes to the buffer at the current position.
// The most significant byte is written first.
// This is useful for writing IPv4 addresses.
/// write_u32 writes four bytes to the buffer at the current position.
/// The most significant byte is written first.
/// This is useful for writing IPv4 addresses.
/// #[allow(clippy::identity_op)]
pub fn write_u32(&mut self, val: u32) -> Result<(), BufferError> {
self.write(((val >> 24) & 0xFF) as u8)?;
self.write(((val >> 16) & 0xFF) as u8)?;
Expand All @@ -228,7 +228,7 @@ impl PacketBuffer {
Ok(())
}

// write_qname writes query names in labeled form
/// write_qname writes query names in labeled form
pub fn write_qname(&mut self, qname: &str) -> Result<(), BufferError> {
for label in qname.split('.') {
// ox3f is 0011 1111 in binary, so we can use it to check if the label is longer than 63 characters
Expand All @@ -255,8 +255,8 @@ impl PacketBuffer {
Ok(())
}

// set_u16 writes two bytes to the buffer at the specified position.
// The most significant byte is written first.
/// set_u16 writes two bytes to the buffer at the specified position.
/// The most significant byte is written first.
pub fn set_u16(&mut self, pos: usize, val: u16) -> Result<(), BufferError> {
self.set(pos, (val >> 8) as u8)?;
// The bitwise AND operation with 0xFF then clears all bits except for the least significant byte,
Expand Down
4 changes: 2 additions & 2 deletions src/question.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::pb::{BufferError, PacketBuffer};

// 1, 2, 5, 15, 28 are IDs of the query types as defined in RFC 1035:
// see https://tools.ietf.org/html/rfc1035#section-3.2.2
/// 1, 2, 5, 15, 28 are IDs of the query types as defined in RFC 1035:
/// see https://tools.ietf.org/html/rfc1035#section-3.2.2
#[allow(clippy::upper_case_acronyms)]
#[derive(PartialEq, Eq, Debug, Clone, Hash, Copy)]
pub enum QueryType {
Expand Down
4 changes: 2 additions & 2 deletions src/rc.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Result codes as defined in RFC 1035:
// see https://tools.ietf.org/html/rfc1035#section-4.1.1
/// Result codes as defined in RFC 1035:
/// see https://tools.ietf.org/html/rfc1035#section-4.1.1
#[allow(clippy::upper_case_acronyms)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ResultCode {
Expand Down
6 changes: 3 additions & 3 deletions src/record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ use crate::question::QueryType;
use log::info;
use std::net::{Ipv4Addr, Ipv6Addr};

/// 0, 1, 2, 5, 15, 28 are IDs of the query types as defined in RFC 1035:
/// see https://tools.ietf.org/html/rfc1035#section-3.2.2
#[allow(clippy::upper_case_acronyms)]
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
// 0, 1, 2, 5, 15, 28 are IDs of the query types as defined in RFC 1035:
// see https://tools.ietf.org/html/rfc1035#section-3.2.2
pub enum DnsRecord {
UNKNOWN {
domain: String,
Expand Down Expand Up @@ -43,7 +43,7 @@ pub enum DnsRecord {
}

impl DnsRecord {
// Reads a DNS record from a buffer
/// Reads a DNS record from a buffer
#[allow(clippy::identity_op, clippy::redundant_field_names)]
pub fn read(buffer: &mut PacketBuffer) -> Result<DnsRecord, BufferError> {
let mut domain = String::new();
Expand Down

0 comments on commit 46632be

Please sign in to comment.