1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
use {grammar, ScopedIp, Network, ParseError};

/// Represent a resolver configuration, as described in `man 5 resolv.conf` on linux.
/// The options and defaults match those in this `man` page.
///
/// ```rust
/// extern crate resolv_conf;
///
/// use std::net::Ipv4Addr;
/// use resolv_conf::{Config, ScopedIp};
///
/// fn main() {
///     // Create a new config
///     let mut config = Config::new();
///     config.nameservers.push(ScopedIp::V4(Ipv4Addr::new(8, 8, 8, 8)));
///     config.search.push("example.com".into());
///
///     // Parse a config
///     let parsed = Config::parse("nameserver 8.8.8.8\nsearch example.com").unwrap();
///     assert_eq!(parsed, config);
/// }
/// ```
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Config {
    /// List of nameservers
    pub nameservers: Vec<ScopedIp>,
    /// List of suffixes to append to name when it doesn't contain ndots
    pub search: Vec<String>,
    /// List of preferred addresses
    pub sortlist: Vec<Network>,
    /// Enable DNS resolve debugging
    pub debug: bool,
    /// Number of dots in name to try absolute resolving first (default 1)
    pub ndots: u32,
    /// Dns query timeout (default 5 [sec])
    pub timeout: u32,
    /// Number of attempts to resolve name if server is inaccesible (default 2)
    pub attempts: u32,
    /// Round-robin selection of servers (default false)
    pub rotate: bool,
    /// Don't check names for validity (default false)
    pub no_check_names: bool,
    /// Try AAAA query before A
    pub inet6: bool,
    /// Use reverse lookup of ipv6 using bit-label format described instead
    /// of nibble format
    pub ip6_bytestring: bool,
    /// Do ipv6 reverse lookups in ip6.int zone instead of ip6.arpa
    /// (default false)
    pub ip6_dotint: bool,
    /// Enable dns extensions described in RFC 2671
    pub edns0: bool,
    /// Don't make ipv4 and ipv6 requests simultaneously
    pub single_request: bool,
    /// Use same socket for the A and AAAA requests
    pub single_request_reopen: bool,
    /// Don't resolve unqualified name as top level domain
    pub no_tld_query: bool,
    /// Force using TCP for DNS resolution
    pub use_vc: bool,
}

impl Config {
    /// Create a new `Config` object with default values.
    ///
    /// ```rust
    /// # extern crate resolv_conf;
    /// use resolv_conf::Config;
    /// # fn main() {
    /// assert_eq!(
    ///     Config::new(),
    ///     Config {
    ///         nameservers: vec![],
    ///         search: vec![],
    ///         sortlist: vec![],
    ///         debug: false,
    ///         ndots: 1,
    ///         timeout: 5,
    ///         attempts: 2,
    ///         rotate: false,
    ///         no_check_names: false,
    ///         inet6: false,
    ///         ip6_bytestring: false,
    ///         ip6_dotint: false,
    ///         edns0: false,
    ///         single_request: false,
    ///         single_request_reopen: false,
    ///         no_tld_query: false,
    ///         use_vc: false,
    ///     });
    /// # }
    pub fn new() -> Config {
        Config {
            nameservers: Vec::new(),
            search: Vec::new(),
            sortlist: Vec::new(),
            debug: false,
            ndots: 1,
            timeout: 5,
            attempts: 2,
            rotate: false,
            no_check_names: false,
            inet6: false,
            ip6_bytestring: false,
            ip6_dotint: false,
            edns0: false,
            single_request: false,
            single_request_reopen: false,
            no_tld_query: false,
            use_vc: false,
        }
    }

    /// Parse a buffer and return the corresponding `Config` object.
    ///
    /// ```rust
    /// # extern crate resolv_conf;
    /// use resolv_conf::{ScopedIp, Config};
    /// # fn main() {
    /// let config_str = "# /etc/resolv.conf
    /// nameserver  8.8.8.8
    /// nameserver  8.8.4.4
    /// search      example.com sub.example.com
    /// options     ndots:8 attempts:8";
    ///
    /// // Parse the config
    /// let parsed_config = Config::parse(&config_str).expect("Failed to parse config");
    ///
    /// // Print the config
    /// println!("{:?}", parsed_config);
    /// # }
    /// ```
    pub fn parse<T: AsRef<[u8]>>(buf: T) -> Result<Config, ParseError> {
        grammar::parse(buf.as_ref())
    }
}