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
This commit is contained in:
Patrick Ziegler 2021-10-15 17:36:32 +02:00 committed by GitHub
parent abd96eb089
commit 4d90ac2f4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 36 additions and 0 deletions

View File

@ -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)) ([`#2491`](https://github.com/polybar/polybar/issues/2491))
- Module would error if WM was not full started up. - Module would error if WM was not full started up.
([`#1915`](https://github.com/polybar/polybar/issues/1915)) ([`#1915`](https://github.com/polybar/polybar/issues/1915))
- `internal/network`: The module now properly supports 'altnames' for
interfaces.
## [3.5.7] - 2021-09-21 ## [3.5.7] - 2021-09-21
### Fixed ### Fixed

View File

@ -38,6 +38,7 @@ namespace net {
DEFINE_ERROR(network_error); DEFINE_ERROR(network_error);
bool is_interface_valid(const string& ifname); bool is_interface_valid(const string& ifname);
std::pair<string, bool> get_canonical_interface(const string& ifname);
bool is_wireless_interface(const string& ifname); bool is_wireless_interface(const string& ifname);
std::string find_wireless_interface(); std::string find_wireless_interface();
std::string find_wired_interface(); std::string find_wired_interface();

View File

@ -62,6 +62,31 @@ namespace net {
return if_nametoindex(ifname.c_str()) != 0; 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<string, bool> 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 * Test if interface with given name is a wireless device
*/ */

View File

@ -44,6 +44,14 @@ namespace modules {
throw module_error("Invalid network interface \"" + m_interface + "\""); 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_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_udspeed_minwidth = m_conf.get(name(), "udspeed-minwidth", m_udspeed_minwidth);
m_accumulate = m_conf.get(name(), "accumulate-stats", m_accumulate); m_accumulate = m_conf.get(name(), "accumulate-stats", m_accumulate);