dns/src/proto/udp.rs
mice_on_drugs 6f9e4e9d59 Create module structure (#29)
Co-authored-by: Tobias Ottenweller <tobi@ottenweller.net>
Reviewed-on: #29
Co-authored-by: mice_on_drugs <tobi@ottenweller.net>
Co-committed-by: mice_on_drugs <tobi@ottenweller.net>
2022-06-05 19:05:49 +02:00

166 lines
4.7 KiB
Rust

use crate::models::DNSQuery;
use crate::models::DNSResponse;
use crate::proto::Coder;
pub struct UdpCoder {}
impl Coder for UdpCoder {
fn decode(datagram: &[u8]) -> Result<DNSQuery, DNSParseError> {
let message = Message::try_from(datagram)?;
Ok(DNSQuery {
id: message.header.id,
questions: vec![],
})
}
fn encode(respone: DNSResponse) -> Result<Vec<u8>, DNSParseError> {
todo!();
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum DNSParseError {
DatagramTooShort
}
#[derive(Debug, PartialEq, Clone, Copy)]
enum MessageType {
Query,
Response,
}
impl From<bool> for MessageType {
fn from(value: bool) -> MessageType {
match value {
false => Self::Query,
true => Self::Response,
}
}
}
#[derive(Debug, Clone, PartialEq)]
struct Header {
/// used by the requester to match up replies to outstanding queries
id: u16,
/// specifies whether this message is a query or a response
message_type: MessageType,
opcode: u8,
/// specifies that the responding name server is an authority for the domain name in question section
authorative_answer: bool,
/// specifies that this message was truncated due to length greater than that permitted on the transmission channel
truncated: bool,
/// it directs the name server to pursue the query recursively
recursion_desired: bool,
/// denotes whether recursive query support is available in the name server
recursion_available: bool,
// no support of rfc4035 at the moment
//pub authentic_data: bool,
// no support of rfc4035 at the moment
//pub checking_disabled: bool,
response_code: u8,
/// TODO: add documuentation about this count
query_count: u16,
/// TODO: add documuentation about this count
answer_count: u16,
/// TODO: add documuentation about this count
name_server_count: u16,
/// TODO: add documuentation about this count
additional_count: u16,
}
#[derive(Debug, Clone)]
struct Question {
name: String,
r#type: u16,
class: u16,
}
#[derive(Debug, Clone)]
struct ResourceRecord {
name: String,
r#type: u16,
class: u16,
ttl: u32,
data: String,
}
#[derive(Debug, Clone)]
pub struct Message {
header: Header,
questions: Vec<Question>,
answers: Vec<ResourceRecord>,
authorities: Vec<ResourceRecord>,
additionals: Vec<ResourceRecord>,
}
impl TryFrom<&[u8]> for Message {
type Error = DNSParseError;
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
todo!();
}
}
impl TryFrom<&[u8]> for Header {
type Error = DNSParseError;
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
const QR_MASK: u8 = 0b10000000;
const OPCODE_MASK: u8 = 0b01111000;
const AA_MASK: u8 = 0b00000100;
const TC_MASK: u8 = 0b00000010;
const RD_MASK: u8 = 0b00000001;
const RA_MASK: u8 = 0b10000000;
// no support of rfc4035 at the moment
//const AD_MASK: u8 = 0b00100000;
//const CD_MASK: u8 = 0b00010000;
const RCODE_MASK: u8 = 0b00001111;
const OPCODE_OFFSET: u8 = 3;
if value.len() < 12 {
return Err(DNSParseError::DatagramTooShort);
}
let id = u16::from_be_bytes((&value[..2]).try_into().unwrap());
let message_type = MessageType::from(value[2] & QR_MASK != 0);
let opcode =(value[2] & OPCODE_MASK) >> OPCODE_OFFSET;
let authorative_answer = (value[2] & AA_MASK) != 0;
let truncated = (value[2] & TC_MASK) != 0;
let recursion_desired = (value[2] & RD_MASK) != 0;
let recursion_available = (value[3] & RA_MASK) != 0;
// no support for rfc4035 at the moment
//let authentic_data = (datagram[2] & AD_MASK) != 0;
//let checking_disabled = (datagram[2] & CD_MASK) != 0;
let response_code = value[3] & RCODE_MASK;
let query_count = u16::from_be_bytes((value[4..6]).try_into().unwrap());
let answer_count = u16::from_be_bytes((value[6..8]).try_into().unwrap());
let name_server_count = u16::from_be_bytes((value[8..10]).try_into().unwrap());
let additional_count = u16::from_be_bytes((value[10..12]).try_into().unwrap());
Ok(Header {
id,
message_type,
opcode,
authorative_answer,
truncated,
recursion_desired,
recursion_available,
//authentic_data, // no support of rfc4035 at the moment
//checking_disabled, // no support of rfc4035 at the moment
response_code,
query_count,
answer_count,
name_server_count,
additional_count,
})
}
}