fix nameserver's A record & add some docs

This commit is contained in:
Jorge Aparicio 2024-02-05 19:51:02 +01:00
parent d13186e404
commit fc7cf970a5
3 changed files with 40 additions and 26 deletions

View File

@ -2,13 +2,13 @@ use std::net::Ipv4Addr;
use std::process::Child; use std::process::Child;
use crate::container::Container; use crate::container::Container;
use crate::record::{self, Referral, SoaSettings, Zone}; use crate::record::{self, Referral, SoaSettings, ZoneFile};
use crate::{Domain, Result, CHMOD_RW_EVERYONE}; use crate::{Domain, Result, CHMOD_RW_EVERYONE};
pub struct AuthoritativeNameServer<'a> { pub struct AuthoritativeNameServer<'a> {
child: Child, child: Child,
container: Container, container: Container,
zone: Zone<'a>, zone_file: ZoneFile<'a>,
} }
impl<'a> AuthoritativeNameServer<'a> { impl<'a> AuthoritativeNameServer<'a> {
@ -24,6 +24,7 @@ impl<'a> AuthoritativeNameServer<'a> {
}) })
} }
/// This is short-hand for `Self::reserve().start(/* .. */)`
pub fn start( pub fn start(
domain: Domain<'a>, domain: Domain<'a>,
referrals: &[Referral<'a>], referrals: &[Referral<'a>],
@ -37,11 +38,11 @@ impl<'a> AuthoritativeNameServer<'a> {
} }
pub fn nameserver(&self) -> &Domain<'a> { pub fn nameserver(&self) -> &Domain<'a> {
&self.zone.soa.ns &self.zone_file.soa.ns
} }
pub fn zone(&self) -> &Zone<'a> { pub fn zone_file(&self) -> &ZoneFile<'a> {
&self.zone &self.zone_file
} }
} }
@ -74,9 +75,22 @@ impl StoppedAuthoritativeNameServer {
&self.nameserver &self.nameserver
} }
/// Starts a primary name server that has authority over the given `zone`
///
/// The domain of the name server will have the form `primary{count}.nameservers.com.` where
/// `{count}` is a unique, monotonically increasing integer
///
/// The zone will contain these records
///
/// - one SOA record, with the primary name server set to the name server domain
/// - one NS record, with the name server domain set as the only available name server for
/// `zone`
/// - one A record, that maps the name server domain to its IPv4 address
/// - one NS + A record pair, for each referral in the `referrals` list
/// - the A records in the `a_records` list
pub fn start<'a>( pub fn start<'a>(
self, self,
domain: Domain<'a>, zone: Domain<'a>,
referrals: &[Referral<'a>], referrals: &[Referral<'a>],
a_records: &[record::A<'a>], a_records: &[record::A<'a>],
) -> Result<AuthoritativeNameServer<'a>> { ) -> Result<AuthoritativeNameServer<'a>> {
@ -90,42 +104,42 @@ impl StoppedAuthoritativeNameServer {
container.status_ok(&["mkdir", "-p", "/run/nsd/"])?; container.status_ok(&["mkdir", "-p", "/run/nsd/"])?;
container.status_ok(&["mkdir", "-p", "/etc/nsd/zones"])?; container.status_ok(&["mkdir", "-p", "/etc/nsd/zones"])?;
let zone_path = "/etc/nsd/zones/main.zone"; let zone_file_path = "/etc/nsd/zones/main.zone";
container.cp("/etc/nsd/nsd.conf", &nsd_conf(&domain), CHMOD_RW_EVERYONE)?; container.cp("/etc/nsd/nsd.conf", &nsd_conf(&zone), CHMOD_RW_EVERYONE)?;
let soa = record::Soa { let soa = record::Soa {
domain: domain.clone(), domain: zone.clone(),
ns: nameserver.clone(), ns: nameserver.clone(),
admin: admin_ns(ns_count), admin: admin_ns(ns_count),
settings: SoaSettings::default(), settings: SoaSettings::default(),
}; };
let mut zone = Zone::new(domain.clone(), soa); let mut zone_file = ZoneFile::new(zone.clone(), soa);
zone.record(record::Ns { zone_file.record(record::Ns {
domain: domain.clone(), domain: zone.clone(),
ns: nameserver, ns: nameserver.clone(),
}); });
zone.record(record::A { zone_file.record(record::A {
domain, domain: nameserver,
ipv4_addr: container.ipv4_addr(), ipv4_addr: container.ipv4_addr(),
}); });
for referral in referrals { for referral in referrals {
zone.referral(referral) zone_file.referral(referral)
} }
for a in a_records { for a in a_records {
zone.record(a.clone()) zone_file.record(a.clone())
} }
container.cp(zone_path, &zone.to_string(), CHMOD_RW_EVERYONE)?; container.cp(zone_file_path, &zone_file.to_string(), CHMOD_RW_EVERYONE)?;
let child = container.spawn(&["nsd", "-d"])?; let child = container.spawn(&["nsd", "-d"])?;
Ok(AuthoritativeNameServer { Ok(AuthoritativeNameServer {
child, child,
container, container,
zone, zone_file,
}) })
} }
} }

View File

@ -7,14 +7,14 @@ use std::net::Ipv4Addr;
use crate::Domain; use crate::Domain;
pub struct Zone<'a> { pub struct ZoneFile<'a> {
pub origin: Domain<'a>, pub origin: Domain<'a>,
pub ttl: u32, pub ttl: u32,
pub soa: Soa<'a>, pub soa: Soa<'a>,
pub records: Vec<Record<'a>>, pub records: Vec<Record<'a>>,
} }
impl<'a> Zone<'a> { impl<'a> ZoneFile<'a> {
/// Convenience constructor that uses "reasonable" defaults /// Convenience constructor that uses "reasonable" defaults
pub fn new(origin: Domain<'a>, soa: Soa<'a>) -> Self { pub fn new(origin: Domain<'a>, soa: Soa<'a>) -> Self {
Self { Self {
@ -49,7 +49,7 @@ impl<'a> Zone<'a> {
} }
} }
impl fmt::Display for Zone<'_> { 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,
@ -260,7 +260,7 @@ $TTL 1800
com. IN NS e.gtld-servers.net. com. IN NS e.gtld-servers.net.
e.gtld-servers.net. IN A 192.12.94.30 e.gtld-servers.net. IN A 192.12.94.30
"; ";
let mut zone = Zone::new(Domain::ROOT, example_soa()?); let mut zone = ZoneFile::new(Domain::ROOT, example_soa()?);
zone.record(example_ns()?); zone.record(example_ns()?);
zone.record(example_a()?); zone.record(example_a()?);

View File

@ -74,7 +74,7 @@ mod tests {
], ],
)?; )?;
eprintln!("nameservers.com.zone:\n{}", nameservers_ns.zone()); eprintln!("nameservers.com.zone:\n{}", nameservers_ns.zone_file());
let com_domain = Domain("com.")?; let com_domain = Domain("com.")?;
let com_ns = com_ns.start( let com_ns = com_ns.start(
@ -87,7 +87,7 @@ mod tests {
&[], &[],
)?; )?;
eprintln!("com.zone:\n{}", com_ns.zone()); eprintln!("com.zone:\n{}", com_ns.zone_file());
let root_ns = root_ns.start( let root_ns = root_ns.start(
Domain::ROOT, Domain::ROOT,
@ -99,7 +99,7 @@ mod tests {
&[], &[],
)?; )?;
eprintln!("root.zone:\n{}", root_ns.zone()); eprintln!("root.zone:\n{}", root_ns.zone_file());
let roots = &[Root::new(root_ns.nameserver().clone(), root_ns.ipv4_addr())]; let roots = &[Root::new(root_ns.nameserver().clone(), root_ns.ipv4_addr())];
let resolver = RecursiveResolver::start(roots)?; let resolver = RecursiveResolver::start(roots)?;