dns/src/proto.rs

165 lines
4.7 KiB
Rust
Raw Normal View History

use std::convert::TryInto;
2022-03-13 21:56:17 +01:00
#[derive(Debug)]
pub enum DNSOpCode {
QUERY = 0,
IQUERY = 1, // obsolete
STATUS = 2,
NOTIFY = 4,
UPDATE = 5,
}
impl From<u16> for DNSOpCode {
fn from(val: u16) -> Self {
match val {
0 => DNSOpCode::QUERY,
1 => DNSOpCode::IQUERY,
2 => DNSOpCode::STATUS,
4 => DNSOpCode::NOTIFY,
5 => DNSOpCode::UPDATE,
_ => panic!("KACKE"),
}
}
}
// TODO: FIXME: TECHNISCHE SCHULD (alle pubs weg und gucken wie es richtig geht)
#[derive(Debug)]
pub enum DNSRCode {
NOERROR = 0,
FORMERR = 1,
SERVFAIL = 2,
NXDOMAIN = 3,
NOTIMP = 4,
REFUSED = 5,
XYDOMAIN = 6,
XYRRSET = 7,
NXRRSET = 8,
NOTAUTH = 9,
NOTINZONE = 10,
}
2022-04-03 17:01:07 +02:00
#[derive(Debug)]
pub enum DNSParseErr {
DatagramLengthError,
SliceError(std::array::TryFromSliceError)
}
2022-03-13 21:56:17 +01:00
impl From<u16> for DNSRCode {
fn from(val: u16) -> Self {
match val {
0 => DNSRCode::NOERROR,
1 => DNSRCode::FORMERR,
2 => DNSRCode::SERVFAIL,
3 => DNSRCode::NXDOMAIN,
4 => DNSRCode::NOTIMP,
5 => DNSRCode::REFUSED,
6 => DNSRCode::XYDOMAIN,
7 => DNSRCode::XYRRSET,
8 => DNSRCode::NXRRSET,
9 => DNSRCode::NOTAUTH,
10 => DNSRCode::NOTINZONE,
_ => panic!("KACKE"),
}
}
}
#[derive(Debug)]
pub struct DNSHeader {
/// used by the requester to match up replies to outstanding queries
pub id: u16,
/// specifies whether this message is a query (false), or a response (true)
pub qr: bool,
pub opcode: DNSOpCode,
/// specifies that the responding name server is an authority for the domain name in question section
pub aa: bool,
/// specifies that this message was truncated due to length greater than that permitted on the transmission channel
pub tc: bool,
/// it directs the name server to pursue the query recursively
pub rd: bool,
/// denotes whether recursive query support is available in the name server
pub ra: bool,
/// TODO: add documuentation about this flag
pub ad: bool,
/// TODO: add documuentation about this flag
pub cd: bool,
pub rcode: DNSRCode,
/// TODO: add documuentation about this count
2022-03-13 21:56:17 +01:00
pub qd_zo_count: u16,
/// TODO: add documuentation about this count
2022-03-13 21:56:17 +01:00
pub an_pr_count: u16,
/// TODO: add documuentation about this count
2022-03-13 21:56:17 +01:00
pub ns_up_count: u16,
/// TODO: add documuentation about this count
2022-03-13 21:56:17 +01:00
pub ar_count: u16,
}
#[derive(Debug)]
pub struct DNSQuery {
pub hdr: DNSHeader,
pub name: String,
pub qclass: u16,
pub qtype: u16,
}
impl DNSHeader {
const QR_MASK: u16 = 0x0001;
const OPCODE_MASK: u16 = 0x000e;
const AA_MASK: u16 = 0x0020;
const TC_MASK: u16 = 0x0040;
const RD_MASK: u16 = 0x0080;
const RA_MASK: u16 = 0x0100;
const AD_MASK: u16 = 0x0400;
const CD_MASK: u16 = 0x0800;
const RCODE_MASK: u16 = 0xf000;
const OPCODE_OFFSET: u16 = 1;
const RCODE_OFFSET: u16 = 11;
2022-04-03 17:01:07 +02:00
pub fn from_udp_datagram(datagram: &[u8]) -> Result<Self, DNSParseErr> {
if datagram.len() < 11 {
2022-04-03 17:01:07 +02:00
return Err(DNSParseErr::DatagramLengthError);
}
2022-04-03 17:01:07 +02:00
let id = u16::from_be_bytes((&datagram[..2]).try_into()?);
2022-04-03 17:01:07 +02:00
let flags = u16::from_be_bytes((&datagram[2..4]).try_into()?);
let qr = (flags & DNSHeader::QR_MASK) != 0;
let opcode = DNSOpCode::from((flags & DNSHeader::OPCODE_MASK) >> DNSHeader::OPCODE_OFFSET);
let aa = (flags & DNSHeader::AA_MASK) != 0;
let tc = (flags & DNSHeader::TC_MASK) != 0;
let rd = (flags & DNSHeader::RD_MASK) != 0;
let ra = (flags & DNSHeader::RA_MASK) != 0;
let ad = (flags & DNSHeader::AD_MASK) != 0;
let cd = (flags & DNSHeader::CD_MASK) != 0;
let rcode = DNSRCode::from((flags & DNSHeader::RCODE_MASK) >> DNSHeader::RCODE_OFFSET);
2022-04-03 17:01:07 +02:00
let qd_zo_count = u16::from_be_bytes((&datagram[4..6]).try_into()?);
let an_pr_count = u16::from_be_bytes((&datagram[6..8]).try_into()?);
let ns_up_count = u16::from_be_bytes((&datagram[8..10]).try_into()?);
let ar_count = u16::from_be_bytes((&datagram[10..12]).try_into()?);
Ok(DNSHeader {
id,
qr,
opcode,
aa,
tc,
rd,
ra,
ad,
cd,
rcode,
qd_zo_count,
an_pr_count,
ns_up_count,
ar_count,
})
}
}
2022-04-03 17:01:07 +02:00
impl From<std::array::TryFromSliceError> for DNSParseErr {
fn from(err: std::array::TryFromSliceError) -> Self {
DNSParseErr::SliceError(err)
}
}