bind-conf/dns_zone/src/rtype.rs

110 lines
3.9 KiB
Rust

use crate::error::{Result, ErrorType};
use crate::name::Name;
use crate::context::CtxString;
use std::net;
#[derive(Debug, PartialEq, Hash, Eq)]
pub enum RType {
A {
target: net::Ipv4Addr,
},
Ns {
target: Name,
},
CName {
target: Name,
},
Soa {
mname: Name,
rname: Name,
serial: u32,
refresh: u32,
retry: u32,
expire: u32,
minimum: u32,
},
AAAA {
target: net::Ipv6Addr,
},
Unknown {
rtype: String,
origin: Name,
data: Vec<String>,
}
}
impl RType {
pub fn from_data(rtype: String, origin: &Name, data: Vec<CtxString>) -> Result<Self> {
Ok(match rtype.as_str() {
"A" | "TYPE1" => RType::A {
target: data.get(0).ok_or(ErrorType::BadParameter)?.parse().unwrap(),
},
"NS" | "TYPE2" => RType::Ns {
target: origin.prefixed_by(data.get(0).ok_or(ErrorType::BadParameter)?.parse()?),
},
"CNAME" | "TYPE5" => RType::CName {
target: origin.prefixed_by(data.get(0).ok_or(ErrorType::BadParameter)?.parse()?),
},
"SOA" | "TYPE6" => RType::Soa {
mname: origin.prefixed_by(data.get(0).ok_or(ErrorType::BadParameter)?.parse()?),
rname: origin.prefixed_by(data.get(1).ok_or(ErrorType::BadParameter)?.parse()?),
serial: data.get(2).ok_or(ErrorType::BadParameter)?.parse().unwrap(),
refresh: data.get(3).ok_or(ErrorType::BadParameter)?.parse().unwrap(),
retry: data.get(4).ok_or(ErrorType::BadParameter)?.parse().unwrap(),
expire: data.get(5).ok_or(ErrorType::BadParameter)?.parse().unwrap(),
minimum: data.get(6).ok_or(ErrorType::BadParameter)?.parse().unwrap(),
},
"AAAA" | "TYPE26" => RType::AAAA {
target: data.get(0).ok_or(ErrorType::BadParameter)?.parse().unwrap(),
},
_ => RType::Unknown {
rtype,
origin: origin.clone(),
data: data.iter().map(|ctx_string| (**ctx_string).to_string()).collect(),
}
})
// TODO: Check for trailing parameters
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn rtype_from_data() {
assert_eq!(
RType::A { target: "198.51.100.1".parse().unwrap() },
RType::from_data("A".into(), &".".parse().unwrap(), vec!["198.51.100.1".into()]).unwrap());
assert_eq!(
RType::Ns { target: "ns1.example.com.".parse().unwrap() },
RType::from_data("NS".into(), &"example.com.".parse().unwrap(), vec!["ns1".into()]).unwrap());
assert_eq!(
RType::Ns { target: "ns2.example.com.".parse().unwrap() },
RType::from_data("NS".into(), &"example.com.".parse().unwrap(), vec!["ns2.example.com.".into()]).unwrap());
assert_eq!(
RType::CName { target: "srv1.example.com.".parse().unwrap() },
RType::from_data("CNAME".into(), &"example.com.".parse().unwrap(), vec!["srv1".into()]).unwrap());
assert_eq!(
RType::AAAA { target: "2001:db8:cafe:bc68::2".parse().unwrap() },
RType::from_data("AAAA".into(), &".".parse().unwrap(), vec!["2001:db8:cafe:bc68::2".into()]).unwrap());
assert_eq!(
RType::Soa {
mname: "ns.example.com.".parse().unwrap(),
rname: "admin.example.com.".parse().unwrap(),
serial: 2020042901,
refresh: 28800,
retry: 7200,
expire: 2419200,
minimum: 300,
},
RType::from_data(
"SOA".into(), &"example.com.".parse().unwrap(),
vec!["ns.example.com.", "admin.example.com.", "2020042901",
"28800", "7200", "2419200", "300"].iter().map(|&s| s.into()).collect()).unwrap())
}
}