use crate::resource::*;
use std::net::SocketAddr;
use std::time::Duration;
use std::time::SystemTime;
use strum_macros::{Display, EnumString};
#[derive(Clone, Debug, Derivative)]
#[derivative(Eq, Hash, PartialEq)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct Message {
pub id: u16,
pub rd: bool,
pub tc: bool,
pub aa: bool,
pub opcode: Opcode,
pub qr: QR,
pub rcode: Rcode,
pub cd: bool,
pub ad: bool,
pub z: bool,
pub ra: bool,
pub questions: Vec<Question>,
pub answers: Vec<Record>,
pub authoritys: Vec<Record>,
pub additionals: Vec<Record>,
pub extension: Option<Extension>,
#[derivative(PartialEq = "ignore")]
#[derivative(Hash = "ignore")]
pub stats: Option<Stats>,
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct Question {
pub name: String,
pub r#type: Type,
pub class: Class,
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct Record {
pub name: String,
pub class: Class,
pub ttl: Duration,
pub resource: Resource,
}
impl Record {
pub fn new(name: &str, class: Class, ttl: Duration, resource: Resource) -> Self {
Self {
name: name.to_owned(),
class,
ttl,
resource,
}
}
pub fn r#type(&self) -> Type {
self.resource.r#type()
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct Extension {
pub payload_size: u16,
pub extend_rcode: u8,
pub version: u8,
pub dnssec_ok: bool,
}
impl Default for Extension {
fn default() -> Self {
Extension {
payload_size: 4096,
extend_rcode: 0,
version: 0,
dnssec_ok: false,
}
}
}
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct Stats {
pub start: SystemTime,
pub duration: Duration,
pub server: SocketAddr,
pub request_size: usize,
pub response_size: usize,
}
#[derive(Copy, Clone, Debug, EnumString, Eq, Hash, PartialEq)]
pub enum QR {
Query = 0,
Response = 1,
}
impl Default for QR {
fn default() -> Self {
QR::Query
}
}
impl QR {
pub fn from_bool(b: bool) -> QR {
match b {
false => QR::Query,
true => QR::Response,
}
}
pub fn to_bool(self) -> bool {
match self {
QR::Query => false,
QR::Response => true,
}
}
}
#[derive(Copy, Clone, Debug, Display, EnumString, Eq, Hash, FromPrimitive, PartialEq)]
#[allow(clippy::upper_case_acronyms)]
#[repr(u8)] pub enum Opcode {
Query = 0,
IQuery = 1,
Status = 2,
Notify = 4,
Update = 5,
DSO = 6,
}
impl Default for Opcode {
fn default() -> Self {
Opcode::Query
}
}
#[derive(Copy, Clone, Debug, Display, EnumString, Eq, Hash, FromPrimitive, PartialEq)]
#[allow(clippy::upper_case_acronyms)]
#[repr(u16)] pub enum Rcode {
NoError = 0,
FormErr = 1,
ServFail = 2,
NXDomain = 3,
NotImp = 4,
Refused = 5,
YXDomain = 6,
YXRRSet = 7,
NXRRSet = 8,
NotAuth = 9,
NotZone = 10,
DSOTYPENI = 11,
}
impl Default for Rcode {
fn default() -> Self {
Rcode::NoError
}
}
#[derive(Copy, Clone, Debug, Display, EnumString, Eq, FromPrimitive, Hash, PartialEq)]
#[allow(clippy::upper_case_acronyms)]
#[repr(u16)]
pub enum Type {
Reserved = 0,
A = 1,
NS = 2,
CNAME = 5,
SOA = 6,
PTR = 12,
MX = 15,
TXT = 16,
AAAA = 28,
SRV = 33,
OPT = 41,
SPF = 99,
ANY = 255,
}
impl Default for Type {
fn default() -> Self {
Type::ANY
}
}
#[derive(Copy, Clone, Debug, Display, EnumString, Eq, FromPrimitive, Hash, PartialEq)]
#[repr(u16)]
pub enum Class {
Reserved = 0,
#[strum(serialize = "IN")]
Internet = 1,
#[strum(serialize = "CS")]
CsNet = 2,
#[strum(serialize = "CH")]
Chaos = 3,
#[strum(serialize = "HS")]
Hesiod = 4,
None = 254,
#[strum(serialize = "*")]
Any = 255,
}
impl Default for Class {
fn default() -> Self {
Class::Internet
}
}
#[allow(clippy::upper_case_acronyms)]
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub enum Resource {
A(A), AAAA(AAAA),
CNAME(CNAME),
NS(NS),
PTR(PTR),
TXT(TXT),
SPF(TXT),
MX(MX),
SOA(SOA),
SRV(SRV),
OPT,
ANY, }
impl Resource {
pub fn r#type(&self) -> Type {
match self {
Resource::A(_) => Type::A,
Resource::AAAA(_) => Type::AAAA,
Resource::CNAME(_) => Type::CNAME,
Resource::NS(_) => Type::NS,
Resource::PTR(_) => Type::PTR,
Resource::TXT(_) => Type::TXT,
Resource::MX(_) => Type::MX,
Resource::SOA(_) => Type::SOA,
Resource::SRV(_) => Type::SRV,
Resource::SPF(_) => Type::SPF,
Resource::OPT => Type::OPT,
Resource::ANY => Type::ANY,
}
}
}