|
@@ -1,18 +1,17 @@
|
|
//! Specifying the address of the DNS server to send requests to.
|
|
//! Specifying the address of the DNS server to send requests to.
|
|
|
|
|
|
-use std::{
|
|
|
|
- io,
|
|
|
|
- net::{IpAddr, UdpSocket},
|
|
|
|
-};
|
|
|
|
|
|
+use std::io;
|
|
|
|
|
|
use log::*;
|
|
use log::*;
|
|
|
|
|
|
use dns::Labels;
|
|
use dns::Labels;
|
|
|
|
|
|
|
|
+
|
|
/// A **resolver** knows the address of the server we should
|
|
/// A **resolver** knows the address of the server we should
|
|
/// send DNS requests to, and the search list for name lookup.
|
|
/// send DNS requests to, and the search list for name lookup.
|
|
#[derive(PartialEq, Debug)]
|
|
#[derive(PartialEq, Debug)]
|
|
pub struct Resolver {
|
|
pub struct Resolver {
|
|
|
|
+
|
|
/// The address of the name server.
|
|
/// The address of the name server.
|
|
pub nameserver: String,
|
|
pub nameserver: String,
|
|
|
|
|
|
@@ -21,24 +20,19 @@ pub struct Resolver {
|
|
}
|
|
}
|
|
|
|
|
|
impl Resolver {
|
|
impl Resolver {
|
|
|
|
+
|
|
/// Returns a resolver with the specified nameserver and an empty
|
|
/// Returns a resolver with the specified nameserver and an empty
|
|
/// search list.
|
|
/// search list.
|
|
pub fn specified(nameserver: String) -> Self {
|
|
pub fn specified(nameserver: String) -> Self {
|
|
let search_list = Vec::new();
|
|
let search_list = Vec::new();
|
|
- Self {
|
|
|
|
- nameserver,
|
|
|
|
- search_list,
|
|
|
|
- }
|
|
|
|
|
|
+ Self { nameserver, search_list }
|
|
}
|
|
}
|
|
|
|
|
|
/// Returns a resolver that is default for the system.
|
|
/// Returns a resolver that is default for the system.
|
|
pub fn system_default() -> Self {
|
|
pub fn system_default() -> Self {
|
|
let (nameserver_opt, search_list) = system_nameservers().expect("Failed to get nameserver");
|
|
let (nameserver_opt, search_list) = system_nameservers().expect("Failed to get nameserver");
|
|
let nameserver = nameserver_opt.expect("No nameserver found");
|
|
let nameserver = nameserver_opt.expect("No nameserver found");
|
|
- Self {
|
|
|
|
- nameserver,
|
|
|
|
- search_list,
|
|
|
|
- }
|
|
|
|
|
|
+ Self { nameserver, search_list }
|
|
}
|
|
}
|
|
|
|
|
|
/// Returns a nameserver that queries should be sent to.
|
|
/// Returns a nameserver that queries should be sent to.
|
|
@@ -50,21 +44,25 @@ impl Resolver {
|
|
/// of the search list.
|
|
/// of the search list.
|
|
pub fn name_list(&self, name: &Labels) -> Vec<Labels> {
|
|
pub fn name_list(&self, name: &Labels) -> Vec<Labels> {
|
|
let mut list = Vec::new();
|
|
let mut list = Vec::new();
|
|
|
|
+
|
|
if name.len() > 1 {
|
|
if name.len() > 1 {
|
|
list.push(name.clone());
|
|
list.push(name.clone());
|
|
return list;
|
|
return list;
|
|
}
|
|
}
|
|
|
|
+
|
|
for search in &self.search_list {
|
|
for search in &self.search_list {
|
|
match Labels::encode(search) {
|
|
match Labels::encode(search) {
|
|
- Ok(suffix) => list.push(name.extend(&suffix)),
|
|
|
|
- Err(_) => panic!("Invalid search list {}", search),
|
|
|
|
|
|
+ Ok(suffix) => list.push(name.extend(&suffix)),
|
|
|
|
+ Err(_) => panic!("Invalid search list {}", search),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
list.push(name.clone());
|
|
list.push(name.clone());
|
|
list
|
|
list
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
/// Looks up the system default nameserver on Unix, by querying
|
|
/// Looks up the system default nameserver on Unix, by querying
|
|
/// `/etc/resolv.conf` and returning the first line that specifies one.
|
|
/// `/etc/resolv.conf` and returning the first line that specifies one.
|
|
/// Returns an error if there’s a problem reading the file, or `None` if no
|
|
/// Returns an error if there’s a problem reading the file, or `None` if no
|
|
@@ -88,7 +86,7 @@ fn system_nameservers() -> io::Result<(Option<String>, Vec<String>)> {
|
|
|
|
|
|
match ip {
|
|
match ip {
|
|
Ok(_ip) => nameservers.push(nameserver_str.into()),
|
|
Ok(_ip) => nameservers.push(nameserver_str.into()),
|
|
- Err(e) => warn!("Failed to parse nameserver line {:?}: {}", line, e),
|
|
|
|
|
|
+ Err(e) => warn!("Failed to parse nameserver line {:?}: {}", line, e),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -101,10 +99,14 @@ fn system_nameservers() -> io::Result<(Option<String>, Vec<String>)> {
|
|
Ok((nameservers.first().cloned(), search_list))
|
|
Ok((nameservers.first().cloned(), search_list))
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
/// Looks up the system default nameserver on Windows, by iterating through
|
|
/// Looks up the system default nameserver on Windows, by iterating through
|
|
/// the list of network adapters and returning the first nameserver it finds.
|
|
/// the list of network adapters and returning the first nameserver it finds.
|
|
#[cfg(windows)]
|
|
#[cfg(windows)]
|
|
|
|
+#[allow(unused)] // todo: Remove this when the time is right
|
|
fn system_nameservers() -> io::Result<(Option<String>, Vec<String>)> {
|
|
fn system_nameservers() -> io::Result<(Option<String>, Vec<String>)> {
|
|
|
|
+ use std::net::{IpAddr, UdpSocket};
|
|
|
|
+
|
|
let adapters = match ipconfig::get_adapters() {
|
|
let adapters = match ipconfig::get_adapters() {
|
|
Ok(a) => a,
|
|
Ok(a) => a,
|
|
Err(e) => {
|
|
Err(e) => {
|
|
@@ -112,24 +114,43 @@ fn system_nameservers() -> io::Result<(Option<String>, Vec<String>)> {
|
|
return Ok((None, Vec::new()));
|
|
return Ok((None, Vec::new()));
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
+
|
|
// According to the specification, prefer ipv6 by default.
|
|
// According to the specification, prefer ipv6 by default.
|
|
// TODO: add control flag to select an ip family.
|
|
// TODO: add control flag to select an ip family.
|
|
- #[allow(dead_code)]
|
|
|
|
#[derive(Debug, PartialEq)]
|
|
#[derive(Debug, PartialEq)]
|
|
enum ForceIPFamily {
|
|
enum ForceIPFamily {
|
|
V4,
|
|
V4,
|
|
V6,
|
|
V6,
|
|
None,
|
|
None,
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ // get the IP of the Network adapter that is used to access the Internet
|
|
|
|
+ // https://stackoverflow.com/questions/24661022/getting-ip-adress-associated-to-real-hardware-ethernet-controller-in-windows-c
|
|
|
|
+ fn get_ipv4() -> io::Result<IpAddr> {
|
|
|
|
+ let s = UdpSocket::bind("0.0.0.0:0")?;
|
|
|
|
+ s.connect("8.8.8.8:53")?;
|
|
|
|
+ let addr = s.local_addr()?;
|
|
|
|
+ Ok(addr.ip())
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fn get_ipv6() -> io::Result<IpAddr> {
|
|
|
|
+ let s = UdpSocket::bind("[::1]:0")?;
|
|
|
|
+ s.connect("[2001:4860:4860::8888]:53")?;
|
|
|
|
+ let addr = s.local_addr()?;
|
|
|
|
+ Ok(addr.ip())
|
|
|
|
+ }
|
|
|
|
+
|
|
let force_ip_family: ForceIPFamily = ForceIPFamily::None;
|
|
let force_ip_family: ForceIPFamily = ForceIPFamily::None;
|
|
let ip = match force_ip_family {
|
|
let ip = match force_ip_family {
|
|
ForceIPFamily::V4 => get_ipv4().ok(),
|
|
ForceIPFamily::V4 => get_ipv4().ok(),
|
|
ForceIPFamily::V6 => get_ipv6().ok(),
|
|
ForceIPFamily::V6 => get_ipv6().ok(),
|
|
ForceIPFamily::None => get_ipv6().or(get_ipv4()).ok(),
|
|
ForceIPFamily::None => get_ipv6().or(get_ipv4()).ok(),
|
|
};
|
|
};
|
|
|
|
+
|
|
let active_adapters = adapters.iter().filter(|a| {
|
|
let active_adapters = adapters.iter().filter(|a| {
|
|
a.oper_status() == ipconfig::OperStatus::IfOperStatusUp && !a.gateways().is_empty()
|
|
a.oper_status() == ipconfig::OperStatus::IfOperStatusUp && !a.gateways().is_empty()
|
|
});
|
|
});
|
|
|
|
+
|
|
if let Some(dns_server) = active_adapters
|
|
if let Some(dns_server) = active_adapters
|
|
.clone()
|
|
.clone()
|
|
.find(|a| ip.map(|ip| a.ip_addresses().contains(&ip)).unwrap_or(false))
|
|
.find(|a| ip.map(|ip| a.ip_addresses().contains(&ip)).unwrap_or(false))
|
|
@@ -140,6 +161,7 @@ fn system_nameservers() -> io::Result<(Option<String>, Vec<String>)> {
|
|
// TODO: Implement dns suffix search list on Windows
|
|
// TODO: Implement dns suffix search list on Windows
|
|
return Ok((Some(dns_server.to_string()), Vec::new()));
|
|
return Ok((Some(dns_server.to_string()), Vec::new()));
|
|
}
|
|
}
|
|
|
|
+
|
|
// Fallback
|
|
// Fallback
|
|
if let Some(dns_server) = active_adapters
|
|
if let Some(dns_server) = active_adapters
|
|
.flat_map(|a| a.dns_servers())
|
|
.flat_map(|a| a.dns_servers())
|
|
@@ -153,6 +175,7 @@ fn system_nameservers() -> io::Result<(Option<String>, Vec<String>)> {
|
|
return Ok((None, Vec::new()));
|
|
return Ok((None, Vec::new()));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
/// The fall-back system default nameserver determinator that is not very
|
|
/// The fall-back system default nameserver determinator that is not very
|
|
/// determined as it returns nothing without actually checking anything.
|
|
/// determined as it returns nothing without actually checking anything.
|
|
#[cfg(all(not(unix), not(windows)))]
|
|
#[cfg(all(not(unix), not(windows)))]
|
|
@@ -160,17 +183,3 @@ fn system_nameservers() -> io::Result<(Option<String>, Vec<String>)> {
|
|
warn!("Unable to fetch default nameservers on this platform.");
|
|
warn!("Unable to fetch default nameservers on this platform.");
|
|
Ok((None, Vec::new()))
|
|
Ok((None, Vec::new()))
|
|
}
|
|
}
|
|
-// get the IP of the Network adapter that is used to access the Internet
|
|
|
|
-// https://stackoverflow.com/questions/24661022/getting-ip-adress-associated-to-real-hardware-ethernet-controller-in-windows-c
|
|
|
|
-fn get_ipv4() -> io::Result<IpAddr> {
|
|
|
|
- let s = UdpSocket::bind("0.0.0.0:0")?;
|
|
|
|
- s.connect("8.8.8.8:53")?;
|
|
|
|
- let addr = s.local_addr()?;
|
|
|
|
- Ok(addr.ip())
|
|
|
|
-}
|
|
|
|
-fn get_ipv6() -> io::Result<IpAddr> {
|
|
|
|
- let s = UdpSocket::bind("[::1]:0")?;
|
|
|
|
- s.connect("[2001:4860:4860::8888]:53")?;
|
|
|
|
- let addr = s.local_addr()?;
|
|
|
|
- Ok(addr.ip())
|
|
|
|
-}
|
|
|