From aa94dc21bbff3369852406503a4a2abd172b0820 Mon Sep 17 00:00:00 2001 From: Xander Bil Date: Wed, 26 Jun 2024 00:22:41 +0200 Subject: [PATCH] Convert errors using thiserror crate --- Cargo.lock | 21 +++++ Cargo.toml | 1 + src/db/models.rs | 10 +- src/errors.rs | 126 +++++++------------------ src/handlers/mod.rs | 11 +-- src/handlers/query.rs | 16 ++-- src/handlers/update/authenticate.rs | 18 +--- src/handlers/update/dnskey.rs | 4 +- src/handlers/update/mod.rs | 30 +++--- src/handlers/update/pubkeys/ed25519.rs | 10 +- src/handlers/update/pubkeys/mod.rs | 35 ++----- src/handlers/update/pubkeys/rsa.rs | 14 +-- src/handlers/update/sig.rs | 21 ++--- src/parser.rs | 18 ++-- src/reader.rs | 14 +-- src/resolver.rs | 6 +- 16 files changed, 143 insertions(+), 212 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 993801a..a7cafca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -943,6 +943,26 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "thiserror" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -1361,5 +1381,6 @@ dependencies = [ "int-enum", "reqwest", "ring", + "thiserror", "tokio", ] diff --git a/Cargo.toml b/Cargo.toml index b4a374b..d61d391 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,3 +12,4 @@ base64 = "0.22.0" reqwest = {version = "0.12.4", features = ["json","default"]} asn1 = "0.16.2" int-enum = "1.1" +thiserror = "1.0" diff --git a/src/db/models.rs b/src/db/models.rs index c96545a..523ea10 100644 --- a/src/db/models.rs +++ b/src/db/models.rs @@ -1,5 +1,5 @@ use crate::{ - errors::DatabaseError, + errors::ZNSError, structs::{Class, Type, RR}, }; use diesel::prelude::*; @@ -81,7 +81,7 @@ impl Record { } } -pub async fn insert_into_database(rr: &RR) -> Result<(), DatabaseError> { +pub async fn insert_into_database(rr: &RR) -> Result<(), ZNSError> { let db_connection = &mut establish_connection(); let record = Record { name: rr.name.join("."), @@ -92,7 +92,7 @@ pub async fn insert_into_database(rr: &RR) -> Result<(), DatabaseError> { rdata: rr.rdata.clone(), }; - Record::create(db_connection, record).map_err(|e| DatabaseError { + Record::create(db_connection, record).map_err(|e| ZNSError::Database { message: e.to_string(), })?; @@ -103,11 +103,11 @@ pub async fn get_from_database( name: &Vec, _type: Type, class: Class, -) -> Result, DatabaseError> { +) -> Result, ZNSError> { let db_connection = &mut establish_connection(); let records = Record::get(db_connection, name.join("."), _type.into(), class.into()).map_err(|e| { - DatabaseError { + ZNSError::Database { message: e.to_string(), } })?; diff --git a/src/errors.rs b/src/errors.rs index 42b450f..d61b4a3 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,100 +1,44 @@ -use core::fmt; +use thiserror::Error; use crate::structs::RCODE; -pub struct DNSError { - pub message: String, - pub rcode: RCODE, +#[derive(Error, Debug)] +pub enum ZNSError { + #[error("Parse Error for {object:?}: {message:?}")] + Parse { object: String, message: String }, + #[error("Database Error: {message:?}")] + Database { message: String }, + #[error("Reader Error: {message:?}")] + Reader { message: String }, + #[error("PublicKey Error: {message:?}")] + PublicKey { message: String }, + #[error("Reqwest error")] + Reqwest(#[from] reqwest::Error), + + #[error("DNS Query Format Error: {message:?}")] + Formerr { message: String }, + #[error("Domain name does not exist")] + NXDomain { domain: String }, + #[error("NotImplemented Error for {object:?}: {message:?}")] + NotImp { object: String, message: String }, + #[error("Authentication Error: {message:?}")] + NotAuth { message: String }, + #[error("I refuse to answer the query: {message:?}")] + Refused { message: String }, } -impl fmt::Display for DNSError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Error: {}", self.message) - } -} +impl ZNSError { + pub fn rcode(&self) -> RCODE { + match self { + ZNSError::Formerr { .. } | ZNSError::Parse { .. } | ZNSError::Reader { .. } => { + RCODE::FORMERR + } + ZNSError::Database { .. } | ZNSError::Reqwest(_) => RCODE::SERVFAIL, -#[derive(Debug)] -pub struct ParseError { - pub object: String, - pub message: String, -} - -impl fmt::Display for ParseError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Parse Error for {}: {}", self.object, self.message) - } -} - -#[derive(Debug)] -pub struct DatabaseError { - pub message: String, -} - -impl fmt::Display for DatabaseError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Database Error: {}", self.message) - } -} - -#[derive(Debug)] -pub struct AuthenticationError { - pub message: String, -} - -impl fmt::Display for AuthenticationError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Authentication Error: {}", self.message) - } -} - -#[derive(Debug)] -pub struct ReaderError { - pub message: String, -} - -impl fmt::Display for ReaderError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Reader Error: {}", self.message) - } -} - -impl From for ParseError -where - E: Into, -{ - fn from(value: E) -> Self { - ParseError { - object: String::from("Reader"), - message: value.into().to_string(), - } - } -} - -impl From for DNSError -where - E: Into, -{ - fn from(value: E) -> Self { - DNSError { - message: value.into().to_string(), - rcode: RCODE::FORMERR, - } - } -} - -trait Supported {} - -impl Supported for reqwest::Error {} -impl Supported for DatabaseError {} - -impl From for AuthenticationError -where - E: Supported, - E: std::fmt::Display, -{ - fn from(value: E) -> Self { - AuthenticationError { - message: value.to_string(), + ZNSError::NotAuth { .. } | ZNSError::PublicKey { .. } => RCODE::NOTAUTH, + ZNSError::NXDomain { .. } => RCODE::NXDOMAIN, + ZNSError::NotImp { .. } => RCODE::NOTIMP, + ZNSError::Refused { .. } => RCODE::REFUSED, } } } diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index 548a3ae..6de0873 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs @@ -1,6 +1,6 @@ use crate::{ - errors::DNSError, - structs::{Message, Opcode, RCODE}, + errors::ZNSError, + structs::{Message, Opcode}, }; use self::{query::QueryHandler, update::UpdateHandler}; @@ -9,21 +9,20 @@ mod query; mod update; pub trait ResponseHandler { - async fn handle(message: &Message, raw: &[u8]) -> Result; + async fn handle(message: &Message, raw: &[u8]) -> Result; } pub struct Handler {} impl ResponseHandler for Handler { - async fn handle(message: &Message, raw: &[u8]) -> Result { + async fn handle(message: &Message, raw: &[u8]) -> Result { match message.get_opcode() { Ok(opcode) => match opcode { Opcode::QUERY => QueryHandler::handle(&message, raw).await, Opcode::UPDATE => UpdateHandler::handle(&message, raw).await, }, - Err(e) => Err(DNSError { + Err(e) => Err(ZNSError::Formerr { message: e.to_string(), - rcode: RCODE::FORMERR, }), } } diff --git a/src/handlers/query.rs b/src/handlers/query.rs index d9bec21..680df0a 100644 --- a/src/handlers/query.rs +++ b/src/handlers/query.rs @@ -1,15 +1,11 @@ -use crate::{ - db::models::get_from_database, - errors::DNSError, - structs::{Message, RCODE}, -}; +use crate::{db::models::get_from_database, errors::ZNSError, structs::Message}; use super::ResponseHandler; pub struct QueryHandler {} impl ResponseHandler for QueryHandler { - async fn handle(message: &Message, _raw: &[u8]) -> Result { + async fn handle(message: &Message, _raw: &[u8]) -> Result { let mut response = message.clone(); response.header.arcount = 0; //TODO: fix this, handle unknown class values @@ -23,12 +19,16 @@ impl ResponseHandler for QueryHandler { match answers { Ok(rrs) => { + if rrs.len() == 0 { + return Err(ZNSError::NXDomain { + domain: question.qname.join("."), + }); + } response.header.ancount = rrs.len() as u16; response.answer.extend(rrs) } Err(e) => { - return Err(DNSError { - rcode: RCODE::NXDOMAIN, + return Err(ZNSError::Database { message: e.to_string(), }) } diff --git a/src/handlers/update/authenticate.rs b/src/handlers/update/authenticate.rs index 969a3d6..6c0242d 100644 --- a/src/handlers/update/authenticate.rs +++ b/src/handlers/update/authenticate.rs @@ -1,15 +1,15 @@ use crate::{ config::Config, db::models::get_from_database, - errors::{AuthenticationError, DatabaseError}, + errors::ZNSError, parser::FromBytes, reader::Reader, structs::{Class, RRClass, RRType, Type}, }; -use super::{dnskey::DNSKeyRData, pubkeys::PublicKeyError, sig::Sig}; +use super::{dnskey::DNSKeyRData, sig::Sig}; -pub async fn authenticate(sig: &Sig, zone: &Vec) -> Result { +pub async fn authenticate(sig: &Sig, zone: &Vec) -> Result { if zone.len() >= 4 { let username = &zone[zone.len() - 4]; // Should match: username.users.zeus.gent @@ -21,7 +21,7 @@ pub async fn authenticate(sig: &Sig, zone: &Vec) -> Result Result, sig: &Sig) -> Result { +async fn validate_dnskey(zone: &Vec, sig: &Sig) -> Result { Ok( get_from_database(zone, Type::Type(RRType::DNSKEY), Class::Class(RRClass::IN)) .await? @@ -52,11 +52,3 @@ async fn validate_dnskey(zone: &Vec, sig: &Sig) -> Result for AuthenticationError { - fn from(value: PublicKeyError) -> Self { - AuthenticationError { - message: value.to_string(), - } - } -} diff --git a/src/handlers/update/dnskey.rs b/src/handlers/update/dnskey.rs index 39af8e5..3d0d343 100644 --- a/src/handlers/update/dnskey.rs +++ b/src/handlers/update/dnskey.rs @@ -1,4 +1,4 @@ -use crate::{errors::ParseError, parser::FromBytes, reader::Reader}; +use crate::{errors::ZNSError, parser::FromBytes, reader::Reader}; use super::sig::Algorithm; @@ -13,7 +13,7 @@ pub struct DNSKeyRData { //TODO: validate values impl FromBytes for DNSKeyRData { - fn from_bytes(reader: &mut Reader) -> Result { + fn from_bytes(reader: &mut Reader) -> Result { Ok(DNSKeyRData { flags: reader.read_u16()?, protocol: reader.read_u8()?, diff --git a/src/handlers/update/mod.rs b/src/handlers/update/mod.rs index 6df813e..c1cac91 100644 --- a/src/handlers/update/mod.rs +++ b/src/handlers/update/mod.rs @@ -1,7 +1,7 @@ use crate::{ db::models::{delete_from_database, insert_into_database}, - errors::DNSError, - structs::{Class, Message, RRClass, RRType, Type, RCODE}, + errors::ZNSError, + structs::{Class, Message, RRClass, RRType, Type}, utils::vec_equal, }; @@ -17,15 +17,14 @@ mod sig; pub struct UpdateHandler {} impl ResponseHandler for UpdateHandler { - async fn handle(message: &Message, raw: &[u8]) -> Result { + async fn handle(message: &Message, raw: &[u8]) -> Result { let response = message.clone(); // Zone section (question) processing if (message.header.qdcount != 1) || !matches!(message.question[0].qtype, Type::Type(RRType::SOA)) { - return Err(DNSError { + return Err(ZNSError::Formerr { message: "Qdcount not one".to_string(), - rcode: RCODE::FORMERR, }); } @@ -33,9 +32,8 @@ impl ResponseHandler for UpdateHandler { let zone = &message.question[0]; let zlen = zone.qname.len(); if !(zlen >= 2 && zone.qname[zlen - 1] == "gent" && zone.qname[zlen - 2] == "zeus") { - return Err(DNSError { + return Err(ZNSError::Formerr { message: "Invalid zone".to_string(), - rcode: RCODE::NOTAUTH, }); } @@ -50,15 +48,13 @@ impl ResponseHandler for UpdateHandler { .await .is_ok_and(|x| x) { - return Err(DNSError { + return Err(ZNSError::NotAuth { message: "Unable to verify authentication".to_string(), - rcode: RCODE::NOTAUTH, }); } } else { - return Err(DNSError { + return Err(ZNSError::NotAuth { message: "No KEY record at the end of request found".to_string(), - rcode: RCODE::NOTAUTH, }); } @@ -68,9 +64,8 @@ impl ResponseHandler for UpdateHandler { // Check if rr has same zone if rlen < zlen || !(vec_equal(&zone.qname, &rr.name[rlen - zlen..])) { - return Err(DNSError { + return Err(ZNSError::Refused { message: "RR has different zone from Question".to_string(), - rcode: RCODE::NOTZONE, }); } @@ -84,9 +79,8 @@ impl ResponseHandler for UpdateHandler { .contains(&rr.class) { true => { - return Err(DNSError { + return Err(ZNSError::Formerr { message: "RR has invalid rr,ttl or class".to_string(), - rcode: RCODE::FORMERR, }); } false => (), @@ -99,9 +93,9 @@ impl ResponseHandler for UpdateHandler { } else if rr.class == Class::Class(RRClass::ANY) { if rr._type == Type::Type(RRType::ANY) { if rr.name == zone.qname { - return Err(DNSError { - message: "Not yet implemented".to_string(), - rcode: RCODE::NOTIMP, + return Err(ZNSError::NotImp { + object: String::from("Update Handler"), + message: "rr.name == zone.qname".to_string(), }); } else { delete_from_database(&rr.name, None, Class::Class(RRClass::IN), None).await; diff --git a/src/handlers/update/pubkeys/ed25519.rs b/src/handlers/update/pubkeys/ed25519.rs index df3b8a6..d392cdf 100644 --- a/src/handlers/update/pubkeys/ed25519.rs +++ b/src/handlers/update/pubkeys/ed25519.rs @@ -1,15 +1,15 @@ use ring::signature; -use crate::{handlers::update::sig::Algorithm, reader::Reader}; +use crate::{errors::ZNSError, handlers::update::sig::Algorithm, reader::Reader}; -use super::{PublicKey, PublicKeyError, SSH_ED25519}; +use super::{PublicKey, SSH_ED25519}; pub struct Ed25519PublicKey { data: Vec, } impl PublicKey for Ed25519PublicKey { - fn from_openssh(key: &[u8]) -> Result + fn from_openssh(key: &[u8]) -> Result where Self: Sized, { @@ -21,7 +21,7 @@ impl PublicKey for Ed25519PublicKey { }) } - fn from_dnskey(key: &[u8]) -> Result + fn from_dnskey(key: &[u8]) -> Result where Self: Sized, { @@ -33,7 +33,7 @@ impl PublicKey for Ed25519PublicKey { data: &[u8], signature: &[u8], _algorithm: &Algorithm, - ) -> Result { + ) -> Result { let pkey = ring::signature::UnparsedPublicKey::new(&signature::ED25519, &self.data); Ok(pkey.verify(data, signature).is_ok()) diff --git a/src/handlers/update/pubkeys/mod.rs b/src/handlers/update/pubkeys/mod.rs index 1c238f4..95a26f4 100644 --- a/src/handlers/update/pubkeys/mod.rs +++ b/src/handlers/update/pubkeys/mod.rs @@ -1,42 +1,23 @@ mod ed25519; mod rsa; -use core::fmt; use std::str::from_utf8; -use crate::{errors::ReaderError, reader::Reader}; +use crate::errors::ZNSError; +use crate::reader::Reader; pub use self::ed25519::Ed25519PublicKey; pub use self::rsa::RsaPublicKey; use super::sig::Algorithm; -#[derive(Debug)] -pub struct PublicKeyError { - pub message: String, -} - -impl fmt::Display for PublicKeyError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Public Key Error: {}", self.message) - } -} - -impl From for PublicKeyError { - fn from(value: ReaderError) -> Self { - PublicKeyError { - message: value.to_string(), - } - } -} - pub const SSH_ED25519: &str = "ssh-ed25519"; pub const SSH_RSA: &str = "ssh-rsa"; pub trait PublicKey { - fn verify_ssh_type(reader: &mut Reader, key_type: &str) -> Result<(), PublicKeyError> { + fn verify_ssh_type(reader: &mut Reader, key_type: &str) -> Result<(), ZNSError> { let type_size = reader.read_i32()?; let read = reader.read(type_size as usize)?; - let algo_type = from_utf8(&read).map_err(|e| PublicKeyError { + let algo_type = from_utf8(&read).map_err(|e| ZNSError::PublicKey { message: format!( "Could not convert type name bytes to string: {}", e.to_string() @@ -46,17 +27,17 @@ pub trait PublicKey { if algo_type == key_type { Ok(()) } else { - Err(PublicKeyError { + Err(ZNSError::PublicKey { message: String::from("ssh key type does not match identifier"), }) } } - fn from_openssh(key: &[u8]) -> Result + fn from_openssh(key: &[u8]) -> Result where Self: Sized; - fn from_dnskey(key: &[u8]) -> Result + fn from_dnskey(key: &[u8]) -> Result where Self: Sized; @@ -65,5 +46,5 @@ pub trait PublicKey { data: &[u8], signature: &[u8], algorithm: &Algorithm, - ) -> Result; + ) -> Result; } diff --git a/src/handlers/update/pubkeys/rsa.rs b/src/handlers/update/pubkeys/rsa.rs index c228323..5ec5809 100644 --- a/src/handlers/update/pubkeys/rsa.rs +++ b/src/handlers/update/pubkeys/rsa.rs @@ -1,8 +1,8 @@ use ring::signature; -use crate::{handlers::update::sig::Algorithm, reader::Reader}; +use crate::{errors::ZNSError, handlers::update::sig::Algorithm, reader::Reader}; -use super::{PublicKey, PublicKeyError, SSH_RSA}; +use super::{PublicKey, SSH_RSA}; pub struct RsaPublicKey { e: Vec, @@ -16,7 +16,7 @@ struct RsaAsn1<'a> { } impl PublicKey for RsaPublicKey { - fn from_openssh(key: &[u8]) -> Result + fn from_openssh(key: &[u8]) -> Result where Self: Sized, { @@ -34,19 +34,19 @@ impl PublicKey for RsaPublicKey { data: &[u8], signature: &[u8], algorithm: &Algorithm, - ) -> Result { + ) -> Result { let result = asn1::write_single(&RsaAsn1 { n: asn1::BigInt::new(&self.n), e: asn1::BigInt::new(&self.e), }) - .map_err(|e| PublicKeyError { + .map_err(|e| ZNSError::PublicKey { message: format!("Verify Error: {}", e), })?; let signature_type = match algorithm { Algorithm::RSASHA512 => Ok(&signature::RSA_PKCS1_2048_8192_SHA512), Algorithm::RSASHA256 => Ok(&signature::RSA_PKCS1_2048_8192_SHA256), - _ => Err(PublicKeyError { + _ => Err(ZNSError::PublicKey { message: format!("RsaPublicKey: invalid verify algorithm",), }), }?; @@ -56,7 +56,7 @@ impl PublicKey for RsaPublicKey { Ok(pkey.verify(data, signature).is_ok()) } - fn from_dnskey(key: &[u8]) -> Result + fn from_dnskey(key: &[u8]) -> Result where Self: Sized, { diff --git a/src/handlers/update/sig.rs b/src/handlers/update/sig.rs index 5f67fb5..65b1d97 100644 --- a/src/handlers/update/sig.rs +++ b/src/handlers/update/sig.rs @@ -2,7 +2,7 @@ use base64::prelude::*; use int_enum::IntEnum; use crate::{ - errors::ParseError, + errors::ZNSError, parser::FromBytes, reader::Reader, structs::{LabelString, RR}, @@ -10,7 +10,7 @@ use crate::{ use super::{ dnskey::DNSKeyRData, - pubkeys::{Ed25519PublicKey, PublicKey, PublicKeyError, RsaPublicKey, SSH_ED25519, SSH_RSA}, + pubkeys::{Ed25519PublicKey, PublicKey, RsaPublicKey, SSH_ED25519, SSH_RSA}, }; pub struct Sig { @@ -41,9 +41,8 @@ pub enum Algorithm { } impl Algorithm { - pub fn from(value: u8) -> Result { - Algorithm::try_from(value).map_err(|a| ParseError { - // TODO: Should respond with error code refused or notimpl + pub fn from(value: u8) -> Result { + Algorithm::try_from(value).map_err(|a| ZNSError::NotImp { object: String::from("Algorithm"), message: format!("Usupported algorithm: {}", a), }) @@ -51,9 +50,9 @@ impl Algorithm { } impl FromBytes for SigRData { - fn from_bytes(reader: &mut Reader) -> Result { + fn from_bytes(reader: &mut Reader) -> Result { if reader.unread_bytes() < 18 { - Err(ParseError { + Err(ZNSError::Parse { object: String::from("KeyRData"), message: String::from("invalid rdata"), }) @@ -74,7 +73,7 @@ impl FromBytes for SigRData { } impl Sig { - pub fn new(rr: &RR, datagram: &[u8]) -> Result { + pub fn new(rr: &RR, datagram: &[u8]) -> Result { let mut request = datagram[0..datagram.len() - 11 - rr.rdlength as usize].to_vec(); request[11] -= 1; // Decrease arcount @@ -90,7 +89,7 @@ impl Sig { }) } - fn verify(&self, key: impl PublicKey) -> Result { + fn verify(&self, key: impl PublicKey) -> Result { key.verify( &self.raw_data, &self.key_rdata.signature, @@ -98,7 +97,7 @@ impl Sig { ) } - pub fn verify_ssh(&self, key: &str) -> Result { + pub fn verify_ssh(&self, key: &str) -> Result { let key_split: Vec<&str> = key.split_ascii_whitespace().collect(); let bin = BASE64_STANDARD.decode(key_split[1]).unwrap(); @@ -111,7 +110,7 @@ impl Sig { } } - pub fn verify_dnskey(&self, key: DNSKeyRData) -> Result { + pub fn verify_dnskey(&self, key: DNSKeyRData) -> Result { if self.key_rdata.algo != key.algorithm { Ok(false) } else { diff --git a/src/parser.rs b/src/parser.rs index 226f92f..11f8e8a 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,12 +1,12 @@ -use std::{mem::size_of, vec}; +use std::mem::size_of; use crate::{ - errors::ParseError, + errors::ZNSError, reader::Reader, structs::{Class, Header, LabelString, Message, Opcode, Question, RRClass, RRType, Type, RR}, }; -type Result = std::result::Result; +type Result = std::result::Result; impl From for u16 { fn from(value: Type) -> Self { @@ -83,7 +83,7 @@ pub trait ToBytes { impl FromBytes for Header { fn from_bytes(reader: &mut Reader) -> Result { if reader.unread_bytes() < size_of::
() { - Err(ParseError { + Err(ZNSError::Parse { object: String::from("Header"), message: String::from("Size of Header does not match"), }) @@ -124,7 +124,7 @@ impl FromBytes for LabelString { while code != 0 && (code & 0b11000000 == 0) && reader.unread_bytes() > code as usize { out.push( String::from_utf8(reader.read(code as usize)?.to_vec()).map_err(|e| { - ParseError { + ZNSError::Parse { object: String::from("Label"), message: e.to_string(), } @@ -159,7 +159,7 @@ impl FromBytes for Question { fn from_bytes(reader: &mut Reader) -> Result { // 16 for length octet + zero length octet if reader.unread_bytes() < 2 + size_of::() + size_of::() { - Err(ParseError { + Err(ZNSError::Parse { object: String::from("Question"), message: String::from("len of bytes smaller then minimum size"), }) @@ -167,7 +167,7 @@ impl FromBytes for Question { let qname = LabelString::from_bytes(reader)?; if reader.unread_bytes() < 4 { - Err(ParseError { + Err(ZNSError::Parse { object: String::from("Question"), message: String::from("len of rest bytes smaller then minimum size"), }) @@ -201,7 +201,7 @@ impl FromBytes for RR { fn from_bytes(reader: &mut Reader) -> Result { let name = LabelString::from_bytes(reader)?; if reader.unread_bytes() < size_of::() + size_of::() + 6 { - Err(ParseError { + Err(ZNSError::Parse { object: String::from("RR"), message: String::from("len of rest of bytes smaller then minimum size"), }) @@ -211,7 +211,7 @@ impl FromBytes for RR { let ttl = reader.read_i32()?; let rdlength = reader.read_u16()?; if reader.unread_bytes() < rdlength as usize { - Err(ParseError { + Err(ZNSError::Parse { object: String::from("RR"), message: String::from("len of rest of bytes not equal to rdlength"), }) diff --git a/src/reader.rs b/src/reader.rs index b349acf..82efbca 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -1,13 +1,13 @@ use std::array::TryFromSliceError; -use crate::errors::ReaderError; +use crate::errors::ZNSError; pub struct Reader<'a> { buffer: &'a [u8], position: usize, } -type Result = std::result::Result; +type Result = std::result::Result; impl<'a> Reader<'a> { pub fn new(buffer: &[u8]) -> Reader { @@ -23,7 +23,7 @@ impl<'a> Reader<'a> { pub fn read(&mut self, size: usize) -> Result> { if size > self.unread_bytes() { - Err(ReaderError { + Err(ZNSError::Reader { message: String::from("cannot read enough bytes"), }) } else { @@ -41,7 +41,7 @@ impl<'a> Reader<'a> { let result = u16::from_be_bytes( self.buffer[self.position..self.position + 2] .try_into() - .map_err(|e: TryFromSliceError| ReaderError { + .map_err(|e: TryFromSliceError| ZNSError::Reader { message: e.to_string(), })?, ); @@ -53,7 +53,7 @@ impl<'a> Reader<'a> { let result = i32::from_be_bytes( self.buffer[self.position..self.position + 4] .try_into() - .map_err(|e: TryFromSliceError| ReaderError { + .map_err(|e: TryFromSliceError| ZNSError::Reader { message: e.to_string(), })?, ); @@ -65,7 +65,7 @@ impl<'a> Reader<'a> { let result = u32::from_be_bytes( self.buffer[self.position..self.position + 4] .try_into() - .map_err(|e: TryFromSliceError| ReaderError { + .map_err(|e: TryFromSliceError| ZNSError::Reader { message: e.to_string(), })?, ); @@ -75,7 +75,7 @@ impl<'a> Reader<'a> { pub fn seek(&self, position: usize) -> Result { if position >= self.position { - Err(ReaderError { + Err(ZNSError::Reader { message: String::from("Seeking into the future is not allowed!!"), }) } else { diff --git a/src/resolver.rs b/src/resolver.rs index 3427407..6447e7a 100644 --- a/src/resolver.rs +++ b/src/resolver.rs @@ -4,7 +4,7 @@ use std::sync::Arc; use tokio::net::UdpSocket; -use crate::errors::ParseError; +use crate::errors::ZNSError; use crate::handlers::{Handler, ResponseHandler}; use crate::parser::{FromBytes, ToBytes}; use crate::reader::Reader; @@ -12,7 +12,7 @@ use crate::structs::{Header, Message, RCODE}; const MAX_DATAGRAM_SIZE: usize = 4096; -fn handle_parse_error(bytes: &[u8], err: ParseError) -> Message { +fn handle_parse_error(bytes: &[u8], err: ZNSError) -> Message { eprintln!("{}", err); let mut reader = Reader::new(bytes); let mut header = Header::from_bytes(&mut reader).unwrap_or(Header { @@ -50,7 +50,7 @@ async fn get_response(bytes: &[u8]) -> Message { } Err(e) => { eprintln!("{}", e.to_string()); - message.set_response(e.rcode); + message.set_response(e.rcode()); message } },