Skip to main content

Mist/
Zone.rs

1//! # DNS Zone
2//!
3//! Provides DNS zone configuration for the CodeEditorLand private network.
4//! Creates an authoritative zone for `land.playform.cloud` that resolves to
5//! loopback addresses.
6
7use anyhow::Result;
8use hickory_proto::rr::{
9	Name,
10	RData,
11	Record,
12	rdata::{A, NS, SOA},
13};
14// hickory-server 0.26: see the block comment in `Server.rs` for the full
15// rename table (`authority::*` → `zone_handler::*`, `InMemoryAuthority` →
16// `InMemoryZoneHandler`, AXFR bool → `AxfrPolicy`). The handler became
17// generic over `P: RuntimeProvider`; we pin it to `TokioRuntimeProvider` so
18// return types are concrete and callers don't have to thread the parameter.
19use hickory_server::{
20	net::runtime::TokioRuntimeProvider,
21	store::in_memory::InMemoryZoneHandler,
22	zone_handler::{AxfrPolicy, ZoneType},
23};
24
25/// Creates the `land.playform.cloud` authoritative zone records.
26///
27/// All `*.land.playform.cloud` domains resolve to `127.x.x.x` (loopback).
28pub fn EditorLandZone() -> Result<Vec<Record>> {
29	let mut Records = Vec::new();
30
31	let Origin = Name::from_ascii("land.playform.cloud.").unwrap();
32
33	let TTL = 300u32;
34
35	let Serial = 2025010100u32;
36
37	let Refresh:i32 = 86400;
38
39	let Retry:i32 = 7200;
40
41	let Expire:i32 = 604800;
42
43	let Minimum:u32 = 3600;
44
45	let SOARecord = SOA::new(
46		Name::from_ascii("ns1.land.playform.cloud.").unwrap(),
47		Name::from_ascii("hostmaster.land.playform.cloud.").unwrap(),
48		Serial,
49		Refresh,
50		Retry,
51		Expire,
52		Minimum,
53	);
54
55	Records.push(Record::from_rdata(Origin.clone(), TTL, RData::SOA(SOARecord)));
56
57	let NSName = Name::from_ascii("ns1.land.playform.cloud.").unwrap();
58
59	Records.push(Record::from_rdata(Origin.clone(), TTL, RData::NS(NS(NSName))));
60
61	Records.push(Record::from_rdata(
62		Name::from_ascii("ns1.land.playform.cloud.").unwrap(),
63		TTL,
64		RData::A(A::new(127, 0, 0, 1)),
65	));
66
67	let Subdomains = vec!["editor", "www", "localhost", "sidecar", "cocoon"];
68
69	for (Index, Subdomain) in Subdomains.iter().enumerate() {
70		let SubdomainName = Name::from_ascii(format!("{}.land.playform.cloud.", Subdomain)).unwrap();
71
72		let IP = A::new(127, 0, (Index / 255) as u8, (Index % 255) as u8);
73
74		Records.push(Record::from_rdata(SubdomainName, TTL, RData::A(IP)));
75	}
76
77	Records.push(Record::from_rdata(Origin, TTL, RData::A(A::new(127, 0, 0, 1))));
78
79	Ok(Records)
80}
81
82/// Creates an `InMemoryZoneHandler` for the `land.playform.cloud` zone.
83pub fn EditorLandAuthority() -> Result<InMemoryZoneHandler<TokioRuntimeProvider>> {
84	let Origin = Name::from_ascii("land.playform.cloud.").unwrap();
85
86	let Authority =
87		InMemoryZoneHandler::<TokioRuntimeProvider>::empty(Origin, ZoneType::Primary, AxfrPolicy::Deny, None);
88
89	let _Records = EditorLandZone()?;
90
91	Ok(Authority)
92}
93
94/// Creates an `InMemoryZoneHandler` for a custom origin with specified records.
95pub fn CustomAuthority(Origin:&Name, _Records:Vec<Record>) -> Result<InMemoryZoneHandler<TokioRuntimeProvider>> {
96	let Authority =
97		InMemoryZoneHandler::<TokioRuntimeProvider>::empty(Origin.clone(), ZoneType::Primary, AxfrPolicy::Deny, None);
98
99	Ok(Authority)
100}
101
102#[cfg(test)]
103mod tests {
104
105	use hickory_server::zone_handler::ZoneHandler;
106
107	use super::*;
108
109	#[test]
110	fn TestZoneCreation() {
111		let Zone = EditorLandZone().expect("Failed to create zone");
112
113		assert!(!Zone.is_empty());
114	}
115
116	#[test]
117	fn TestZoneHasLoopbackRecords() {
118		let Zone = EditorLandZone().expect("Failed to create zone");
119
120		for Record in &Zone {
121			if let RData::A(IP) = Record.data() {
122				assert_eq!(IP.octets()[0], 127, "A record must resolve to 127.x.x.x");
123			}
124		}
125	}
126}