greshake / i3status-rust

Very resourcefriendly and feature-rich replacement for i3status, written in pure Rust
GNU General Public License v3.0
2.88k stars 475 forks source link

Netlink module fails to parse IPv6 addresses with zone ID #2080

Closed torimus closed 2 months ago

torimus commented 2 months ago

Problem description: netlink module fails with "Failed to read nameservers" error when parsing valid IPv6 address (in accordance to RFC6874)

Expected behavior: netlink would properly parse correct IPv6

Steps to reproduce:

This is a known issue in standard Rust library. One solution is to simply discard scope_id part, including '%' delimiter.

Possible quick fix:

diff --git a/src/netlink.rs b/src/netlink.rs
index b8557db..46bf6b6 100644
--- a/src/netlink.rs
+++ b/src/netlink.rs
@@ -438,12 +438,13 @@ async fn read_nameservers() -> Result<Vec<IpAddr>> {
         .await
         .error("Failed to read /etc/resolv.conf")?;
     let mut nameservers = Vec::new();
+    let strip_scope_id = |s: &str| s.chars().take_while(|c| *c != '%').collect::<String>();

     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")?);
+                nameservers.push(strip_scope_id(ip).parse().error("Unable to parse ip")?);
             }
         }
     }
MaxVerevkin commented 2 months ago

Thanks for a detailed report.

In case of resolv.conf, which information does the zone id convey? We of course can simply ignore it, but if this zone id implies that a nameserver is only specified for that net interface, then we may use that information to not show this nameserver if it doesn't match iface.

But it may mean something different, I don't know, in which case ignoring it would be fine.

torimus commented 2 months ago

In my example, this is how NetworkManager declares scope(zone) id by default. Unfortunately the format is not strict to be relied upon - see specification in RFC6874.

It would be ideal, as you suggest, if it could be used to determine name of the network interface for that non-global address, but it does not seem to be the case. I'm all ears if it behaves consistently in practice for different setups.

MaxVerevkin commented 2 months ago

Hm, okay, I guess a TODO would suffice for now :)