Implement TryFrom for DNSOpCode and DNSRCode. (#15)

Co-authored-by: Tobias Ottenweller <tobi@ottenweller.net>
Reviewed-on: #15
This commit is contained in:
mice_on_drugs 2022-04-03 19:03:46 +02:00 committed by ddidderr
parent a07fb80b45
commit cccdf5b5e9
Signed by: ddidderr
GPG Key ID: 3841F1C27E6F0E14
2 changed files with 53 additions and 50 deletions

View File

@ -1,11 +1,15 @@
use std::sync::mpsc;
use std::net::UdpSocket; use std::net::UdpSocket;
use std::sync::mpsc;
use std::thread::{self, JoinHandle}; use std::thread::{self, JoinHandle};
mod proto; mod proto;
use proto::DNSHeader; use proto::DNSHeader;
fn listen() -> (JoinHandle<()>, mpsc::Sender<Vec<u8>>, mpsc::Receiver<Vec<u8>>) { fn listen() -> (
JoinHandle<()>,
mpsc::Sender<Vec<u8>>,
mpsc::Receiver<Vec<u8>>,
) {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let tx_clone = tx.clone(); let tx_clone = tx.clone();

View File

@ -20,15 +20,17 @@ pub enum DNSOpCode {
Update = 5, Update = 5,
} }
impl From<u16> for DNSOpCode { impl TryFrom<u16> for DNSOpCode {
fn from(val: u16) -> Self { type Error = DNSParseError;
match val {
0 => DNSOpCode::Query, fn try_from(value: u16) -> Result<Self, Self::Error> {
1 => DNSOpCode::IQuery, match value {
2 => DNSOpCode::Status, 0 => Ok(DNSOpCode::Query),
4 => DNSOpCode::Notify, 1 => Ok(DNSOpCode::IQuery),
5 => DNSOpCode::Update, 2 => Ok(DNSOpCode::Status),
_ => panic!("KACKE"), 4 => Ok(DNSOpCode::Notify),
5 => Ok(DNSOpCode::Update),
_ => Err(DNSParseError::DNSOpCodeInvalid),
} }
} }
} }
@ -87,21 +89,23 @@ pub enum DNSRCode {
NotZone = 10, NotZone = 10,
} }
impl From<u16> for DNSRCode { impl TryFrom<u16> for DNSRCode {
fn from(val: u16) -> Self { type Error = DNSParseError;
match val {
0 => DNSRCode::NoError, fn try_from(value: u16) -> Result<Self, Self::Error> {
1 => DNSRCode::FormErr, match value {
2 => DNSRCode::ServFail, 0 => Ok(DNSRCode::NoError),
3 => DNSRCode::NXDomain, 1 => Ok(DNSRCode::FormErr),
4 => DNSRCode::NotImp, 2 => Ok(DNSRCode::ServFail),
5 => DNSRCode::Refused, 3 => Ok(DNSRCode::NXDomain),
6 => DNSRCode::YXDomain, 4 => Ok(DNSRCode::NotImp),
7 => DNSRCode::YXRRSet, 5 => Ok(DNSRCode::Refused),
8 => DNSRCode::NXRRSet, 6 => Ok(DNSRCode::YXDomain),
9 => DNSRCode::NotAuth, 7 => Ok(DNSRCode::YXRRSet),
10 => DNSRCode::NotZone, 8 => Ok(DNSRCode::NXRRSet),
_ => panic!("KACKE"), 9 => Ok(DNSRCode::NotAuth),
10 => Ok(DNSRCode::NotZone),
_ => Err(DNSParseError::DNSRCodeInvalid),
} }
} }
} }
@ -160,26 +164,26 @@ impl DNSHeader {
pub fn from_udp_datagram(datagram: &[u8]) -> Result<Self, DNSParseError> { pub fn from_udp_datagram(datagram: &[u8]) -> Result<Self, DNSParseError> {
if datagram.len() < 11 { if datagram.len() < 11 {
return Err(DNSParseError::DatagramLengthError); return Err(DNSParseError::DatagramTooShort);
} }
let id = u16::from_be_bytes((&datagram[..2]).try_into()?); let id = u16::from_be_bytes((&datagram[..2]).try_into().unwrap());
let flags = u16::from_be_bytes((&datagram[2..4]).try_into()?); let flags = u16::from_be_bytes((&datagram[2..4]).try_into().unwrap());
let qr = (flags & DNSHeader::QR_MASK) != 0; let qr = (flags & Self::QR_MASK) != 0;
let opcode = DNSOpCode::from((flags & DNSHeader::OPCODE_MASK) >> DNSHeader::OPCODE_OFFSET); let opcode = DNSOpCode::try_from((flags & Self::OPCODE_MASK) >> Self::OPCODE_OFFSET)?;
let aa = (flags & DNSHeader::AA_MASK) != 0; let aa = (flags & Self::AA_MASK) != 0;
let tc = (flags & DNSHeader::TC_MASK) != 0; let tc = (flags & Self::TC_MASK) != 0;
let rd = (flags & DNSHeader::RD_MASK) != 0; let rd = (flags & Self::RD_MASK) != 0;
let ra = (flags & DNSHeader::RA_MASK) != 0; let ra = (flags & Self::RA_MASK) != 0;
let ad = (flags & DNSHeader::AD_MASK) != 0; let ad = (flags & Self::AD_MASK) != 0;
let cd = (flags & DNSHeader::CD_MASK) != 0; let cd = (flags & Self::CD_MASK) != 0;
let rcode = DNSRCode::from((flags & DNSHeader::RCODE_MASK) >> DNSHeader::RCODE_OFFSET); let rcode = DNSRCode::try_from((flags & Self::RCODE_MASK) >> Self::RCODE_OFFSET)?;
let qd_zo_count = u16::from_be_bytes((&datagram[4..6]).try_into()?); let qd_zo_count = u16::from_be_bytes((&datagram[4..6]).try_into().unwrap());
let an_pr_count = u16::from_be_bytes((&datagram[6..8]).try_into()?); let an_pr_count = u16::from_be_bytes((&datagram[6..8]).try_into().unwrap());
let ns_up_count = u16::from_be_bytes((&datagram[8..10]).try_into()?); let ns_up_count = u16::from_be_bytes((&datagram[8..10]).try_into().unwrap());
let ar_count = u16::from_be_bytes((&datagram[10..12]).try_into()?); let ar_count = u16::from_be_bytes((&datagram[10..12]).try_into().unwrap());
Ok(DNSHeader { Ok(DNSHeader {
id, id,
@ -202,12 +206,7 @@ impl DNSHeader {
#[derive(Debug)] #[derive(Debug)]
pub enum DNSParseError { pub enum DNSParseError {
DatagramLengthError, DatagramTooShort,
SliceError(std::array::TryFromSliceError) DNSOpCodeInvalid,
} DNSRCodeInvalid,
impl From<std::array::TryFromSliceError> for DNSParseError {
fn from(err: std::array::TryFromSliceError) -> Self {
DNSParseError::SliceError(err)
}
} }