trust_dns_client/rr/
zone.rs

1//! Reserved Zone and related information
2
3pub use crate::proto::rr::domain::usage::*;
4use crate::proto::rr::domain::{Label, Name};
5use crate::proto::serialize::binary::BinEncodable;
6
7use once_cell::sync::Lazy;
8use radix_trie::{Trie, TrieKey};
9
10// Reserved reverse IPs
11//
12// [Special-Use Domain Names](https://tools.ietf.org/html/rfc6761), RFC 6761 February, 2013
13//
14// ```text
15// 6.1.  Domain Name Reservation Considerations for Private Addresses
16//
17//    The private-address [RFC1918] reverse-mapping domains listed below,
18//    and any names falling within those domains, are Special-Use Domain
19//    Names:
20//
21//      10.in-addr.arpa.      21.172.in-addr.arpa.  26.172.in-addr.arpa.
22//      16.172.in-addr.arpa.  22.172.in-addr.arpa.  27.172.in-addr.arpa.
23//      17.172.in-addr.arpa.  30.172.in-addr.arpa.  28.172.in-addr.arpa.
24//      18.172.in-addr.arpa.  23.172.in-addr.arpa.  29.172.in-addr.arpa.
25//      19.172.in-addr.arpa.  24.172.in-addr.arpa.  31.172.in-addr.arpa.
26//      20.172.in-addr.arpa.  25.172.in-addr.arpa.  168.192.in-addr.arpa.
27// ```
28
29/// 10.in-addr.arpa. usage
30pub static IN_ADDR_ARPA_10: Lazy<ZoneUsage> = Lazy::new(|| {
31    ZoneUsage::reverse(
32        Name::from_ascii("10")
33            .unwrap()
34            .append_domain(&IN_ADDR_ARPA)
35            .unwrap(),
36    )
37});
38
39static IN_ADDR_ARPA_172: Lazy<Name> = Lazy::new(|| {
40    Name::from_ascii("172")
41        .unwrap()
42        .append_domain(&IN_ADDR_ARPA)
43        .unwrap()
44});
45
46/// 16.172.in-addr.arpa. usage
47pub static IN_ADDR_ARPA_172_16: Lazy<ZoneUsage> = Lazy::new(|| {
48    ZoneUsage::reverse(
49        Name::from_ascii("16")
50            .unwrap()
51            .append_domain(&IN_ADDR_ARPA_172)
52            .unwrap(),
53    )
54});
55/// 17.172.in-addr.arpa. usage
56pub static IN_ADDR_ARPA_172_17: Lazy<ZoneUsage> = Lazy::new(|| {
57    ZoneUsage::reverse(
58        Name::from_ascii("17")
59            .unwrap()
60            .append_domain(&IN_ADDR_ARPA_172)
61            .unwrap(),
62    )
63});
64/// 18.172.in-addr.arpa. usage
65pub static IN_ADDR_ARPA_172_18: Lazy<ZoneUsage> = Lazy::new(|| {
66    ZoneUsage::reverse(
67        Name::from_ascii("18")
68            .unwrap()
69            .append_domain(&IN_ADDR_ARPA_172)
70            .unwrap(),
71    )
72});
73/// 19.172.in-addr.arpa. usage
74pub static IN_ADDR_ARPA_172_19: Lazy<ZoneUsage> = Lazy::new(|| {
75    ZoneUsage::reverse(
76        Name::from_ascii("19")
77            .unwrap()
78            .append_domain(&IN_ADDR_ARPA_172)
79            .unwrap(),
80    )
81});
82/// 20.172.in-addr.arpa. usage
83pub static IN_ADDR_ARPA_172_20: Lazy<ZoneUsage> = Lazy::new(|| {
84    ZoneUsage::reverse(
85        Name::from_ascii("20")
86            .unwrap()
87            .append_domain(&IN_ADDR_ARPA_172)
88            .unwrap(),
89    )
90});
91/// 21.172.in-addr.arpa. usage
92pub static IN_ADDR_ARPA_172_21: Lazy<ZoneUsage> = Lazy::new(|| {
93    ZoneUsage::reverse(
94        Name::from_ascii("21")
95            .unwrap()
96            .append_domain(&IN_ADDR_ARPA_172)
97            .unwrap(),
98    )
99});
100/// 22.172.in-addr.arpa. usage
101pub static IN_ADDR_ARPA_172_22: Lazy<ZoneUsage> = Lazy::new(|| {
102    ZoneUsage::reverse(
103        Name::from_ascii("22")
104            .unwrap()
105            .append_domain(&IN_ADDR_ARPA_172)
106            .unwrap(),
107    )
108});
109/// 23.172.in-addr.arpa. usage
110pub static IN_ADDR_ARPA_172_23: Lazy<ZoneUsage> = Lazy::new(|| {
111    ZoneUsage::reverse(
112        Name::from_ascii("23")
113            .unwrap()
114            .append_domain(&IN_ADDR_ARPA_172)
115            .unwrap(),
116    )
117});
118/// 24.172.in-addr.arpa. usage
119pub static IN_ADDR_ARPA_172_24: Lazy<ZoneUsage> = Lazy::new(|| {
120    ZoneUsage::reverse(
121        Name::from_ascii("24")
122            .unwrap()
123            .append_domain(&IN_ADDR_ARPA_172)
124            .unwrap(),
125    )
126});
127/// 25.172.in-addr.arpa. usage
128pub static IN_ADDR_ARPA_172_25: Lazy<ZoneUsage> = Lazy::new(|| {
129    ZoneUsage::reverse(
130        Name::from_ascii("25")
131            .unwrap()
132            .append_domain(&IN_ADDR_ARPA_172)
133            .unwrap(),
134    )
135});
136/// 26.172.in-addr.arpa. usage
137pub static IN_ADDR_ARPA_172_26: Lazy<ZoneUsage> = Lazy::new(|| {
138    ZoneUsage::reverse(
139        Name::from_ascii("26")
140            .unwrap()
141            .append_domain(&IN_ADDR_ARPA_172)
142            .unwrap(),
143    )
144});
145/// 27.172.in-addr.arpa. usage
146pub static IN_ADDR_ARPA_172_27: Lazy<ZoneUsage> = Lazy::new(|| {
147    ZoneUsage::reverse(
148        Name::from_ascii("27")
149            .unwrap()
150            .append_domain(&IN_ADDR_ARPA_172)
151            .unwrap(),
152    )
153});
154/// 28.172.in-addr.arpa. usage
155pub static IN_ADDR_ARPA_172_28: Lazy<ZoneUsage> = Lazy::new(|| {
156    ZoneUsage::reverse(
157        Name::from_ascii("28")
158            .unwrap()
159            .append_domain(&IN_ADDR_ARPA_172)
160            .unwrap(),
161    )
162});
163/// 29.172.in-addr.arpa. usage
164pub static IN_ADDR_ARPA_172_29: Lazy<ZoneUsage> = Lazy::new(|| {
165    ZoneUsage::reverse(
166        Name::from_ascii("29")
167            .unwrap()
168            .append_domain(&IN_ADDR_ARPA_172)
169            .unwrap(),
170    )
171});
172/// 30.172.in-addr.arpa. usage
173pub static IN_ADDR_ARPA_172_30: Lazy<ZoneUsage> = Lazy::new(|| {
174    ZoneUsage::reverse(
175        Name::from_ascii("30")
176            .unwrap()
177            .append_domain(&IN_ADDR_ARPA_172)
178            .unwrap(),
179    )
180});
181/// 31.172.in-addr.arpa. usage
182pub static IN_ADDR_ARPA_172_31: Lazy<ZoneUsage> = Lazy::new(|| {
183    ZoneUsage::reverse(
184        Name::from_ascii("31")
185            .unwrap()
186            .append_domain(&IN_ADDR_ARPA_172)
187            .unwrap(),
188    )
189});
190
191/// 168.192.in-addr.arpa. usage
192pub static IN_ADDR_ARPA_192_168: Lazy<ZoneUsage> = Lazy::new(|| {
193    ZoneUsage::reverse(
194        Name::from_ascii("168.192")
195            .unwrap()
196            .append_domain(&IN_ADDR_ARPA)
197            .unwrap(),
198    )
199});
200
201// example., example.com., example.net., and example.org.
202//
203// [Special-Use Domain Names](https://tools.ietf.org/html/rfc6761), RFC 6761 February, 2013
204//
205// ```text
206// 6.5.  Domain Name Reservation Considerations for Example Domains
207//
208//    The domains "example.", "example.com.", "example.net.",
209//    "example.org.", and any names falling within those domains, are
210//    special in the following ways:
211// ```
212
213static COM: Lazy<Label> = Lazy::new(|| Label::from_ascii("com").unwrap());
214static NET: Lazy<Label> = Lazy::new(|| Label::from_ascii("net").unwrap());
215static ORG: Lazy<Label> = Lazy::new(|| Label::from_ascii("org").unwrap());
216static EXAMPLE_L: Lazy<Label> = Lazy::new(|| Label::from_ascii("example").unwrap());
217
218/// example. usage
219pub static EXAMPLE: Lazy<ZoneUsage> =
220    Lazy::new(|| ZoneUsage::example(Name::from_labels(vec![EXAMPLE_L.clone()]).unwrap()));
221/// example.com. usage
222pub static EXAMPLE_COM: Lazy<ZoneUsage> = Lazy::new(|| {
223    ZoneUsage::example(Name::from_labels(vec![EXAMPLE_L.clone(), COM.clone()]).unwrap())
224});
225/// example.com. usage
226pub static EXAMPLE_NET: Lazy<ZoneUsage> = Lazy::new(|| {
227    ZoneUsage::example(Name::from_labels(vec![EXAMPLE_L.clone(), NET.clone()]).unwrap())
228});
229/// example.com. usage
230pub static EXAMPLE_ORG: Lazy<ZoneUsage> = Lazy::new(|| {
231    ZoneUsage::example(Name::from_labels(vec![EXAMPLE_L.clone(), ORG.clone()]).unwrap())
232});
233
234// test.
235//
236// [Special-Use Domain Names](https://tools.ietf.org/html/rfc6761), RFC 6761 February, 2013
237//
238// ```text
239// 6.2.  Domain Name Reservation Considerations for "test."
240//
241//    The domain "test.", and any names falling within ".test.", are
242//    special in the following ways:
243// ```
244
245/// test. usage
246pub static TEST: Lazy<ZoneUsage> =
247    Lazy::new(|| ZoneUsage::test(Name::from_ascii("test.").unwrap()));
248
249#[derive(Clone, Eq, PartialEq)]
250struct TrieName(Name);
251
252impl From<Name> for TrieName {
253    fn from(n: Name) -> Self {
254        Self(n)
255    }
256}
257
258impl TrieKey for TrieName {
259    /// Returns this name in byte form, reversed for searching from zone to local label
260    ///
261    /// # Panics
262    ///
263    /// This will panic on bad names
264    fn encode_bytes(&self) -> Vec<u8> {
265        let mut bytes = self.0.to_bytes().expect("bad name for trie");
266        bytes.reverse();
267        bytes
268    }
269}
270
271#[derive(Clone, Eq, PartialEq)]
272struct TrieNameRef<'n>(&'n Name);
273
274impl<'n> From<&'n Name> for TrieNameRef<'n> {
275    fn from(n: &'n Name) -> Self {
276        TrieNameRef(n)
277    }
278}
279
280impl<'n> TrieKey for TrieNameRef<'n> {
281    /// Returns this name in byte form, reversed for searching from zone to local label
282    ///
283    /// # Panics
284    ///
285    /// This will panic on bad names
286    fn encode_bytes(&self) -> Vec<u8> {
287        let mut bytes = self.0.to_bytes().expect("bad name for trie");
288        bytes.reverse();
289        bytes
290    }
291}
292
293/// A Trie of all reserved Zones
294pub struct UsageTrie(Trie<TrieName, &'static ZoneUsage>);
295
296impl UsageTrie {
297    #[allow(clippy::cognitive_complexity)]
298    fn default() -> Self {
299        let mut trie: Trie<TrieName, &'static ZoneUsage> = Trie::new();
300
301        assert!(trie.insert(DEFAULT.clone().into(), &DEFAULT).is_none());
302
303        assert!(trie
304            .insert(IN_ADDR_ARPA_10.clone().into(), &IN_ADDR_ARPA_10)
305            .is_none());
306        assert!(trie
307            .insert(IN_ADDR_ARPA_172_16.clone().into(), &IN_ADDR_ARPA_172_16)
308            .is_none());
309        assert!(trie
310            .insert(IN_ADDR_ARPA_172_17.clone().into(), &IN_ADDR_ARPA_172_17)
311            .is_none());
312        assert!(trie
313            .insert(IN_ADDR_ARPA_172_18.clone().into(), &IN_ADDR_ARPA_172_18)
314            .is_none());
315        assert!(trie
316            .insert(IN_ADDR_ARPA_172_19.clone().into(), &IN_ADDR_ARPA_172_19)
317            .is_none());
318        assert!(trie
319            .insert(IN_ADDR_ARPA_172_20.clone().into(), &IN_ADDR_ARPA_172_20)
320            .is_none());
321        assert!(trie
322            .insert(IN_ADDR_ARPA_172_21.clone().into(), &IN_ADDR_ARPA_172_21)
323            .is_none());
324        assert!(trie
325            .insert(IN_ADDR_ARPA_172_22.clone().into(), &IN_ADDR_ARPA_172_22)
326            .is_none());
327        assert!(trie
328            .insert(IN_ADDR_ARPA_172_23.clone().into(), &IN_ADDR_ARPA_172_23)
329            .is_none());
330        assert!(trie
331            .insert(IN_ADDR_ARPA_172_24.clone().into(), &IN_ADDR_ARPA_172_24)
332            .is_none());
333        assert!(trie
334            .insert(IN_ADDR_ARPA_172_25.clone().into(), &IN_ADDR_ARPA_172_25)
335            .is_none());
336        assert!(trie
337            .insert(IN_ADDR_ARPA_172_26.clone().into(), &IN_ADDR_ARPA_172_26)
338            .is_none());
339        assert!(trie
340            .insert(IN_ADDR_ARPA_172_27.clone().into(), &IN_ADDR_ARPA_172_27)
341            .is_none());
342        assert!(trie
343            .insert(IN_ADDR_ARPA_172_28.clone().into(), &IN_ADDR_ARPA_172_28)
344            .is_none());
345        assert!(trie
346            .insert(IN_ADDR_ARPA_172_29.clone().into(), &IN_ADDR_ARPA_172_29)
347            .is_none());
348        assert!(trie
349            .insert(IN_ADDR_ARPA_172_30.clone().into(), &IN_ADDR_ARPA_172_30)
350            .is_none());
351        assert!(trie
352            .insert(IN_ADDR_ARPA_172_31.clone().into(), &IN_ADDR_ARPA_172_31)
353            .is_none());
354        assert!(trie
355            .insert(IN_ADDR_ARPA_192_168.clone().into(), &IN_ADDR_ARPA_192_168)
356            .is_none());
357
358        assert!(trie.insert(TEST.clone().into(), &TEST).is_none());
359
360        assert!(trie.insert(LOCALHOST.clone().into(), &LOCALHOST).is_none());
361        assert!(trie
362            .insert(IN_ADDR_ARPA_127.clone().into(), &IN_ADDR_ARPA_127)
363            .is_none());
364        assert!(trie
365            .insert(IP6_ARPA_1.clone().into(), &IP6_ARPA_1)
366            .is_none());
367
368        assert!(trie.insert(INVALID.clone().into(), &INVALID).is_none());
369        assert!(trie.insert(ONION.clone().into(), &ONION).is_none());
370
371        assert!(trie.insert(EXAMPLE.clone().into(), &EXAMPLE).is_none());
372        assert!(trie
373            .insert(EXAMPLE_COM.clone().into(), &EXAMPLE_COM)
374            .is_none());
375        assert!(trie
376            .insert(EXAMPLE_NET.clone().into(), &EXAMPLE_NET)
377            .is_none());
378        assert!(trie
379            .insert(EXAMPLE_ORG.clone().into(), &EXAMPLE_ORG)
380            .is_none());
381
382        Self(trie)
383    }
384
385    /// Fetches the ZoneUsage
386    ///
387    /// # Returns
388    ///
389    /// Matches the closest zone encapsulating `name`, at a minimum the default root zone usage will be returned
390    pub fn get(&self, name: &Name) -> &'static ZoneUsage {
391        self.0
392            .get_ancestor_value(&TrieName::from(name.clone()))
393            .expect("DEFAULT root ZoneUsage should have been returned")
394    }
395}
396
397/// All default usage mappings
398pub static USAGE: Lazy<UsageTrie> = Lazy::new(UsageTrie::default);
399
400#[cfg(test)]
401mod tests {
402    use std::net::{Ipv4Addr, Ipv6Addr};
403
404    use super::*;
405
406    #[test]
407    fn test_root() {
408        let name = Name::from_ascii("com.").unwrap();
409
410        let usage = USAGE.get(&name);
411        assert!(usage.is_root());
412    }
413
414    #[test]
415    fn test_local_networks() {
416        assert_eq!(
417            USAGE.get(&Name::from(Ipv4Addr::new(9, 0, 0, 1))).name(),
418            DEFAULT.name()
419        );
420        assert_eq!(
421            USAGE.get(&Name::from(Ipv4Addr::new(10, 0, 0, 1))).name(),
422            IN_ADDR_ARPA_10.name()
423        );
424        assert_eq!(
425            USAGE.get(&Name::from(Ipv4Addr::new(11, 0, 0, 1))).name(),
426            DEFAULT.name()
427        );
428
429        assert_eq!(
430            USAGE.get(&Name::from(Ipv4Addr::new(172, 16, 0, 0))).name(),
431            IN_ADDR_ARPA_172_16.name()
432        );
433        assert_eq!(
434            USAGE.get(&Name::from(Ipv4Addr::new(172, 17, 0, 0))).name(),
435            IN_ADDR_ARPA_172_17.name()
436        );
437        assert_eq!(
438            USAGE.get(&Name::from(Ipv4Addr::new(172, 18, 0, 0))).name(),
439            IN_ADDR_ARPA_172_18.name()
440        );
441        assert_eq!(
442            USAGE.get(&Name::from(Ipv4Addr::new(172, 19, 0, 0))).name(),
443            IN_ADDR_ARPA_172_19.name()
444        );
445        assert_eq!(
446            USAGE.get(&Name::from(Ipv4Addr::new(172, 20, 0, 0))).name(),
447            IN_ADDR_ARPA_172_20.name()
448        );
449        assert_eq!(
450            USAGE.get(&Name::from(Ipv4Addr::new(172, 21, 0, 0))).name(),
451            IN_ADDR_ARPA_172_21.name()
452        );
453        assert_eq!(
454            USAGE.get(&Name::from(Ipv4Addr::new(172, 22, 0, 0))).name(),
455            IN_ADDR_ARPA_172_22.name()
456        );
457        assert_eq!(
458            USAGE.get(&Name::from(Ipv4Addr::new(172, 23, 0, 0))).name(),
459            IN_ADDR_ARPA_172_23.name()
460        );
461        assert_eq!(
462            USAGE.get(&Name::from(Ipv4Addr::new(172, 24, 0, 0))).name(),
463            IN_ADDR_ARPA_172_24.name()
464        );
465        assert_eq!(
466            USAGE.get(&Name::from(Ipv4Addr::new(172, 25, 0, 0))).name(),
467            IN_ADDR_ARPA_172_25.name()
468        );
469        assert_eq!(
470            USAGE.get(&Name::from(Ipv4Addr::new(172, 26, 0, 0))).name(),
471            IN_ADDR_ARPA_172_26.name()
472        );
473        assert_eq!(
474            USAGE.get(&Name::from(Ipv4Addr::new(172, 27, 0, 0))).name(),
475            IN_ADDR_ARPA_172_27.name()
476        );
477        assert_eq!(
478            USAGE.get(&Name::from(Ipv4Addr::new(172, 28, 0, 0))).name(),
479            IN_ADDR_ARPA_172_28.name()
480        );
481        assert_eq!(
482            USAGE.get(&Name::from(Ipv4Addr::new(172, 29, 0, 0))).name(),
483            IN_ADDR_ARPA_172_29.name()
484        );
485        assert_eq!(
486            USAGE.get(&Name::from(Ipv4Addr::new(172, 30, 0, 0))).name(),
487            IN_ADDR_ARPA_172_30.name()
488        );
489        assert_eq!(
490            USAGE.get(&Name::from(Ipv4Addr::new(172, 31, 0, 0))).name(),
491            IN_ADDR_ARPA_172_31.name()
492        );
493
494        assert_eq!(
495            USAGE.get(&Name::from(Ipv4Addr::new(172, 15, 0, 0))).name(),
496            DEFAULT.name()
497        );
498        assert_eq!(
499            USAGE.get(&Name::from(Ipv4Addr::new(172, 32, 0, 0))).name(),
500            DEFAULT.name()
501        );
502
503        assert_eq!(
504            USAGE
505                .get(&Name::from(Ipv4Addr::new(192, 167, 255, 255)))
506                .name(),
507            DEFAULT.name()
508        );
509        assert_eq!(
510            USAGE.get(&Name::from(Ipv4Addr::new(192, 168, 2, 3))).name(),
511            IN_ADDR_ARPA_192_168.name()
512        );
513        assert_eq!(
514            USAGE.get(&Name::from(Ipv4Addr::new(192, 169, 0, 0))).name(),
515            DEFAULT.name()
516        );
517    }
518
519    #[test]
520    fn test_example() {
521        let name = Name::from_ascii("example.").unwrap();
522
523        let usage = USAGE.get(&name);
524        assert_eq!(usage.name(), EXAMPLE.name());
525
526        let name = Name::from_ascii("example.com.").unwrap();
527
528        let usage = USAGE.get(&name);
529        assert_eq!(usage.name(), EXAMPLE_COM.name());
530
531        let name = Name::from_ascii("example.net.").unwrap();
532
533        let usage = USAGE.get(&name);
534        assert_eq!(usage.name(), EXAMPLE_NET.name());
535
536        let name = Name::from_ascii("example.org.").unwrap();
537
538        let usage = USAGE.get(&name);
539        assert_eq!(usage.name(), EXAMPLE_ORG.name());
540
541        let name = Name::from_ascii("www.example.org.").unwrap();
542
543        let usage = USAGE.get(&name);
544        assert_eq!(usage.name(), EXAMPLE_ORG.name());
545    }
546
547    #[test]
548    fn test_localhost() {
549        let name = Name::from_ascii("localhost.").unwrap();
550
551        let usage = USAGE.get(&name);
552        assert_eq!(usage.name(), LOCALHOST.name());
553
554        let name = Name::from_ascii("this.localhost.").unwrap();
555
556        let usage = USAGE.get(&name);
557        assert_eq!(usage.name(), LOCALHOST.name());
558
559        assert_eq!(
560            USAGE.get(&Name::from(Ipv4Addr::new(127, 0, 0, 1))).name(),
561            IN_ADDR_ARPA_127.name()
562        );
563        assert_eq!(
564            USAGE.get(&Name::from(Ipv4Addr::new(127, 0, 0, 2))).name(),
565            IN_ADDR_ARPA_127.name()
566        );
567        assert_eq!(
568            USAGE.get(&Name::from(Ipv4Addr::new(127, 255, 0, 0))).name(),
569            IN_ADDR_ARPA_127.name()
570        );
571        assert_eq!(
572            USAGE
573                .get(&Name::from(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)))
574                .name(),
575            IP6_ARPA_1.name()
576        );
577    }
578
579    #[test]
580    fn test_invalid() {
581        let name = Name::from_ascii("invalid.").unwrap();
582
583        let usage = USAGE.get(&name);
584        assert_eq!(usage.name(), INVALID.name());
585
586        let name = Name::from_ascii("something.invalid.").unwrap();
587
588        let usage = USAGE.get(&name);
589        assert_eq!(usage.name(), INVALID.name());
590    }
591
592    #[test]
593    fn test_onion() {
594        let name = Name::from_ascii("onion.").unwrap();
595
596        let usage = USAGE.get(&name);
597        assert_eq!(usage.name(), ONION.name());
598
599        let name =
600            Name::from_ascii("2gzyxa5ihm7nsggfxnu52rck2vv4rvmdlkiu3zzui5du4xyclen53wid.onion.")
601                .unwrap(); // torproject.org onion
602
603        let usage = USAGE.get(&name);
604        assert_eq!(usage.name(), ONION.name());
605    }
606
607    #[test]
608    fn test_test() {
609        let name = Name::from_ascii("test.").unwrap();
610
611        let usage = USAGE.get(&name);
612        assert_eq!(usage.name(), TEST.name());
613
614        let name = Name::from_ascii("foo.bar.test.").unwrap();
615
616        let usage = USAGE.get(&name);
617        assert_eq!(usage.name(), TEST.name());
618    }
619}