Skip to main content

mist/
Zone.rs

1#![allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
2//! # DNS Zone
3//!
4//! Provides DNS zone configuration for the CodeEditorLand private network.
5//! Creates an authoritative zone for `editor.land` that resolves to loopback
6//! addresses.
7
8use anyhow::Result;
9use hickory_proto::rr::{
10	Name,
11	RData,
12	Record,
13	rdata::{A, NS, SOA},
14};
15use hickory_server::{authority::ZoneType, store::in_memory::InMemoryAuthority};
16
17/// Creates the `editor.land` authoritative zone records.
18///
19/// All `*.editor.land` domains resolve to `127.x.x.x` (loopback).
20pub fn EditorLandZone() -> Result<Vec<Record>> {
21	let mut Records = Vec::new();
22	let Origin = Name::from_ascii("editor.land.").unwrap();
23	let TTL = 300u32;
24
25	let Serial = 2025010100u32;
26	let Refresh:i32 = 86400;
27	let Retry:i32 = 7200;
28	let Expire:i32 = 604800;
29	let Minimum:u32 = 3600;
30
31	let SOARecord = SOA::new(
32		Name::from_ascii("ns1.editor.land.").unwrap(),
33		Name::from_ascii("hostmaster.editor.land.").unwrap(),
34		Serial,
35		Refresh,
36		Retry,
37		Expire,
38		Minimum,
39	);
40	Records.push(Record::from_rdata(Origin.clone(), TTL, RData::SOA(SOARecord)));
41
42	let NSName = Name::from_ascii("ns1.editor.land.").unwrap();
43	Records.push(Record::from_rdata(Origin.clone(), TTL, RData::NS(NS(NSName))));
44
45	Records.push(Record::from_rdata(
46		Name::from_ascii("ns1.editor.land.").unwrap(),
47		TTL,
48		RData::A(A::new(127, 0, 0, 1)),
49	));
50
51	let Subdomains = vec!["editor", "www", "localhost", "sidecar", "cocoon"];
52	for (Index, Subdomain) in Subdomains.iter().enumerate() {
53		let SubdomainName = Name::from_ascii(format!("{}.editor.land.", Subdomain)).unwrap();
54		let IP = A::new(127, 0, (Index / 255) as u8, (Index % 255) as u8);
55		Records.push(Record::from_rdata(SubdomainName, TTL, RData::A(IP)));
56	}
57
58	Records.push(Record::from_rdata(Origin, TTL, RData::A(A::new(127, 0, 0, 1))));
59
60	Ok(Records)
61}
62
63/// Creates an `InMemoryAuthority` for the `editor.land` zone.
64pub fn EditorLandAuthority() -> Result<InMemoryAuthority> {
65	let Origin = Name::from_ascii("editor.land.").unwrap();
66	let Authority = InMemoryAuthority::empty(Origin, ZoneType::Primary, false, None);
67	let _Records = EditorLandZone()?;
68	Ok(Authority)
69}
70
71/// Creates an `InMemoryAuthority` for a custom origin with specified records.
72pub fn CustomAuthority(Origin:&Name, _Records:Vec<Record>) -> Result<InMemoryAuthority> {
73	let Authority = InMemoryAuthority::empty(Origin.clone(), ZoneType::Primary, false, None);
74	Ok(Authority)
75}
76
77#[cfg(test)]
78mod tests {
79	use hickory_server::authority::Authority;
80
81	use super::*;
82
83	#[test]
84	fn TestZoneCreation() {
85		let Zone = EditorLandZone().expect("Failed to create zone");
86		assert!(!Zone.is_empty());
87	}
88
89	#[test]
90	fn TestZoneHasLoopbackRecords() {
91		let Zone = EditorLandZone().expect("Failed to create zone");
92		for Record in &Zone {
93			if let RData::A(IP) = Record.data() {
94				assert_eq!(IP.octets()[0], 127, "A record must resolve to 127.x.x.x");
95			}
96		}
97	}
98}