Merge pull request #1126 from tperard/fix-network-auto-detection
Fix network interface auto detection
This commit is contained in:
commit
9e34be7b16
|
@ -72,6 +72,7 @@ class Network : public ALabel {
|
||||||
int32_t signal_strength_dbm_;
|
int32_t signal_strength_dbm_;
|
||||||
uint8_t signal_strength_;
|
uint8_t signal_strength_;
|
||||||
uint32_t frequency_;
|
uint32_t frequency_;
|
||||||
|
uint32_t route_priority;
|
||||||
|
|
||||||
util::SleeperThread thread_;
|
util::SleeperThread thread_;
|
||||||
util::SleeperThread thread_timer_;
|
util::SleeperThread thread_timer_;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "modules/network.hpp"
|
#include "modules/network.hpp"
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
#include <sys/eventfd.h>
|
#include <sys/eventfd.h>
|
||||||
|
#include <linux/if.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
@ -400,6 +401,7 @@ bool waybar::modules::Network::checkInterface(std::string name) {
|
||||||
|
|
||||||
void waybar::modules::Network::clearIface() {
|
void waybar::modules::Network::clearIface() {
|
||||||
ifid_ = -1;
|
ifid_ = -1;
|
||||||
|
ifname_.clear();
|
||||||
essid_.clear();
|
essid_.clear();
|
||||||
ipaddr_.clear();
|
ipaddr_.clear();
|
||||||
netmask_.clear();
|
netmask_.clear();
|
||||||
|
@ -431,6 +433,20 @@ int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) {
|
||||||
return NL_OK;
|
return NL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if the interface goes "down" and if we want to detect the
|
||||||
|
// external interface.
|
||||||
|
if (net->ifid_ != -1 && !(ifi->ifi_flags & IFF_UP)
|
||||||
|
&& !net->config_["interface"].isString()) {
|
||||||
|
// The current interface is now down, all the routes associated with
|
||||||
|
// it have been deleted, so start looking for a new default route.
|
||||||
|
spdlog::debug("network: if{} down", net->ifid_);
|
||||||
|
net->clearIface();
|
||||||
|
net->dp.emit();
|
||||||
|
net->want_route_dump_ = true;
|
||||||
|
net->askForStateDump();
|
||||||
|
return NL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
for (; RTA_OK(ifla, attrlen); ifla = RTA_NEXT(ifla, attrlen)) {
|
for (; RTA_OK(ifla, attrlen); ifla = RTA_NEXT(ifla, attrlen)) {
|
||||||
switch (ifla->rta_type) {
|
switch (ifla->rta_type) {
|
||||||
case IFLA_IFNAME:
|
case IFLA_IFNAME:
|
||||||
|
@ -572,11 +588,7 @@ int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) {
|
||||||
bool has_gateway = false;
|
bool has_gateway = false;
|
||||||
bool has_destination = false;
|
bool has_destination = false;
|
||||||
int temp_idx = -1;
|
int temp_idx = -1;
|
||||||
|
uint32_t priority = 0;
|
||||||
/* If we found the correct answer, skip parsing the attributes. */
|
|
||||||
if (!is_del_event && net->ifid_ != -1) {
|
|
||||||
return NL_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find the message(s) concerting the main routing table, each message
|
/* Find the message(s) concerting the main routing table, each message
|
||||||
* corresponds to a single routing table entry.
|
* corresponds to a single routing table entry.
|
||||||
|
@ -620,52 +632,59 @@ int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) {
|
||||||
/* The output interface index. */
|
/* The output interface index. */
|
||||||
temp_idx = *static_cast<int *>(RTA_DATA(attr));
|
temp_idx = *static_cast<int *>(RTA_DATA(attr));
|
||||||
break;
|
break;
|
||||||
|
case RTA_PRIORITY:
|
||||||
|
priority = *(uint32_t*)RTA_DATA(attr);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* If this is the default route, and we know the interface index,
|
// Check if we have a default route.
|
||||||
* we can stop parsing this message.
|
if (has_gateway && !has_destination && temp_idx != -1) {
|
||||||
*/
|
// Check if this is the first default route we see, or if this new
|
||||||
if (has_gateway && !has_destination && temp_idx != -1) {
|
// route have a higher priority.
|
||||||
if (!is_del_event) {
|
if (!is_del_event && ((net->ifid_ == -1) || (priority < net->route_priority))) {
|
||||||
net->ifid_ = temp_idx;
|
// Clear if's state for the case were there is a higher priority
|
||||||
|
// route on a different interface.
|
||||||
|
net->clearIface();
|
||||||
|
net->ifid_ = temp_idx;
|
||||||
|
net->route_priority = priority;
|
||||||
|
|
||||||
spdlog::debug("network: new default route via if{}", temp_idx);
|
spdlog::debug("network: new default route via if{} metric {}", temp_idx, priority);
|
||||||
|
|
||||||
/* Ask ifname associated with temp_idx as well as carrier status */
|
/* Ask ifname associated with temp_idx as well as carrier status */
|
||||||
struct ifinfomsg ifinfo_hdr = {
|
struct ifinfomsg ifinfo_hdr = {
|
||||||
.ifi_family = AF_UNSPEC,
|
.ifi_family = AF_UNSPEC,
|
||||||
.ifi_index = temp_idx,
|
.ifi_index = temp_idx,
|
||||||
};
|
};
|
||||||
int err;
|
int err;
|
||||||
err = nl_send_simple(net->ev_sock_, RTM_GETLINK, NLM_F_REQUEST,
|
err = nl_send_simple(net->ev_sock_, RTM_GETLINK, NLM_F_REQUEST,
|
||||||
&ifinfo_hdr, sizeof (ifinfo_hdr));
|
&ifinfo_hdr, sizeof (ifinfo_hdr));
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
spdlog::error("network: failed to ask link info: {}", err);
|
spdlog::error("network: failed to ask link info: {}", err);
|
||||||
/* Ask for a dump of all links instead */
|
/* Ask for a dump of all links instead */
|
||||||
net->want_link_dump_ = true;
|
net->want_link_dump_ = true;
|
||||||
}
|
|
||||||
|
|
||||||
/* Also ask for the address. Asking for a addresses of a specific
|
|
||||||
* interface doesn't seems to work so ask for a dump of all
|
|
||||||
* addresses. */
|
|
||||||
net->want_addr_dump_ = true;
|
|
||||||
net->askForStateDump();
|
|
||||||
net->thread_timer_.wake_up();
|
|
||||||
} else if (is_del_event && temp_idx == net->ifid_) {
|
|
||||||
spdlog::debug("network: default route deleted {}/if{}",
|
|
||||||
net->ifname_, temp_idx);
|
|
||||||
|
|
||||||
net->ifname_.clear();
|
|
||||||
net->clearIface();
|
|
||||||
net->dp.emit();
|
|
||||||
/* Ask for a dump of all routes in case another one is already
|
|
||||||
* setup. If there's none, there'll be an event with new one
|
|
||||||
* later. */
|
|
||||||
net->want_route_dump_ = true;
|
|
||||||
net->askForStateDump();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Also ask for the address. Asking for a addresses of a specific
|
||||||
|
* interface doesn't seems to work so ask for a dump of all
|
||||||
|
* addresses. */
|
||||||
|
net->want_addr_dump_ = true;
|
||||||
|
net->askForStateDump();
|
||||||
|
net->thread_timer_.wake_up();
|
||||||
|
} else if (is_del_event && temp_idx == net->ifid_
|
||||||
|
&& net->route_priority == priority) {
|
||||||
|
spdlog::debug("network: default route deleted {}/if{} metric {}",
|
||||||
|
net->ifname_, temp_idx, priority);
|
||||||
|
|
||||||
|
net->clearIface();
|
||||||
|
net->dp.emit();
|
||||||
|
/* Ask for a dump of all routes in case another one is already
|
||||||
|
* setup. If there's none, there'll be an event with new one
|
||||||
|
* later. */
|
||||||
|
net->want_route_dump_ = true;
|
||||||
|
net->askForStateDump();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue