rust-dnsbox/lib/dnsbox-base/src/records/weird_structs.rs

313 lines
8.4 KiB
Rust
Raw Normal View History

2017-12-27 14:24:11 +00:00
use bytes::{Bytes, Buf, BufMut};
use errors::*;
2017-12-21 12:32:14 +00:00
use common_types::*;
use failure::ResultExt;
2017-12-27 20:50:51 +00:00
use ser::packet::{DnsPacketData, DnsPacketWriteContext, remaining_bytes};
2017-12-26 21:23:51 +00:00
use ser::text::{DnsTextData, DnsTextFormatter, DnsTextContext};
2017-12-21 12:32:14 +00:00
use std::fmt;
use std::io::Read;
2017-12-27 20:50:51 +00:00
use std::net::{Ipv4Addr, Ipv6Addr};
2017-12-21 12:32:14 +00:00
// deriving RRData will add a unit test to make sure the type is
// registered; there must be a records::types::$name `Type` constant
// with the same name as the struct.
#[derive(Clone, PartialEq, Eq, Debug, RRData)]
2017-12-26 16:30:08 +00:00
#[RRClass(ANY)]
2017-12-21 12:32:14 +00:00
pub enum LOC {
Version0(LOC0),
UnknownVersion{
version: u8,
data: Bytes,
},
}
impl DnsPacketData for LOC {
2017-12-27 14:24:11 +00:00
fn deserialize(data: &mut ::std::io::Cursor<Bytes>) -> Result<Self> {
2017-12-21 12:32:14 +00:00
let version: u8 = DnsPacketData::deserialize(data)?;
if 0 == version {
Ok(LOC::Version0(DnsPacketData::deserialize(data)?))
} else {
Ok(LOC::UnknownVersion{
version: version,
2017-12-27 20:50:51 +00:00
data: remaining_bytes(data),
2017-12-21 12:32:14 +00:00
})
}
}
2017-12-27 14:24:11 +00:00
fn serialize(&self, context: &mut DnsPacketWriteContext, packet: &mut Vec<u8>) -> Result<()> {
match *self {
LOC::Version0(ref l0) => {
packet.reserve(1);
packet.put_u8(0);
l0.serialize(context, packet)
},
LOC::UnknownVersion{version, ref data} => {
packet.reserve(data.len() + 1);
packet.put_u8(version);
packet.put_slice(data);
Ok(())
},
}
}
2017-12-21 12:32:14 +00:00
}
impl DnsTextData for LOC {
2017-12-27 14:24:11 +00:00
fn dns_parse(_context: &DnsTextContext, _data: &mut &str) -> Result<Self> {
2017-12-21 12:32:14 +00:00
unimplemented!()
}
fn dns_format(&self, _f: &mut DnsTextFormatter) -> fmt::Result {
// always prefer binary representation
Err(fmt::Error)
}
}
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData)]
pub struct LOC0 {
size: u8,
horizontal_precision: u8,
vertical_precision: u8,
latitude: u32,
longitude: u32,
altitude: u32,
}
#[derive(Clone, PartialEq, Eq, Debug, RRData)]
2017-12-26 16:30:08 +00:00
#[RRClass(IN)]
2017-12-21 12:32:14 +00:00
pub struct A6 {
prefix: u8, // [0...128]
// might include non-zero padding
dirty_suffix: Ipv6Addr,
suffix: Ipv6Addr,
prefix_name: Option<DnsCanonicalName>,
}
impl DnsPacketData for A6 {
2017-12-27 14:24:11 +00:00
fn deserialize(data: &mut ::std::io::Cursor<Bytes>) -> Result<Self> {
2017-12-21 12:32:14 +00:00
let prefix: u8 = DnsPacketData::deserialize(data)
.context("failed parsing field A6::prefix")?;
ensure!(prefix <= 128, "invalid A6::prefix {}", prefix);
let suffix_offset = (prefix / 8) as usize;
debug_assert!(suffix_offset <= 16);
let suffix_len = 16 - suffix_offset;
check_enough_data!(data, suffix_len, "A6::suffix");
let mut addr = [0u8; 16];
data.read_exact(&mut addr[suffix_offset..16])?;
let dirty_suffix = Ipv6Addr::from(addr);
if suffix_offset < 16 {
let mask = 0xff >> (prefix % 8);
addr[suffix_offset] &= mask;
}
let suffix = Ipv6Addr::from(addr);
let prefix_name = if data.has_remaining() {
Some(DnsPacketData::deserialize(data)?)
} else {
None
};
Ok(A6 {
prefix,
dirty_suffix,
suffix,
prefix_name,
})
}
2017-12-27 14:24:11 +00:00
fn serialize(&self, context: &mut DnsPacketWriteContext, packet: &mut Vec<u8>) -> Result<()> {
let suffix_offset = (self.prefix / 8) as usize;
debug_assert!(suffix_offset <= 16);
let suffix = self.dirty_suffix.octets();
let suffix_data = &suffix[suffix_offset..];
packet.reserve(1 /* prefix */ + suffix_data.len());
packet.put_u8(self.prefix);
packet.put_slice(suffix_data);
if let Some(ref n) = self.prefix_name {
n.serialize(context, packet)?;
}
Ok(())
}
2017-12-21 12:32:14 +00:00
}
impl DnsTextData for A6 {
2017-12-27 14:24:11 +00:00
fn dns_parse(context: &DnsTextContext, data: &mut &str) -> Result<Self> {
2017-12-26 21:23:51 +00:00
let prefix: u8 = DnsTextData::dns_parse(context, data)
2017-12-21 12:32:14 +00:00
.context("failed parsing field A6::prefix")?;
ensure!(prefix <= 128, "invalid A6::prefix {}", prefix);
let suffix_offset = (prefix / 8) as usize;
debug_assert!(suffix_offset <= 16);
2017-12-26 21:23:51 +00:00
let suffix: Ipv6Addr = DnsTextData::dns_parse(context, data)
2017-12-21 12:32:14 +00:00
.context("failed parsing field A6::suffix")?;
// clear prefix bits
let mut suffix = suffix.octets();
for i in 0..suffix_offset {
suffix[i] = 0;
}
if suffix_offset < 16 {
let mask = 0xff >> (prefix % 8);
suffix[suffix_offset] &= mask;
}
let suffix = Ipv6Addr::from(suffix);
let prefix_name = if !data.is_empty() {
2017-12-26 21:23:51 +00:00
Some(DnsTextData::dns_parse(context, data)
2017-12-21 12:32:14 +00:00
.context("failed parsing field A6::prefix_name")?)
} else {
None
};
Ok(A6 {
prefix,
dirty_suffix: suffix.clone(),
suffix,
prefix_name,
})
}
fn dns_format(&self, f: &mut DnsTextFormatter) -> fmt::Result {
if self.dirty_suffix != self.suffix {
// parsing text clears the padding, so we would loose data.
// use binary representation instead.
return Err(fmt::Error);
}
write!(f, "{} {}", self.prefix, self.suffix)?;
if let Some(ref prefix_name) = self.prefix_name {
write!(f, "{}", prefix_name)?;
}
Ok(())
}
}
2017-12-27 20:50:51 +00:00
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum IpsecKeyGateway {
None,
Ipv4(Ipv4Addr),
Ipv6(Ipv6Addr),
Name(DnsName),
}
#[derive(Clone, PartialEq, Eq, Debug, RRData)]
#[RRClass(ANY)]
pub enum IPSECKEY {
Known{
precedence: u8,
algorithm: u8,
gateway: IpsecKeyGateway,
public_key: Base64RemainingBlob,
},
UnknownGateway{
precedence: u8,
gateway_type: u8,
algorithm: u8,
// length of gateway is unknown, can't split gateway and public key
remaining: Bytes,
}
}
impl DnsPacketData for IPSECKEY {
fn deserialize(data: &mut ::std::io::Cursor<Bytes>) -> Result<Self> {
let precedence = u8::deserialize(data)?;
let gateway_type = u8::deserialize(data)?;
let algorithm = u8::deserialize(data)?;
let gateway = match gateway_type {
0 => IpsecKeyGateway::None,
1 => IpsecKeyGateway::Ipv4(Ipv4Addr::deserialize(data)?),
2 => IpsecKeyGateway::Ipv6(Ipv6Addr::deserialize(data)?),
3 => IpsecKeyGateway::Name(DnsName::deserialize(data)?),
_ => return Ok(IPSECKEY::UnknownGateway{
precedence,
gateway_type,
algorithm,
remaining: remaining_bytes(data),
}),
};
Ok(IPSECKEY::Known{
precedence,
algorithm,
gateway,
public_key: Base64RemainingBlob::deserialize(data)?,
})
}
fn serialize(&self, context: &mut DnsPacketWriteContext, packet: &mut Vec<u8>) -> Result<()> {
match *self {
IPSECKEY::Known{precedence, algorithm, ref gateway, ref public_key} => {
packet.reserve(3);
packet.put_u8(precedence);
let gateway_type: u8 = match *gateway {
IpsecKeyGateway::None => 0,
IpsecKeyGateway::Ipv4(_) => 1,
IpsecKeyGateway::Ipv6(_) => 2,
IpsecKeyGateway::Name(_) => 3,
};
packet.put_u8(gateway_type);
packet.put_u8(algorithm);
match *gateway {
IpsecKeyGateway::None => (),
IpsecKeyGateway::Ipv4(ref a) => a.serialize(context, packet)?,
IpsecKeyGateway::Ipv6(ref a) => a.serialize(context, packet)?,
IpsecKeyGateway::Name(ref n) => n.serialize(context, packet)?,
};
public_key.serialize(context, packet)?;
},
IPSECKEY::UnknownGateway{precedence, gateway_type, algorithm, ref remaining} => {
packet.reserve(3 + remaining.len());
packet.put_u8(precedence);
packet.put_u8(gateway_type);
packet.put_u8(algorithm);
packet.put_slice(remaining);
}
}
Ok(())
}
}
impl DnsTextData for IPSECKEY {
fn dns_parse(context: &DnsTextContext, data: &mut &str) -> Result<Self> {
let precedence = u8::dns_parse(context, data)?;
let gateway_type = u8::dns_parse(context, data)?;
let algorithm = u8::dns_parse(context, data)?;
let gateway = match gateway_type {
0 => IpsecKeyGateway::None,
1 => IpsecKeyGateway::Ipv4(Ipv4Addr::dns_parse(context, data)?),
2 => IpsecKeyGateway::Ipv6(Ipv6Addr::dns_parse(context, data)?),
3 => IpsecKeyGateway::Name(DnsName::dns_parse(context, data)?),
_ => bail!("unknown gateway type {} for IPSECKEY", gateway_type),
};
Ok(IPSECKEY::Known{
precedence,
algorithm,
gateway,
public_key: Base64RemainingBlob::dns_parse(context, data)?,
})
}
fn dns_format(&self, f: &mut DnsTextFormatter) -> fmt::Result {
match *self {
IPSECKEY::Known{precedence, algorithm, ref gateway, ref public_key} => {
let gateway_type: u8 = match *gateway {
IpsecKeyGateway::None => 0,
IpsecKeyGateway::Ipv4(_) => 1,
IpsecKeyGateway::Ipv6(_) => 2,
IpsecKeyGateway::Name(_) => 3,
};
write!(f, "{} {} {}", precedence, gateway_type, algorithm)?;
match *gateway {
IpsecKeyGateway::None => (),
IpsecKeyGateway::Ipv4(ref a) => a.dns_format(f)?,
IpsecKeyGateway::Ipv6(ref a) => a.dns_format(f)?,
IpsecKeyGateway::Name(ref n) => n.dns_format(f)?,
};
public_key.dns_format(f)?;
Ok(())
},
IPSECKEY::UnknownGateway{..} => Err(fmt::Error),
}
}
}