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