use std::mem::transmute;
use std::net::{Ipv4Addr, Ipv6Addr};
use crate::message::{DecodeError, EncodeError, MsgReader, MsgWriter};
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Class {
Internet,
Any,
Other(u16),
}
impl Class {
pub fn from_u16(u: u16) -> Class {
match u {
1 => Class::Internet,
255 => Class::Any,
n => Class::Other(n),
}
}
pub fn to_u16(&self) -> u16 {
match *self {
Class::Internet => 1,
Class::Any => 255,
Class::Other(n) => n,
}
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum RecordType {
A,
AAAA,
CName,
Mx,
Ns,
Ptr,
Soa,
Srv,
Txt,
Other(u16),
}
macro_rules! record_types {
( $( $name:ident => $code:expr , )+ ) => {
impl RecordType {
pub fn from_u16(u: u16) -> RecordType {
match u {
$( $code => RecordType::$name , )+
n => RecordType::Other(n),
}
}
pub fn to_u16(&self) -> u16 {
match *self {
$( RecordType::$name => $code , )+
RecordType::Other(n) => n,
}
}
}
}
}
record_types! {
A => 1,
AAAA => 28,
CName => 5,
Mx => 15,
Ns => 2,
Ptr => 12,
Soa => 6,
Srv => 33,
Txt => 16,
}
pub trait Record: Sized {
fn decode(data: &mut MsgReader) -> Result<Self, DecodeError>;
fn encode(&self, data: &mut MsgWriter) -> Result<(), EncodeError>;
fn record_type() -> RecordType;
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct A {
pub address: Ipv4Addr,
}
impl Record for A {
fn decode(data: &mut MsgReader) -> Result<Self, DecodeError> {
let mut buf = [0; 4];
data.read(&mut buf)?;
Ok(A {
address: Ipv4Addr::new(buf[0], buf[1], buf[2], buf[3]),
})
}
fn encode(&self, data: &mut MsgWriter) -> Result<(), EncodeError> {
data.write(&self.address.octets())
}
fn record_type() -> RecordType {
RecordType::A
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct AAAA {
pub address: Ipv6Addr,
}
impl Record for AAAA {
fn decode(data: &mut MsgReader) -> Result<Self, DecodeError> {
let mut buf = [0; 16];
data.read(&mut buf)?;
let segments: [u16; 8] = unsafe { transmute(buf) };
Ok(AAAA {
address: Ipv6Addr::new(
u16::from_be(segments[0]),
u16::from_be(segments[1]),
u16::from_be(segments[2]),
u16::from_be(segments[3]),
u16::from_be(segments[4]),
u16::from_be(segments[5]),
u16::from_be(segments[6]),
u16::from_be(segments[7]),
),
})
}
fn encode(&self, data: &mut MsgWriter) -> Result<(), EncodeError> {
let mut segments = self.address.segments();
for seg in &mut segments {
*seg = seg.to_be()
}
let buf: [u8; 16] = unsafe { transmute(segments) };
data.write(&buf)
}
fn record_type() -> RecordType {
RecordType::AAAA
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct CName {
pub name: String,
}
impl Record for CName {
fn decode(data: &mut MsgReader) -> Result<Self, DecodeError> {
Ok(CName {
name: data.read_name()?,
})
}
fn encode(&self, data: &mut MsgWriter) -> Result<(), EncodeError> {
data.write_name(&self.name)
}
fn record_type() -> RecordType {
RecordType::CName
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Mx {
pub preference: u16,
pub exchange: String,
}
impl Record for Mx {
fn decode(data: &mut MsgReader) -> Result<Self, DecodeError> {
Ok(Mx {
preference: data.read_u16()?,
exchange: data.read_name()?,
})
}
fn encode(&self, data: &mut MsgWriter) -> Result<(), EncodeError> {
data.write_u16(self.preference)?;
data.write_name(&self.exchange)
}
fn record_type() -> RecordType {
RecordType::Mx
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Ns {
pub name: String,
}
impl Record for Ns {
fn decode(data: &mut MsgReader) -> Result<Self, DecodeError> {
Ok(Ns {
name: data.read_name()?,
})
}
fn encode(&self, data: &mut MsgWriter) -> Result<(), EncodeError> {
data.write_name(&self.name)
}
fn record_type() -> RecordType {
RecordType::Ns
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Ptr {
pub name: String,
}
impl Record for Ptr {
fn decode(data: &mut MsgReader) -> Result<Self, DecodeError> {
Ok(Ptr {
name: data.read_name()?,
})
}
fn encode(&self, data: &mut MsgWriter) -> Result<(), EncodeError> {
data.write_name(&self.name)
}
fn record_type() -> RecordType {
RecordType::Ptr
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Soa {
pub mname: String,
pub rname: String,
pub serial: u32,
pub refresh: u32,
pub retry: u32,
pub expire: u32,
pub minimum: u32,
}
impl Record for Soa {
fn decode(data: &mut MsgReader) -> Result<Self, DecodeError> {
Ok(Soa {
mname: data.read_name()?,
rname: data.read_name()?,
serial: data.read_u32()?,
refresh: data.read_u32()?,
retry: data.read_u32()?,
expire: data.read_u32()?,
minimum: data.read_u32()?,
})
}
fn encode(&self, data: &mut MsgWriter) -> Result<(), EncodeError> {
data.write_name(&self.mname)?;
data.write_name(&self.rname)?;
data.write_u32(self.serial)?;
data.write_u32(self.refresh)?;
data.write_u32(self.retry)?;
data.write_u32(self.expire)?;
data.write_u32(self.minimum)?;
Ok(())
}
fn record_type() -> RecordType {
RecordType::Soa
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Srv {
pub priority: u16,
pub weight: u16,
pub port: u16,
pub target: String,
}
impl Record for Srv {
fn decode(data: &mut MsgReader) -> Result<Self, DecodeError> {
Ok(Srv {
priority: data.read_u16()?,
weight: data.read_u16()?,
port: data.read_u16()?,
target: data.read_name()?,
})
}
fn encode(&self, data: &mut MsgWriter) -> Result<(), EncodeError> {
data.write_u16(self.priority)?;
data.write_u16(self.weight)?;
data.write_u16(self.port)?;
data.write_name(&self.target)?;
Ok(())
}
fn record_type() -> RecordType {
RecordType::Srv
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Txt {
pub data: Vec<u8>,
}
impl Record for Txt {
fn decode(data: &mut MsgReader) -> Result<Self, DecodeError> {
Ok(Txt {
data: data.read_character_string()?,
})
}
fn encode(&self, data: &mut MsgWriter) -> Result<(), EncodeError> {
data.write_character_string(&self.data)
}
fn record_type() -> RecordType {
RecordType::Txt
}
}