drop generic lifetime parameters from types

none of the parsing we are doing requires a non-static lifetime
This commit is contained in:
Jorge Aparicio 2024-02-16 15:53:40 +01:00
parent 795adc32c2
commit a83b6629a3
5 changed files with 76 additions and 81 deletions

View File

@ -29,7 +29,7 @@ impl Client {
&self, &self,
server: Ipv4Addr, server: Ipv4Addr,
record_type: RecordType, record_type: RecordType,
fqdn: &FQDN<'_>, fqdn: &FQDN,
trust_anchor: &TrustAnchor, trust_anchor: &TrustAnchor,
) -> Result<String> { ) -> Result<String> {
const TRUST_ANCHOR_PATH: &str = "/etc/bind.keys"; const TRUST_ANCHOR_PATH: &str = "/etc/bind.keys";
@ -57,7 +57,7 @@ impl Client {
dnssec: Dnssec, dnssec: Dnssec,
server: Ipv4Addr, server: Ipv4Addr,
record_type: RecordType, record_type: RecordType,
fqdn: &FQDN<'_>, fqdn: &FQDN,
) -> Result<DigOutput> { ) -> Result<DigOutput> {
let output = self.inner.stdout(&[ let output = self.inner.stdout(&[
"dig", "dig",

View File

@ -5,13 +5,13 @@ use std::borrow::Cow;
use crate::{Error, Result}; use crate::{Error, Result};
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq)]
pub struct FQDN<'a> { pub struct FQDN {
inner: Cow<'a, str>, inner: Cow<'static, str>,
} }
// TODO likely needs further validation // TODO likely needs further validation
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn FQDN<'a>(input: impl Into<Cow<'a, str>>) -> Result<FQDN<'a>> { pub fn FQDN(input: impl Into<Cow<'static, str>>) -> Result<FQDN> {
let input = input.into(); let input = input.into();
if !input.ends_with('.') { if !input.ends_with('.') {
return Err("FQDN must end with a `.`".into()); return Err("FQDN must end with a `.`".into());
@ -24,12 +24,12 @@ pub fn FQDN<'a>(input: impl Into<Cow<'a, str>>) -> Result<FQDN<'a>> {
Ok(FQDN { inner: input }) Ok(FQDN { inner: input })
} }
impl<'a> FQDN<'a> { impl FQDN {
pub const ROOT: FQDN<'static> = FQDN { pub const ROOT: FQDN = FQDN {
inner: Cow::Borrowed("."), inner: Cow::Borrowed("."),
}; };
pub const COM: FQDN<'static> = FQDN { pub const COM: FQDN = FQDN {
inner: Cow::Borrowed("com."), inner: Cow::Borrowed("com."),
}; };
@ -41,7 +41,7 @@ impl<'a> FQDN<'a> {
&self.inner &self.inner
} }
pub fn into_owned(self) -> FQDN<'static> { pub fn into_owned(self) -> FQDN {
let owned = match self.inner { let owned = match self.inner {
Cow::Borrowed(borrowed) => borrowed.to_string(), Cow::Borrowed(borrowed) => borrowed.to_string(),
Cow::Owned(owned) => owned, Cow::Owned(owned) => owned,
@ -53,21 +53,21 @@ impl<'a> FQDN<'a> {
} }
} }
impl FromStr for FQDN<'static> { impl FromStr for FQDN {
type Err = Error; type Err = Error;
fn from_str(input: &str) -> Result<Self> { fn from_str(input: &str) -> Result<Self> {
Ok(FQDN(input)?.into_owned()) FQDN(input.to_string())
} }
} }
impl fmt::Debug for FQDN<'_> { impl fmt::Debug for FQDN {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self, f) fmt::Display::fmt(self, f)
} }
} }
impl fmt::Display for FQDN<'_> { impl fmt::Display for FQDN {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.inner) f.write_str(&self.inner)
} }

View File

@ -6,13 +6,13 @@ use crate::tshark::Tshark;
use crate::zone_file::{self, SoaSettings, ZoneFile, DNSKEY, DS}; use crate::zone_file::{self, SoaSettings, ZoneFile, DNSKEY, DS};
use crate::{Implementation, Result, FQDN}; use crate::{Implementation, Result, FQDN};
pub struct NameServer<'a, State> { pub struct NameServer<State> {
container: Container, container: Container,
zone_file: ZoneFile<'a>, zone_file: ZoneFile,
state: State, state: State,
} }
impl<'a> NameServer<'a, Stopped> { impl NameServer<Stopped> {
/// Spins up a primary name server that has authority over the given `zone` /// Spins up a primary name server that has authority over the given `zone`
/// ///
/// The initial state of the server is the "Stopped" state where it won't answer any query. /// The initial state of the server is the "Stopped" state where it won't answer any query.
@ -25,7 +25,7 @@ impl<'a> NameServer<'a, Stopped> {
/// - one SOA record, with the primary name server field set to this name server's FQDN /// - one SOA record, with the primary name server field set to this name server's FQDN
/// - one NS record, with this name server's FQDN set as the only available name server for /// - one NS record, with this name server's FQDN set as the only available name server for
/// the zone /// the zone
pub fn new(implementation: Implementation, zone: FQDN<'a>, network: &Network) -> Result<Self> { pub fn new(implementation: Implementation, zone: FQDN, network: &Network) -> Result<Self> {
assert!( assert!(
matches!(implementation, Implementation::Unbound), matches!(implementation, Implementation::Unbound),
"currently only `unbound` (`nsd`) can be used as a `NameServer`" "currently only `unbound` (`nsd`) can be used as a `NameServer`"
@ -56,18 +56,13 @@ impl<'a> NameServer<'a, Stopped> {
} }
/// Adds a NS + A record pair to the zone file /// Adds a NS + A record pair to the zone file
pub fn referral( pub fn referral(&mut self, zone: FQDN, nameserver: FQDN, ipv4_addr: Ipv4Addr) -> &mut Self {
&mut self,
zone: FQDN<'a>,
nameserver: FQDN<'a>,
ipv4_addr: Ipv4Addr,
) -> &mut Self {
self.zone_file.referral(zone, nameserver, ipv4_addr); self.zone_file.referral(zone, nameserver, ipv4_addr);
self self
} }
/// Adds an A record pair to the zone file /// Adds an A record pair to the zone file
pub fn a(&mut self, fqdn: FQDN<'a>, ipv4_addr: Ipv4Addr) -> &mut Self { pub fn a(&mut self, fqdn: FQDN, ipv4_addr: Ipv4Addr) -> &mut Self {
self.zone_file.entry(zone_file::A { fqdn, ipv4_addr }); self.zone_file.entry(zone_file::A { fqdn, ipv4_addr });
self self
} }
@ -79,7 +74,7 @@ impl<'a> NameServer<'a, Stopped> {
} }
/// Freezes and signs the name server's zone file /// Freezes and signs the name server's zone file
pub fn sign(self) -> Result<NameServer<'a, Signed>> { pub fn sign(self) -> Result<NameServer<Signed>> {
// TODO do we want to make these settings configurable? // TODO do we want to make these settings configurable?
const ZSK_BITS: usize = 1024; const ZSK_BITS: usize = 1024;
const KSK_BITS: usize = 2048; const KSK_BITS: usize = 2048;
@ -139,7 +134,7 @@ impl<'a> NameServer<'a, Stopped> {
} }
/// Moves the server to the "Start" state where it can answer client queries /// Moves the server to the "Start" state where it can answer client queries
pub fn start(self) -> Result<NameServer<'a, Running>> { pub fn start(self) -> Result<NameServer<Running>> {
let Self { let Self {
container, container,
zone_file, zone_file,
@ -176,9 +171,9 @@ fn ns_count() -> usize {
COUNT.fetch_add(1, atomic::Ordering::Relaxed) COUNT.fetch_add(1, atomic::Ordering::Relaxed)
} }
impl<'a> NameServer<'a, Signed> { impl NameServer<Signed> {
/// Moves the server to the "Start" state where it can answer client queries /// Moves the server to the "Start" state where it can answer client queries
pub fn start(self) -> Result<NameServer<'a, Running>> { pub fn start(self) -> Result<NameServer<Running>> {
let Self { let Self {
container, container,
zone_file, zone_file,
@ -216,7 +211,7 @@ impl<'a> NameServer<'a, Signed> {
} }
} }
impl<'a> NameServer<'a, Running> { impl NameServer<Running> {
/// Starts a `tshark` instance that captures DNS messages flowing through this network node /// Starts a `tshark` instance that captures DNS messages flowing through this network node
pub fn eavesdrop(&self) -> Result<Tshark> { pub fn eavesdrop(&self) -> Result<Tshark> {
self.container.eavesdrop() self.container.eavesdrop()
@ -246,7 +241,7 @@ kill -TERM $(cat {pidfile})"
} }
} }
impl<'a, S> NameServer<'a, S> { impl<S> NameServer<S> {
pub fn container_id(&self) -> &str { pub fn container_id(&self) -> &str {
self.container.id() self.container.id()
} }
@ -256,15 +251,15 @@ impl<'a, S> NameServer<'a, S> {
} }
/// Zone file BEFORE signing /// Zone file BEFORE signing
pub fn zone_file(&self) -> &ZoneFile<'a> { pub fn zone_file(&self) -> &ZoneFile {
&self.zone_file &self.zone_file
} }
pub fn zone(&self) -> &FQDN<'a> { pub fn zone(&self) -> &FQDN {
&self.zone_file.origin &self.zone_file.origin
} }
pub fn fqdn(&self) -> &FQDN<'a> { pub fn fqdn(&self) -> &FQDN {
&self.zone_file.soa.nameserver &self.zone_file.soa.nameserver
} }
} }
@ -282,11 +277,11 @@ pub struct Running {
child: Child, child: Child,
} }
fn primary_ns(ns_count: usize) -> FQDN<'static> { fn primary_ns(ns_count: usize) -> FQDN {
FQDN(format!("primary{ns_count}.nameservers.com.")).unwrap() FQDN(format!("primary{ns_count}.nameservers.com.")).unwrap()
} }
fn admin_ns(ns_count: usize) -> FQDN<'static> { fn admin_ns(ns_count: usize) -> FQDN {
FQDN(format!("admin{ns_count}.nameservers.com.")).unwrap() FQDN(format!("admin{ns_count}.nameservers.com.")).unwrap()
} }

View File

@ -93,7 +93,7 @@ impl FromStr for Record {
#[derive(Debug)] #[derive(Debug)]
pub struct A { pub struct A {
pub fqdn: FQDN<'static>, pub fqdn: FQDN,
pub ttl: u32, pub ttl: u32,
pub ipv4_addr: Ipv4Addr, pub ipv4_addr: Ipv4Addr,
} }
@ -132,7 +132,7 @@ impl FromStr for A {
#[allow(clippy::upper_case_acronyms)] #[allow(clippy::upper_case_acronyms)]
#[derive(Debug)] #[derive(Debug)]
pub struct RRSIG { pub struct RRSIG {
pub fqdn: FQDN<'static>, pub fqdn: FQDN,
pub ttl: u32, pub ttl: u32,
pub type_covered: RecordType, pub type_covered: RecordType,
pub algorithm: u32, pub algorithm: u32,
@ -141,7 +141,7 @@ pub struct RRSIG {
pub signature_expiration: u64, pub signature_expiration: u64,
pub signature_inception: u64, pub signature_inception: u64,
pub key_tag: u32, pub key_tag: u32,
pub signer_name: FQDN<'static>, pub signer_name: FQDN,
/// base64 encoded /// base64 encoded
pub signature: String, pub signature: String,
} }
@ -193,10 +193,10 @@ impl FromStr for RRSIG {
#[allow(clippy::upper_case_acronyms)] #[allow(clippy::upper_case_acronyms)]
#[derive(Debug)] #[derive(Debug)]
pub struct SOA { pub struct SOA {
pub zone: FQDN<'static>, pub zone: FQDN,
pub ttl: u32, pub ttl: u32,
pub nameserver: FQDN<'static>, pub nameserver: FQDN,
pub admin: FQDN<'static>, pub admin: FQDN,
pub serial: u32, pub serial: u32,
pub refresh: u32, pub refresh: u32,
pub retry: u32, pub retry: u32,

View File

@ -10,16 +10,16 @@ use std::str::FromStr;
use crate::{Error, FQDN}; use crate::{Error, FQDN};
pub struct ZoneFile<'a> { pub struct ZoneFile {
pub origin: FQDN<'a>, pub origin: FQDN,
pub ttl: u32, pub ttl: u32,
pub soa: SOA<'a>, pub soa: SOA,
pub entries: Vec<Entry<'a>>, pub entries: Vec<Entry>,
} }
impl<'a> ZoneFile<'a> { impl ZoneFile {
/// Convenience constructor that uses "reasonable" defaults /// Convenience constructor that uses "reasonable" defaults
pub fn new(origin: FQDN<'a>, soa: SOA<'a>) -> Self { pub fn new(origin: FQDN, soa: SOA) -> Self {
Self { Self {
origin, origin,
ttl: 1800, ttl: 1800,
@ -29,12 +29,12 @@ impl<'a> ZoneFile<'a> {
} }
/// Appends an entry /// Appends an entry
pub fn entry(&mut self, entry: impl Into<Entry<'a>>) { pub fn entry(&mut self, entry: impl Into<Entry>) {
self.entries.push(entry.into()) self.entries.push(entry.into())
} }
/// Appends a NS + A entry pair /// Appends a NS + A entry pair
pub fn referral(&mut self, zone: FQDN<'a>, nameserver: FQDN<'a>, ipv4_addr: Ipv4Addr) { pub fn referral(&mut self, zone: FQDN, nameserver: FQDN, ipv4_addr: Ipv4Addr) {
self.entry(NS { self.entry(NS {
zone: zone.clone(), zone: zone.clone(),
nameserver: nameserver.clone(), nameserver: nameserver.clone(),
@ -46,7 +46,7 @@ impl<'a> ZoneFile<'a> {
} }
} }
impl fmt::Display for ZoneFile<'_> { impl fmt::Display for ZoneFile {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self { let Self {
origin, origin,
@ -67,15 +67,15 @@ impl fmt::Display for ZoneFile<'_> {
} }
} }
pub struct Root<'a> { pub struct Root {
pub ipv4_addr: Ipv4Addr, pub ipv4_addr: Ipv4Addr,
pub ns: FQDN<'a>, pub ns: FQDN,
pub ttl: u32, pub ttl: u32,
} }
impl<'a> Root<'a> { impl Root {
/// Convenience constructor that uses "reasonable" defaults /// Convenience constructor that uses "reasonable" defaults
pub fn new(ns: FQDN<'a>, ipv4_addr: Ipv4Addr) -> Self { pub fn new(ns: FQDN, ipv4_addr: Ipv4Addr) -> Self {
Self { Self {
ipv4_addr, ipv4_addr,
ns, ns,
@ -84,7 +84,7 @@ impl<'a> Root<'a> {
} }
} }
impl fmt::Display for Root<'_> { impl fmt::Display for Root {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self { ipv4_addr, ns, ttl } = self; let Self { ipv4_addr, ns, ttl } = self;
@ -93,32 +93,32 @@ impl fmt::Display for Root<'_> {
} }
} }
pub enum Entry<'a> { pub enum Entry {
A(A<'a>), A(A),
DNSKEY(DNSKEY), DNSKEY(DNSKEY),
DS(DS), DS(DS),
NS(NS<'a>), NS(NS),
} }
impl<'a> From<DS> for Entry<'a> { impl From<DS> for Entry {
fn from(v: DS) -> Self { fn from(v: DS) -> Self {
Self::DS(v) Self::DS(v)
} }
} }
impl<'a> From<A<'a>> for Entry<'a> { impl From<A> for Entry {
fn from(v: A<'a>) -> Self { fn from(v: A) -> Self {
Self::A(v) Self::A(v)
} }
} }
impl<'a> From<NS<'a>> for Entry<'a> { impl From<NS> for Entry {
fn from(v: NS<'a>) -> Self { fn from(v: NS) -> Self {
Self::NS(v) Self::NS(v)
} }
} }
impl fmt::Display for Entry<'_> { impl fmt::Display for Entry {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
Entry::A(a) => a.fmt(f), Entry::A(a) => a.fmt(f),
@ -130,12 +130,12 @@ impl fmt::Display for Entry<'_> {
} }
#[derive(Clone)] #[derive(Clone)]
pub struct A<'a> { pub struct A {
pub fqdn: FQDN<'a>, pub fqdn: FQDN,
pub ipv4_addr: Ipv4Addr, pub ipv4_addr: Ipv4Addr,
} }
impl fmt::Display for A<'_> { impl fmt::Display for A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self { fqdn, ipv4_addr } = self; let Self { fqdn, ipv4_addr } = self;
@ -146,7 +146,7 @@ impl fmt::Display for A<'_> {
// integer types chosen based on bit sizes in section 2.1 of RFC4034 // integer types chosen based on bit sizes in section 2.1 of RFC4034
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct DNSKEY { pub struct DNSKEY {
zone: FQDN<'static>, zone: FQDN,
flags: u16, flags: u16,
protocol: u8, protocol: u8,
algorithm: u8, algorithm: u8,
@ -256,7 +256,7 @@ impl fmt::Display for DNSKEY {
#[derive(Clone)] #[derive(Clone)]
pub struct DS { pub struct DS {
zone: FQDN<'static>, zone: FQDN,
_ttl: u32, _ttl: u32,
key_tag: u16, key_tag: u16,
algorithm: u8, algorithm: u8,
@ -317,12 +317,12 @@ impl fmt::Display for DS {
} }
} }
pub struct NS<'a> { pub struct NS {
pub zone: FQDN<'a>, pub zone: FQDN,
pub nameserver: FQDN<'a>, pub nameserver: FQDN,
} }
impl fmt::Display for NS<'_> { impl fmt::Display for NS {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self { let Self {
zone, zone,
@ -333,14 +333,14 @@ impl fmt::Display for NS<'_> {
} }
} }
pub struct SOA<'a> { pub struct SOA {
pub zone: FQDN<'a>, pub zone: FQDN,
pub nameserver: FQDN<'a>, pub nameserver: FQDN,
pub admin: FQDN<'a>, pub admin: FQDN,
pub settings: SoaSettings, pub settings: SoaSettings,
} }
impl fmt::Display for SOA<'_> { impl fmt::Display for SOA {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self { let Self {
zone, zone,
@ -482,21 +482,21 @@ e.gtld-servers.net. IN A 192.12.94.30
Ok(()) Ok(())
} }
fn example_a() -> Result<A<'static>> { fn example_a() -> Result<A> {
Ok(A { Ok(A {
fqdn: FQDN("e.gtld-servers.net.")?, fqdn: FQDN("e.gtld-servers.net.")?,
ipv4_addr: Ipv4Addr::new(192, 12, 94, 30), ipv4_addr: Ipv4Addr::new(192, 12, 94, 30),
}) })
} }
fn example_ns() -> Result<NS<'static>> { fn example_ns() -> Result<NS> {
Ok(NS { Ok(NS {
zone: FQDN::COM, zone: FQDN::COM,
nameserver: FQDN("e.gtld-servers.net.")?, nameserver: FQDN("e.gtld-servers.net.")?,
}) })
} }
fn example_soa() -> Result<SOA<'static>> { fn example_soa() -> Result<SOA> {
Ok(SOA { Ok(SOA {
zone: FQDN::ROOT, zone: FQDN::ROOT,
nameserver: FQDN("a.root-servers.net.")?, nameserver: FQDN("a.root-servers.net.")?,