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 addresses.
6
7use anyhow::Result;
8use hickory_proto::rr::{
9	Name,
10	RData,
11	Record,
12	rdata::{A, NS, SOA},
13};
14use hickory_server::authority::ZoneType;
15use hickory_server::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(
44		Origin.clone(),
45		TTL,
46		RData::NS(NS(NSName)),
47	));
48
49	Records.push(Record::from_rdata(
50		Name::from_ascii("ns1.editor.land.").unwrap(),
51		TTL,
52		RData::A(A::new(127, 0, 0, 1)),
53	));
54
55	let Subdomains = vec!["editor", "www", "localhost", "sidecar", "cocoon"];
56	for (Index, Subdomain) in Subdomains.iter().enumerate() {
57		let SubdomainName =
58			Name::from_ascii(format!("{}.editor.land.", Subdomain)).unwrap();
59		let IP = A::new(127, 0, (Index / 255) as u8, (Index % 255) as u8);
60		Records.push(Record::from_rdata(SubdomainName, TTL, RData::A(IP)));
61	}
62
63	Records.push(Record::from_rdata(Origin, TTL, RData::A(A::new(127, 0, 0, 1))));
64
65	Ok(Records)
66}
67
68/// Creates an `InMemoryAuthority` for the `editor.land` zone.
69pub fn EditorLandAuthority() -> Result<InMemoryAuthority> {
70	let Origin = Name::from_ascii("editor.land.").unwrap();
71	let Authority = InMemoryAuthority::empty(Origin, ZoneType::Primary, false, None);
72	let _Records = EditorLandZone()?;
73	Ok(Authority)
74}
75
76/// Creates an `InMemoryAuthority` for a custom origin with specified records.
77pub fn CustomAuthority(Origin: &Name, _Records: Vec<Record>) -> Result<InMemoryAuthority> {
78	let Authority =
79		InMemoryAuthority::empty(Origin.clone(), ZoneType::Primary, false, None);
80	Ok(Authority)
81}
82
83#[cfg(test)]
84mod tests {
85	use super::*;
86	use hickory_server::authority::Authority;
87
88	#[test]
89	fn TestZoneCreation() {
90		let Zone = EditorLandZone().expect("Failed to create zone");
91		assert!(!Zone.is_empty());
92	}
93
94	#[test]
95	fn TestZoneHasLoopbackRecords() {
96		let Zone = EditorLandZone().expect("Failed to create zone");
97		for Record in &Zone {
98			if let RData::A(IP) = Record.data() {
99				assert_eq!(IP.octets()[0], 127, "A record must resolve to 127.x.x.x");
100			}
101		}
102	}
103}