trust-dns-client 0.22.0

Trust-DNS is a safe and secure DNS library. This is the Client library with DNSec support. DNSSec with NSEC validation for negative records, is complete. The client supports dynamic DNS with SIG0 authenticated requests, implementing easy to use high level funtions. Trust-DNS is based on the Tokio and Futures libraries, which means it should be easily integrated into other software that also use those libraries.
Documentation
//! Reserved Zone and related information

pub use crate::proto::rr::domain::usage::*;
use crate::proto::rr::domain::{Label, Name};
use crate::proto::serialize::binary::BinEncodable;

use lazy_static::lazy_static;
use radix_trie::{Trie, TrieKey};

// Reserved reverse IPs
//
// [Special-Use Domain Names](https://tools.ietf.org/html/rfc6761), RFC 6761 February, 2013
//
// ```text
// 6.1.  Domain Name Reservation Considerations for Private Addresses
//
//    The private-address [RFC1918] reverse-mapping domains listed below,
//    and any names falling within those domains, are Special-Use Domain
//    Names:
//
//      10.in-addr.arpa.      21.172.in-addr.arpa.  26.172.in-addr.arpa.
//      16.172.in-addr.arpa.  22.172.in-addr.arpa.  27.172.in-addr.arpa.
//      17.172.in-addr.arpa.  30.172.in-addr.arpa.  28.172.in-addr.arpa.
//      18.172.in-addr.arpa.  23.172.in-addr.arpa.  29.172.in-addr.arpa.
//      19.172.in-addr.arpa.  24.172.in-addr.arpa.  31.172.in-addr.arpa.
//      20.172.in-addr.arpa.  25.172.in-addr.arpa.  168.192.in-addr.arpa.
// ```
lazy_static! {
    /// 10.in-addr.arpa. usage
    pub static ref IN_ADDR_ARPA_10: ZoneUsage = ZoneUsage::reverse(Name::from_ascii("10").unwrap().append_domain(&IN_ADDR_ARPA).unwrap());

    static ref IN_ADDR_ARPA_172: Name = Name::from_ascii("172").unwrap().append_domain(&IN_ADDR_ARPA).unwrap();

    /// 16.172.in-addr.arpa. usage
    pub static ref IN_ADDR_ARPA_172_16: ZoneUsage = ZoneUsage::reverse(Name::from_ascii("16").unwrap().append_domain(&IN_ADDR_ARPA_172).unwrap());
    /// 17.172.in-addr.arpa. usage
    pub static ref IN_ADDR_ARPA_172_17: ZoneUsage = ZoneUsage::reverse(Name::from_ascii("17").unwrap().append_domain(&IN_ADDR_ARPA_172).unwrap());
    /// 18.172.in-addr.arpa. usage
    pub static ref IN_ADDR_ARPA_172_18: ZoneUsage = ZoneUsage::reverse(Name::from_ascii("18").unwrap().append_domain(&IN_ADDR_ARPA_172).unwrap());
    /// 19.172.in-addr.arpa. usage
    pub static ref IN_ADDR_ARPA_172_19: ZoneUsage = ZoneUsage::reverse(Name::from_ascii("19").unwrap().append_domain(&IN_ADDR_ARPA_172).unwrap());
    /// 20.172.in-addr.arpa. usage
    pub static ref IN_ADDR_ARPA_172_20: ZoneUsage = ZoneUsage::reverse(Name::from_ascii("20").unwrap().append_domain(&IN_ADDR_ARPA_172).unwrap());
    /// 21.172.in-addr.arpa. usage
    pub static ref IN_ADDR_ARPA_172_21: ZoneUsage = ZoneUsage::reverse(Name::from_ascii("21").unwrap().append_domain(&IN_ADDR_ARPA_172).unwrap());
    /// 22.172.in-addr.arpa. usage
    pub static ref IN_ADDR_ARPA_172_22: ZoneUsage = ZoneUsage::reverse(Name::from_ascii("22").unwrap().append_domain(&IN_ADDR_ARPA_172).unwrap());
    /// 23.172.in-addr.arpa. usage
    pub static ref IN_ADDR_ARPA_172_23: ZoneUsage = ZoneUsage::reverse(Name::from_ascii("23").unwrap().append_domain(&IN_ADDR_ARPA_172).unwrap());
    /// 24.172.in-addr.arpa. usage
    pub static ref IN_ADDR_ARPA_172_24: ZoneUsage = ZoneUsage::reverse(Name::from_ascii("24").unwrap().append_domain(&IN_ADDR_ARPA_172).unwrap());
    /// 25.172.in-addr.arpa. usage
    pub static ref IN_ADDR_ARPA_172_25: ZoneUsage = ZoneUsage::reverse(Name::from_ascii("25").unwrap().append_domain(&IN_ADDR_ARPA_172).unwrap());
    /// 26.172.in-addr.arpa. usage
    pub static ref IN_ADDR_ARPA_172_26: ZoneUsage = ZoneUsage::reverse(Name::from_ascii("26").unwrap().append_domain(&IN_ADDR_ARPA_172).unwrap());
    /// 27.172.in-addr.arpa. usage
    pub static ref IN_ADDR_ARPA_172_27: ZoneUsage = ZoneUsage::reverse(Name::from_ascii("27").unwrap().append_domain(&IN_ADDR_ARPA_172).unwrap());
    /// 28.172.in-addr.arpa. usage
    pub static ref IN_ADDR_ARPA_172_28: ZoneUsage = ZoneUsage::reverse(Name::from_ascii("28").unwrap().append_domain(&IN_ADDR_ARPA_172).unwrap());
    /// 29.172.in-addr.arpa. usage
    pub static ref IN_ADDR_ARPA_172_29: ZoneUsage = ZoneUsage::reverse(Name::from_ascii("29").unwrap().append_domain(&IN_ADDR_ARPA_172).unwrap());
    /// 30.172.in-addr.arpa. usage
    pub static ref IN_ADDR_ARPA_172_30: ZoneUsage = ZoneUsage::reverse(Name::from_ascii("30").unwrap().append_domain(&IN_ADDR_ARPA_172).unwrap());
    /// 31.172.in-addr.arpa. usage
    pub static ref IN_ADDR_ARPA_172_31: ZoneUsage = ZoneUsage::reverse(Name::from_ascii("31").unwrap().append_domain(&IN_ADDR_ARPA_172).unwrap());

    /// 168.192.in-addr.arpa. usage
    pub static ref IN_ADDR_ARPA_192_168: ZoneUsage = ZoneUsage::reverse(Name::from_ascii("168.192").unwrap().append_domain(&IN_ADDR_ARPA).unwrap());
}

// example., example.com., example.net., and example.org.
//
// [Special-Use Domain Names](https://tools.ietf.org/html/rfc6761), RFC 6761 February, 2013
//
// ```text
// 6.5.  Domain Name Reservation Considerations for Example Domains
//
//    The domains "example.", "example.com.", "example.net.",
//    "example.org.", and any names falling within those domains, are
//    special in the following ways:
// ```
lazy_static! {
    static ref COM: Label = Label::from_ascii("com").unwrap();
    static ref NET: Label = Label::from_ascii("net").unwrap();
    static ref ORG: Label = Label::from_ascii("org").unwrap();
    static ref EXAMPLE_L: Label = Label::from_ascii("example").unwrap();

    /// example. usage
    pub static ref EXAMPLE: ZoneUsage = ZoneUsage::example(Name::from_labels(vec![EXAMPLE_L.clone()]).unwrap());
    /// example.com. usage
    pub static ref EXAMPLE_COM: ZoneUsage = ZoneUsage::example(Name::from_labels(vec![EXAMPLE_L.clone(), COM.clone()]).unwrap());
    /// example.com. usage
    pub static ref EXAMPLE_NET: ZoneUsage = ZoneUsage::example(Name::from_labels(vec![EXAMPLE_L.clone(), NET.clone()]).unwrap());
    /// example.com. usage
    pub static ref EXAMPLE_ORG: ZoneUsage = ZoneUsage::example(Name::from_labels(vec![EXAMPLE_L.clone(), ORG.clone()]).unwrap());
}

// test.
//
// [Special-Use Domain Names](https://tools.ietf.org/html/rfc6761), RFC 6761 February, 2013
//
// ```text
// 6.2.  Domain Name Reservation Considerations for "test."
//
//    The domain "test.", and any names falling within ".test.", are
//    special in the following ways:
// ```
lazy_static! {
    /// test. usage
    pub static ref TEST: ZoneUsage = ZoneUsage::test(Name::from_ascii("test.").unwrap());
}

#[derive(Clone, Eq, PartialEq)]
struct TrieName(Name);

impl From<Name> for TrieName {
    fn from(n: Name) -> Self {
        Self(n)
    }
}

impl TrieKey for TrieName {
    /// Returns this name in byte form, reversed for searching from zone to local label
    ///
    /// # Panics
    ///
    /// This will panic on bad names
    fn encode_bytes(&self) -> Vec<u8> {
        let mut bytes = self.0.to_bytes().expect("bad name for trie");
        bytes.reverse();
        bytes
    }
}

#[derive(Clone, Eq, PartialEq)]
struct TrieNameRef<'n>(&'n Name);

impl<'n> From<&'n Name> for TrieNameRef<'n> {
    fn from(n: &'n Name) -> Self {
        TrieNameRef(n)
    }
}

impl<'n> TrieKey for TrieNameRef<'n> {
    /// Returns this name in byte form, reversed for searching from zone to local label
    ///
    /// # Panics
    ///
    /// This will panic on bad names
    fn encode_bytes(&self) -> Vec<u8> {
        let mut bytes = self.0.to_bytes().expect("bad name for trie");
        bytes.reverse();
        bytes
    }
}

/// A Trie of all reserved Zones
pub struct UsageTrie(Trie<TrieName, &'static ZoneUsage>);

impl UsageTrie {
    #[allow(clippy::cognitive_complexity)]
    fn default() -> Self {
        let mut trie: Trie<TrieName, &'static ZoneUsage> = Trie::new();

        assert!(trie.insert(DEFAULT.clone().into(), &DEFAULT).is_none());

        assert!(trie
            .insert(IN_ADDR_ARPA_10.clone().into(), &IN_ADDR_ARPA_10)
            .is_none());
        assert!(trie
            .insert(IN_ADDR_ARPA_172_16.clone().into(), &IN_ADDR_ARPA_172_16)
            .is_none());
        assert!(trie
            .insert(IN_ADDR_ARPA_172_17.clone().into(), &IN_ADDR_ARPA_172_17)
            .is_none());
        assert!(trie
            .insert(IN_ADDR_ARPA_172_18.clone().into(), &IN_ADDR_ARPA_172_18)
            .is_none());
        assert!(trie
            .insert(IN_ADDR_ARPA_172_19.clone().into(), &IN_ADDR_ARPA_172_19)
            .is_none());
        assert!(trie
            .insert(IN_ADDR_ARPA_172_20.clone().into(), &IN_ADDR_ARPA_172_20)
            .is_none());
        assert!(trie
            .insert(IN_ADDR_ARPA_172_21.clone().into(), &IN_ADDR_ARPA_172_21)
            .is_none());
        assert!(trie
            .insert(IN_ADDR_ARPA_172_22.clone().into(), &IN_ADDR_ARPA_172_22)
            .is_none());
        assert!(trie
            .insert(IN_ADDR_ARPA_172_23.clone().into(), &IN_ADDR_ARPA_172_23)
            .is_none());
        assert!(trie
            .insert(IN_ADDR_ARPA_172_24.clone().into(), &IN_ADDR_ARPA_172_24)
            .is_none());
        assert!(trie
            .insert(IN_ADDR_ARPA_172_25.clone().into(), &IN_ADDR_ARPA_172_25)
            .is_none());
        assert!(trie
            .insert(IN_ADDR_ARPA_172_26.clone().into(), &IN_ADDR_ARPA_172_26)
            .is_none());
        assert!(trie
            .insert(IN_ADDR_ARPA_172_27.clone().into(), &IN_ADDR_ARPA_172_27)
            .is_none());
        assert!(trie
            .insert(IN_ADDR_ARPA_172_28.clone().into(), &IN_ADDR_ARPA_172_28)
            .is_none());
        assert!(trie
            .insert(IN_ADDR_ARPA_172_29.clone().into(), &IN_ADDR_ARPA_172_29)
            .is_none());
        assert!(trie
            .insert(IN_ADDR_ARPA_172_30.clone().into(), &IN_ADDR_ARPA_172_30)
            .is_none());
        assert!(trie
            .insert(IN_ADDR_ARPA_172_31.clone().into(), &IN_ADDR_ARPA_172_31)
            .is_none());
        assert!(trie
            .insert(IN_ADDR_ARPA_192_168.clone().into(), &IN_ADDR_ARPA_192_168)
            .is_none());

        assert!(trie.insert(TEST.clone().into(), &TEST).is_none());

        assert!(trie.insert(LOCALHOST.clone().into(), &LOCALHOST).is_none());
        assert!(trie
            .insert(IN_ADDR_ARPA_127.clone().into(), &IN_ADDR_ARPA_127)
            .is_none());
        assert!(trie
            .insert(IP6_ARPA_1.clone().into(), &IP6_ARPA_1)
            .is_none());

        assert!(trie.insert(INVALID.clone().into(), &INVALID).is_none());
        assert!(trie.insert(ONION.clone().into(), &ONION).is_none());

        assert!(trie.insert(EXAMPLE.clone().into(), &EXAMPLE).is_none());
        assert!(trie
            .insert(EXAMPLE_COM.clone().into(), &EXAMPLE_COM)
            .is_none());
        assert!(trie
            .insert(EXAMPLE_NET.clone().into(), &EXAMPLE_NET)
            .is_none());
        assert!(trie
            .insert(EXAMPLE_ORG.clone().into(), &EXAMPLE_ORG)
            .is_none());

        Self(trie)
    }

    /// Fetches the ZoneUsage
    ///
    /// # Returns
    ///
    /// Matches the closest zone encapsulating `name`, at a minimum the default root zone usage will be returned
    pub fn get(&self, name: &Name) -> &'static ZoneUsage {
        self.0
            .get_ancestor_value(&TrieName::from(name.clone()))
            .expect("DEFAULT root ZoneUsage should have been returned")
    }
}

lazy_static! {
    /// All default usage mappings
    pub static ref USAGE: UsageTrie = UsageTrie::default();
}

#[cfg(test)]
mod tests {
    use std::net::{Ipv4Addr, Ipv6Addr};

    use super::*;

    #[test]
    fn test_root() {
        let name = Name::from_ascii("com.").unwrap();

        let usage = USAGE.get(&name);
        assert!(usage.is_root());
    }

    #[test]
    fn test_local_networks() {
        assert_eq!(
            USAGE.get(&Name::from(Ipv4Addr::new(9, 0, 0, 1))).name(),
            DEFAULT.name()
        );
        assert_eq!(
            USAGE.get(&Name::from(Ipv4Addr::new(10, 0, 0, 1))).name(),
            IN_ADDR_ARPA_10.name()
        );
        assert_eq!(
            USAGE.get(&Name::from(Ipv4Addr::new(11, 0, 0, 1))).name(),
            DEFAULT.name()
        );

        assert_eq!(
            USAGE.get(&Name::from(Ipv4Addr::new(172, 16, 0, 0))).name(),
            IN_ADDR_ARPA_172_16.name()
        );
        assert_eq!(
            USAGE.get(&Name::from(Ipv4Addr::new(172, 17, 0, 0))).name(),
            IN_ADDR_ARPA_172_17.name()
        );
        assert_eq!(
            USAGE.get(&Name::from(Ipv4Addr::new(172, 18, 0, 0))).name(),
            IN_ADDR_ARPA_172_18.name()
        );
        assert_eq!(
            USAGE.get(&Name::from(Ipv4Addr::new(172, 19, 0, 0))).name(),
            IN_ADDR_ARPA_172_19.name()
        );
        assert_eq!(
            USAGE.get(&Name::from(Ipv4Addr::new(172, 20, 0, 0))).name(),
            IN_ADDR_ARPA_172_20.name()
        );
        assert_eq!(
            USAGE.get(&Name::from(Ipv4Addr::new(172, 21, 0, 0))).name(),
            IN_ADDR_ARPA_172_21.name()
        );
        assert_eq!(
            USAGE.get(&Name::from(Ipv4Addr::new(172, 22, 0, 0))).name(),
            IN_ADDR_ARPA_172_22.name()
        );
        assert_eq!(
            USAGE.get(&Name::from(Ipv4Addr::new(172, 23, 0, 0))).name(),
            IN_ADDR_ARPA_172_23.name()
        );
        assert_eq!(
            USAGE.get(&Name::from(Ipv4Addr::new(172, 24, 0, 0))).name(),
            IN_ADDR_ARPA_172_24.name()
        );
        assert_eq!(
            USAGE.get(&Name::from(Ipv4Addr::new(172, 25, 0, 0))).name(),
            IN_ADDR_ARPA_172_25.name()
        );
        assert_eq!(
            USAGE.get(&Name::from(Ipv4Addr::new(172, 26, 0, 0))).name(),
            IN_ADDR_ARPA_172_26.name()
        );
        assert_eq!(
            USAGE.get(&Name::from(Ipv4Addr::new(172, 27, 0, 0))).name(),
            IN_ADDR_ARPA_172_27.name()
        );
        assert_eq!(
            USAGE.get(&Name::from(Ipv4Addr::new(172, 28, 0, 0))).name(),
            IN_ADDR_ARPA_172_28.name()
        );
        assert_eq!(
            USAGE.get(&Name::from(Ipv4Addr::new(172, 29, 0, 0))).name(),
            IN_ADDR_ARPA_172_29.name()
        );
        assert_eq!(
            USAGE.get(&Name::from(Ipv4Addr::new(172, 30, 0, 0))).name(),
            IN_ADDR_ARPA_172_30.name()
        );
        assert_eq!(
            USAGE.get(&Name::from(Ipv4Addr::new(172, 31, 0, 0))).name(),
            IN_ADDR_ARPA_172_31.name()
        );

        assert_eq!(
            USAGE.get(&Name::from(Ipv4Addr::new(172, 15, 0, 0))).name(),
            DEFAULT.name()
        );
        assert_eq!(
            USAGE.get(&Name::from(Ipv4Addr::new(172, 32, 0, 0))).name(),
            DEFAULT.name()
        );

        assert_eq!(
            USAGE
                .get(&Name::from(Ipv4Addr::new(192, 167, 255, 255)))
                .name(),
            DEFAULT.name()
        );
        assert_eq!(
            USAGE.get(&Name::from(Ipv4Addr::new(192, 168, 2, 3))).name(),
            IN_ADDR_ARPA_192_168.name()
        );
        assert_eq!(
            USAGE.get(&Name::from(Ipv4Addr::new(192, 169, 0, 0))).name(),
            DEFAULT.name()
        );
    }

    #[test]
    fn test_example() {
        let name = Name::from_ascii("example.").unwrap();

        let usage = USAGE.get(&name);
        assert_eq!(usage.name(), EXAMPLE.name());

        let name = Name::from_ascii("example.com.").unwrap();

        let usage = USAGE.get(&name);
        assert_eq!(usage.name(), EXAMPLE_COM.name());

        let name = Name::from_ascii("example.net.").unwrap();

        let usage = USAGE.get(&name);
        assert_eq!(usage.name(), EXAMPLE_NET.name());

        let name = Name::from_ascii("example.org.").unwrap();

        let usage = USAGE.get(&name);
        assert_eq!(usage.name(), EXAMPLE_ORG.name());

        let name = Name::from_ascii("www.example.org.").unwrap();

        let usage = USAGE.get(&name);
        assert_eq!(usage.name(), EXAMPLE_ORG.name());
    }

    #[test]
    fn test_localhost() {
        let name = Name::from_ascii("localhost.").unwrap();

        let usage = USAGE.get(&name);
        assert_eq!(usage.name(), LOCALHOST.name());

        let name = Name::from_ascii("this.localhost.").unwrap();

        let usage = USAGE.get(&name);
        assert_eq!(usage.name(), LOCALHOST.name());

        assert_eq!(
            USAGE.get(&Name::from(Ipv4Addr::new(127, 0, 0, 1))).name(),
            IN_ADDR_ARPA_127.name()
        );
        assert_eq!(
            USAGE.get(&Name::from(Ipv4Addr::new(127, 0, 0, 2))).name(),
            IN_ADDR_ARPA_127.name()
        );
        assert_eq!(
            USAGE.get(&Name::from(Ipv4Addr::new(127, 255, 0, 0))).name(),
            IN_ADDR_ARPA_127.name()
        );
        assert_eq!(
            USAGE
                .get(&Name::from(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)))
                .name(),
            IP6_ARPA_1.name()
        );
    }

    #[test]
    fn test_invalid() {
        let name = Name::from_ascii("invalid.").unwrap();

        let usage = USAGE.get(&name);
        assert_eq!(usage.name(), INVALID.name());

        let name = Name::from_ascii("something.invalid.").unwrap();

        let usage = USAGE.get(&name);
        assert_eq!(usage.name(), INVALID.name());
    }

    #[test]
    fn test_onion() {
        let name = Name::from_ascii("onion.").unwrap();

        let usage = USAGE.get(&name);
        assert_eq!(usage.name(), ONION.name());

        let name =
            Name::from_ascii("2gzyxa5ihm7nsggfxnu52rck2vv4rvmdlkiu3zzui5du4xyclen53wid.onion.")
                .unwrap(); // torproject.org onion

        let usage = USAGE.get(&name);
        assert_eq!(usage.name(), ONION.name());
    }

    #[test]
    fn test_test() {
        let name = Name::from_ascii("test.").unwrap();

        let usage = USAGE.get(&name);
        assert_eq!(usage.name(), TEST.name());

        let name = Name::from_ascii("foo.bar.test.").unwrap();

        let usage = USAGE.get(&name);
        assert_eq!(usage.name(), TEST.name());
    }
}