From 4d90ac2f4c09b32ae9a4878319d3b24d7afdb23d Mon Sep 17 00:00:00 2001 From: Patrick Ziegler Date: Fri, 15 Oct 2021 17:36:32 +0200 Subject: [PATCH] fix(net): Use canonical interface name (#2540) One can define an 'altname' for an interface. That name is valid of if_nametoindex but it doesn't appear in `/sys/class/net`: ``` sudo ip link property add dev enp0s31f6 altname eno ``` This creates an altname eno for the existing interface enp0s31f6 Before, using eno, would lead to an error in `realpath`. Ref: https://www.reddit.com/r/Polybar/comments/q8f0ye/error_disabling_module_network_reason_realpath/hgqpq1m/?context=3 --- CHANGELOG.md | 2 ++ include/adapters/net.hpp | 1 + src/adapters/net.cpp | 25 +++++++++++++++++++++++++ src/modules/network.cpp | 8 ++++++++ 4 files changed, 36 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64802916..b6fcd6b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -187,6 +187,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ([`#2491`](https://github.com/polybar/polybar/issues/2491)) - Module would error if WM was not full started up. ([`#1915`](https://github.com/polybar/polybar/issues/1915)) +- `internal/network`: The module now properly supports 'altnames' for + interfaces. ## [3.5.7] - 2021-09-21 ### Fixed diff --git a/include/adapters/net.hpp b/include/adapters/net.hpp index 27cf2c72..f9aa2920 100644 --- a/include/adapters/net.hpp +++ b/include/adapters/net.hpp @@ -38,6 +38,7 @@ namespace net { DEFINE_ERROR(network_error); bool is_interface_valid(const string& ifname); + std::pair get_canonical_interface(const string& ifname); bool is_wireless_interface(const string& ifname); std::string find_wireless_interface(); std::string find_wired_interface(); diff --git a/src/adapters/net.cpp b/src/adapters/net.cpp index 730372c8..e7853486 100644 --- a/src/adapters/net.cpp +++ b/src/adapters/net.cpp @@ -62,6 +62,31 @@ namespace net { return if_nametoindex(ifname.c_str()) != 0; } + /** + * Returns the canonical name of the given interface and whether that differs + * from the given name. + * + * The canonical name is the name that has an entry in `/sys/class/net`. + * + * This resolves any altnames that were defined (see man ip-link). + */ + std::pair get_canonical_interface(const string& ifname) { + int idx = if_nametoindex(ifname.c_str()); + + if (idx == 0) { + throw system_error("if_nameindex(" + ifname + ")"); + } + + char canonical[IF_NAMESIZE]; + if (!if_indextoname(idx, canonical)) { + throw system_error("if_indextoname(" + to_string(idx) + ")"); + } + + string str{canonical}; + + return {str, str != ifname}; + } + /** * Test if interface with given name is a wireless device */ diff --git a/src/modules/network.cpp b/src/modules/network.cpp index 9e979bd8..0eac9f76 100644 --- a/src/modules/network.cpp +++ b/src/modules/network.cpp @@ -44,6 +44,14 @@ namespace modules { throw module_error("Invalid network interface \"" + m_interface + "\""); } + auto canonical = net::get_canonical_interface(m_interface); + + if (canonical.second) { + m_log.info( + "%s: Replacing given interface '%s' with its canonical name '%s'", name(), m_interface, canonical.first); + m_interface = canonical.first; + } + m_ping_nth_update = m_conf.get(name(), "ping-interval", m_ping_nth_update); m_udspeed_minwidth = m_conf.get(name(), "udspeed-minwidth", m_udspeed_minwidth); m_accumulate = m_conf.get(name(), "accumulate-stats", m_accumulate);