diff --git a/cspell.yaml b/cspell.yaml index 4aa7648a1a..dda275469c 100644 --- a/cspell.yaml +++ b/cspell.yaml @@ -1,4 +1,4 @@ -version: '0.2' +version: "0.2" language: en-US, en-GB allowCompoundWords: true ignorePaths: @@ -124,6 +124,7 @@ words: - recip - repr - reqwest + - resolv - retval - rofi - rofication diff --git a/src/blocks/net.rs b/src/blocks/net.rs index c9fb1de6ab..3b41882b88 100644 --- a/src/blocks/net.rs +++ b/src/blocks/net.rs @@ -31,6 +31,7 @@ //! `bitrate` | WiFi connection bitrate | Number | Bits per second //! `ip` | IPv4 address of the iface | Text | - //! `ipv6` | IPv6 address of the iface | Text | - +//! `nameserver` | Nameserver | Text | - //! //! # Example //! @@ -61,6 +62,7 @@ use super::prelude::*; use crate::netlink::NetDevice; use crate::util; +use itertools::Itertools; use regex::Regex; use std::time::Instant; @@ -159,6 +161,13 @@ pub async fn run(config: &Config, api: &CommonApi) -> Result<()> { [if let Some(v) = device.frequency()] "frequency" => Value::hertz(v), [if let Some(v) = device.bitrate()] "bitrate" => Value::bits(v), [if let Some(v) = device.signal()] "signal_strength" => Value::percents(v), + [if !device.nameservers.is_empty()] "nameserver" => Value::text( + device + .nameservers + .into_iter() + .map(|s| s.to_string()) + .join(" "), + ), "device" => Value::text(device.iface.name), }); diff --git a/src/netlink.rs b/src/netlink.rs index 05abc83eb1..b8557dbff6 100644 --- a/src/netlink.rs +++ b/src/netlink.rs @@ -9,7 +9,7 @@ use regex::Regex; use libc::c_uchar; -use std::net::{Ipv4Addr, Ipv6Addr}; +use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use std::ops; use std::path::Path; @@ -27,6 +27,7 @@ pub struct NetDevice { pub ipv6: Option, pub icon: &'static str, pub tun_wg_ppp: bool, + pub nameservers: Vec, } #[derive(Debug, Default)] @@ -67,6 +68,9 @@ impl NetDevice { let wifi_info = WifiInfo::new(iface.index).await?; let ip = ipv4(&mut sock, iface.index).await?; let ipv6 = ipv6(&mut sock, iface.index).await?; + let nameservers = read_nameservers() + .await + .error("Failed to read nameservers")?; // TODO: use netlink for the these too // I don't believe that this should ever change, so set it now: @@ -97,6 +101,7 @@ impl NetDevice { ipv6, icon, tun_wg_ppp: tun | wg | ppp, + nameservers, })) } @@ -428,6 +433,24 @@ async fn ipv6(sock: &mut NlSocket, ifa_index: i32) -> Result> { .map(Ipv6Addr::from)) } +async fn read_nameservers() -> Result> { + let file = util::read_file("/etc/resolv.conf") + .await + .error("Failed to read /etc/resolv.conf")?; + let mut nameservers = Vec::new(); + + for line in file.lines() { + let mut line_parts = line.split_whitespace(); + if line_parts.next() == Some("nameserver") { + if let Some(ip) = line_parts.next() { + nameservers.push(ip.parse().error("Unable to parse ip")?); + } + } + } + + Ok(nameservers) +} + // Source: https://www.kernel.org/doc/Documentation/networking/operstates.txt #[derive(Debug, PartialEq, Eq)] pub enum Operstate {