2019-07-01 15:43:34 +00:00
|
|
|
use crate::common_types::binary::HEXLOWER_PERMISSIVE_ALLOW_WS;
|
2020-03-07 15:57:47 +00:00
|
|
|
use crate::common_types::*;
|
2019-07-01 15:43:34 +00:00
|
|
|
use crate::errors::*;
|
2020-03-07 15:57:47 +00:00
|
|
|
use crate::ser::packet::{remaining_bytes, DnsPacketWriteContext};
|
|
|
|
use crate::ser::text::{next_field, DnsTextContext, DnsTextFormatter};
|
2019-07-01 15:43:34 +00:00
|
|
|
use crate::ser::{RRData, RRDataPacket, RRDataText};
|
2020-03-07 15:57:47 +00:00
|
|
|
use bytes::{BufMut, Bytes};
|
|
|
|
use failure::{Fail, ResultExt};
|
2017-12-27 11:41:54 +00:00
|
|
|
use std::borrow::Cow;
|
2017-12-21 12:32:14 +00:00
|
|
|
use std::fmt;
|
2017-12-26 16:30:08 +00:00
|
|
|
use std::io::Cursor;
|
2017-12-21 12:32:14 +00:00
|
|
|
|
|
|
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
|
|
|
pub struct UnknownRecord {
|
|
|
|
rr_type: Type,
|
|
|
|
raw: Bytes,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl UnknownRecord {
|
|
|
|
pub fn new(rr_type: Type, raw: Bytes) -> Self {
|
|
|
|
UnknownRecord {
|
|
|
|
rr_type: rr_type,
|
|
|
|
raw: raw,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-29 21:25:43 +00:00
|
|
|
pub fn raw(&self) -> &Bytes {
|
|
|
|
&self.raw
|
|
|
|
}
|
|
|
|
|
2017-12-21 12:32:14 +00:00
|
|
|
pub fn deserialize(rr_type: Type, data: &mut ::std::io::Cursor<Bytes>) -> Result<Self> {
|
|
|
|
Ok(UnknownRecord::new(rr_type, remaining_bytes(data)))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn dns_parse(rr_type: Type, data: &mut &str) -> Result<Self> {
|
|
|
|
let field = next_field(data)?;
|
2019-07-01 15:43:34 +00:00
|
|
|
failure::ensure!(field == r"\#", "expect \\# token to mark generic encoding");
|
2017-12-21 12:32:14 +00:00
|
|
|
let field = next_field(data).context("generic record data length")?;
|
|
|
|
let len: usize = field.parse()?;
|
|
|
|
|
2020-03-07 15:57:47 +00:00
|
|
|
let result = HEXLOWER_PERMISSIVE_ALLOW_WS
|
|
|
|
.decode(data.as_bytes())
|
2017-12-21 12:32:14 +00:00
|
|
|
.with_context(|e| e.context(format!("invalid hex: {:?}", data)))?;
|
2020-03-07 15:57:47 +00:00
|
|
|
failure::ensure!(
|
|
|
|
len == result.len(),
|
|
|
|
"length {} doesn't match length of encoded data {}",
|
|
|
|
len,
|
|
|
|
result.len()
|
|
|
|
);
|
2017-12-27 11:41:54 +00:00
|
|
|
*data = ""; // read all data
|
2017-12-21 12:32:14 +00:00
|
|
|
|
|
|
|
Ok(UnknownRecord {
|
|
|
|
rr_type,
|
|
|
|
raw: result.into(),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2017-12-26 16:30:08 +00:00
|
|
|
|
|
|
|
impl RRDataPacket for UnknownRecord {
|
2020-03-07 15:57:47 +00:00
|
|
|
fn deserialize_rr_data(
|
|
|
|
_ttl: u32,
|
|
|
|
_rr_class: Class,
|
|
|
|
rr_type: Type,
|
|
|
|
data: &mut Cursor<Bytes>,
|
|
|
|
) -> Result<Self> {
|
2017-12-26 16:30:08 +00:00
|
|
|
UnknownRecord::deserialize(rr_type, data)
|
|
|
|
}
|
2017-12-26 21:23:47 +00:00
|
|
|
|
|
|
|
fn rr_type(&self) -> Type {
|
|
|
|
self.rr_type
|
|
|
|
}
|
2017-12-27 14:24:11 +00:00
|
|
|
|
2020-03-07 15:57:47 +00:00
|
|
|
fn serialize_rr_data(
|
|
|
|
&self,
|
|
|
|
_context: &mut DnsPacketWriteContext,
|
|
|
|
packet: &mut Vec<u8>,
|
|
|
|
) -> Result<()> {
|
2017-12-27 14:24:11 +00:00
|
|
|
packet.reserve(self.raw.len());
|
|
|
|
packet.put_slice(&self.raw);
|
|
|
|
Ok(())
|
|
|
|
}
|
2017-12-26 16:30:08 +00:00
|
|
|
}
|
2017-12-27 11:41:54 +00:00
|
|
|
|
|
|
|
impl RRDataText for UnknownRecord {
|
|
|
|
fn dns_parse_rr_data(context: &DnsTextContext, data: &mut &str) -> Result<Self>
|
|
|
|
where
|
|
|
|
Self: Sized,
|
|
|
|
{
|
|
|
|
let t = match context.record_type() {
|
|
|
|
Some(t) => t,
|
2019-07-01 15:43:34 +00:00
|
|
|
None => failure::bail!("must parse DNS record with record type context"),
|
2017-12-27 11:41:54 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
UnknownRecord::dns_parse(t, data)
|
|
|
|
}
|
|
|
|
|
2017-12-27 14:24:11 +00:00
|
|
|
/// this must never fail unless the underlying buffer fails.
|
2017-12-27 11:41:54 +00:00
|
|
|
fn dns_format_rr_data(&self, f: &mut DnsTextFormatter) -> fmt::Result {
|
2020-03-07 15:57:47 +00:00
|
|
|
write!(
|
|
|
|
f,
|
|
|
|
"\\# {} {}",
|
|
|
|
self.raw.len(),
|
|
|
|
HEXLOWER_PERMISSIVE_ALLOW_WS.encode(&self.raw)
|
|
|
|
)
|
2017-12-27 11:41:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn rr_type_txt(&self) -> Cow<'static, str> {
|
|
|
|
Cow::Owned(self.rr_type.generic_name())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl RRData for UnknownRecord {
|
2019-09-08 13:34:28 +00:00
|
|
|
fn clone_box(&self) -> Box<dyn RRData> {
|
2017-12-27 17:38:02 +00:00
|
|
|
Box::new(self.clone()) as _
|
|
|
|
}
|
2017-12-29 21:25:43 +00:00
|
|
|
|
2019-09-08 13:34:28 +00:00
|
|
|
fn as_any(&self) -> &dyn ::std::any::Any {
|
2017-12-29 21:25:43 +00:00
|
|
|
self as _
|
|
|
|
}
|
2017-12-27 11:41:54 +00:00
|
|
|
}
|