Skip to main content

hickory_resolver/system_conf/
mod.rs

1// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// https://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// https://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8//! System configuration loading
9//!
10//! This module is responsible for parsing and returning the configuration from
11//!  the host system. It will read from the default location on each operating
12//!  system, e.g. most Unixes have this written to `/etc/resolv.conf`
13#![allow(missing_docs)]
14
15#[cfg(all(unix, not(any(target_os = "android", target_vendor = "apple"))))]
16#[cfg(feature = "system-config")]
17mod unix;
18
19#[cfg(all(unix, not(any(target_os = "android", target_vendor = "apple"))))]
20#[cfg(feature = "system-config")]
21pub use self::unix::{parse_resolv_conf, read_system_conf};
22
23#[cfg(windows)]
24#[cfg(feature = "system-config")]
25mod windows;
26
27#[cfg(target_os = "windows")]
28#[cfg(feature = "system-config")]
29pub use self::windows::read_system_conf;
30
31#[cfg(target_os = "android")]
32#[cfg(feature = "system-config")]
33mod android;
34
35#[cfg(target_os = "android")]
36#[cfg(feature = "system-config")]
37pub use self::android::read_system_conf;
38
39#[cfg(target_vendor = "apple")]
40#[cfg(feature = "system-config")]
41mod apple;
42
43#[cfg(target_vendor = "apple")]
44#[cfg(feature = "system-config")]
45pub use self::apple::read_system_conf;
46
47#[cfg(all(feature = "system-config", any(windows, target_vendor = "apple")))]
48mod sanitize {
49    use std::str::FromStr;
50
51    use crate::proto::{ProtoError, rr::Name};
52
53    pub(super) fn parse_search_domains(
54        raw: &str,
55    ) -> impl Iterator<Item = Result<Name, ProtoError>> + '_ {
56        raw.split(|c: char| c.is_whitespace() || c == '\0')
57            .filter(|domain| !domain.is_empty())
58            .map(Name::from_str)
59    }
60
61    #[cfg(test)]
62    mod tests {
63        use std::str::FromStr;
64
65        use crate::proto::rr::Name;
66
67        use super::parse_search_domains;
68
69        fn names(domains: &[&str]) -> Vec<Name> {
70            domains
71                .iter()
72                .map(|d| Name::from_str(d).expect("test domain must parse"))
73                .collect()
74        }
75
76        #[test]
77        fn test_parse_search_domains() {
78            let cases: &[(&str, &[&str])] = &[
79                ("example.com", &["example.com"]),
80                ("example.com. example.net", &["example.com.", "example.net"]),
81                ("a.com\tb.com\r\nc.com", &["a.com", "b.com", "c.com"]),
82                ("test.com\0something.net", &["test.com", "something.net"]),
83                ("", &[]),
84            ];
85            for (input, expected) in cases {
86                assert_eq!(
87                    parse_search_domains(input)
88                        .collect::<Result<Vec<_>, _>>()
89                        .expect("test domains must parse"),
90                    names(expected),
91                    "input: {input:?}"
92                );
93            }
94
95            let invalid = format!("{}.com valid.com", "a".repeat(64));
96            assert!(
97                parse_search_domains(&invalid)
98                    .collect::<Result<Vec<_>, _>>()
99                    .is_err()
100            );
101        }
102    }
103}