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);