Skip to content

Commit 72cb1e1

Browse files
committed
Windows support with ipconfig
This commit adds Windows support through the ipconfig crate, which determines the system default nameserver to use on Windows, where /etc/resolv.conf isn't a thing.
1 parent 4607bcf commit 72cb1e1

File tree

4 files changed

+94
-2
lines changed

4 files changed

+94
-2
lines changed

.travis.yml

+2
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ rust:
77

88
script:
99
- cargo build --verbose --workspace
10+
- cargo test --verbose --workspace --no-run
1011
- cargo test --verbose --workspace
1112

1213
os:
14+
- windows
1315
- linux
1416
- osx
1517

Cargo.lock

+40
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+4
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ serde_json = "1.0"
4949
# logging
5050
log = "0.4"
5151

52+
# windows default nameserver determination
53+
[target.'cfg(windows)'.dependencies]
54+
ipconfig = { version = "0.2" }
55+
5256
[build-dependencies]
5357
datetime = { version = "0.5.1", default_features = false }
5458
regex = { version = "1.3", default_features = false, features = ["std"] }

src/resolve.rs

+48-2
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,17 @@ pub enum Resolver {
1313
/// Read the list of nameservers from the system, and use that.
1414
SystemDefault,
1515

16-
// Use a resolver specified by the user.
16+
// Use a specific nameserver specified by the user.
1717
Specified(Nameserver),
1818
}
1919

2020
pub type Nameserver = String;
2121

2222
impl Resolver {
23+
24+
/// Returns a nameserver that queries should be sent to, possibly by
25+
/// obtaining one based on the system, returning an error if there was a
26+
/// problem looking one up.
2327
pub fn lookup(self) -> io::Result<Option<Nameserver>> {
2428
match self {
2529
Self::Specified(ns) => Ok(Some(ns)),
@@ -29,6 +33,10 @@ impl Resolver {
2933
}
3034

3135

36+
/// Looks up the system default nameserver on Unix, by querying
37+
/// `/etc/resolv.conf` and returning the first line that specifies one.
38+
/// Returns an error if there’s a problem reading the file, or `None` if no
39+
/// nameserver is specified in the file.
3240
#[cfg(unix)]
3341
fn system_nameservers() -> io::Result<Option<Nameserver>> {
3442
use std::io::{BufRead, BufReader};
@@ -54,7 +62,45 @@ fn system_nameservers() -> io::Result<Option<Nameserver>> {
5462
Ok(nameservers.first().cloned())
5563
}
5664

57-
#[cfg(not(unix))]
65+
66+
/// Looks up the system default nameserver on Windows, by iterating through
67+
/// the list of network adapters and returning the first nameserver it finds.
68+
#[cfg(windows)]
69+
fn system_nameservers() -> io::Result<Option<Nameserver>> {
70+
let adapters = match ipconfig::get_adapters() {
71+
Ok(a) => a,
72+
Err(e) => {
73+
warn!("Error getting network adapters: {}", e);
74+
return Ok(None);
75+
}
76+
};
77+
78+
let first_adapter = match adapters.first() {
79+
Some(a) => a,
80+
None => {
81+
warn!("No network adapters available");
82+
return Ok(None);
83+
}
84+
};
85+
debug!("Found network adapter {:?}", first_adapter.adapter_name());
86+
87+
let first_nameserver = match first_adapter.dns_servers().first() {
88+
Some(ns) => ns,
89+
None => {
90+
warn!("No nameservers available");
91+
return Ok(None);
92+
}
93+
};
94+
debug!("Found nameserver {:?}", first_nameserver);
95+
96+
// todo: have this not be turned into a string, then parsed again later
97+
Ok(Some(first_nameserver.to_string()))
98+
}
99+
100+
101+
/// The fall-back system default nameserver determinator that is not very
102+
/// determined as it returns nothing without actually checking anything.
103+
#[cfg(all(not(unix), not(windows)))]
58104
fn system_nameservers() -> io::Result<Option<Nameserver>> {
59105
warn!("Unable to fetch default nameservers on this platform.");
60106
Ok(None)

0 commit comments

Comments
 (0)