feat(net): Add local_ip6 token (#1239)

It's queried the same way ipv4 addresses are queried, but here it displays globally routable addresses. If there are multiple such addresses, it picks one (same as with ipv4). It's possible that an address discovered this way is not in fact globally reachable but still marked as global.
This commit is contained in:
sqwishy 2018-06-10 13:51:43 -07:00 committed by Patrick Ziegler
parent 1965498e20
commit d1d307d500
3 changed files with 41 additions and 2 deletions

View File

@ -14,6 +14,7 @@
#include "common.hpp"
#include "settings.hpp"
#include "errors.hpp"
#include "components/logger.hpp"
#include "utils/math.hpp"
POLYBAR_NS
@ -49,6 +50,7 @@ namespace net {
struct link_status {
string ip;
string ip6;
link_activity previous{};
link_activity current{};
};
@ -66,6 +68,7 @@ namespace net {
virtual bool ping() const;
string ip() const;
string ip6() const;
string downspeed(int minwidth = 3) const;
string upspeed(int minwidth = 3) const;
void set_unknown_up(bool unknown = true);
@ -74,7 +77,9 @@ namespace net {
void check_tuntap();
bool test_interface() const;
string format_speedrate(float bytes_diff, int minwidth) const;
void query_ip6();
const logger& m_log;
unique_ptr<file_descriptor> m_socketfd;
link_status m_status{};
string m_interface;

View File

@ -7,6 +7,7 @@
#include <sstream>
#include <utility>
#include <arpa/inet.h>
#include <linux/ethtool.h>
#include <linux/if_link.h>
#include <linux/sockios.h>
@ -36,12 +37,14 @@ namespace net {
return file_util::exists("/sys/class/net/" + ifname + "/wireless");
}
static const string NO_IP6 = string("N/A");
// class : network {{{
/**
* Construct network interface
*/
network::network(string interface) : m_interface(move(interface)) {
network::network(string interface) : m_log(logger::make()), m_interface(move(interface)) {
if (if_nametoindex(m_interface.c_str()) == 0) {
throw network_error("Invalid network interface \"" + m_interface + "\"");
}
@ -67,6 +70,7 @@ namespace net {
m_status.current.transmitted = 0;
m_status.current.received = 0;
m_status.current.time = std::chrono::system_clock::now();
m_status.ip6 = NO_IP6;
for (auto ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == nullptr) {
@ -79,6 +83,8 @@ namespace net {
}
}
struct sockaddr_in6* sa6;
switch (ifa->ifa_addr->sa_family) {
case AF_INET:
char ip_buffer[NI_MAXHOST];
@ -86,6 +92,26 @@ namespace net {
m_status.ip = string{ip_buffer};
break;
case AF_INET6:
char ip6_buffer[INET_ADDRSTRLEN];
sa6 = reinterpret_cast<decltype(sa6)>(ifa->ifa_addr);
if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) {
continue;
}
if (IN6_IS_ADDR_SITELOCAL(&sa6->sin6_addr)) {
continue;
}
if ((((unsigned char*)sa6->sin6_addr.s6_addr)[0] & 0xFE) == 0xFC) {
/* Skip Unique Local Addresses (fc00::/7) */
continue;
}
if (inet_ntop(AF_INET6, &sa6->sin6_addr, ip6_buffer, NI_MAXHOST) == 0) {
m_log.warn("inet_ntop() " + string(strerror(errno)));
continue;
}
m_status.ip6 = string{ip6_buffer};
break;
case AF_PACKET:
if (ifa->ifa_data == nullptr) {
continue;
@ -119,12 +145,19 @@ namespace net {
}
/**
* Get interface ip address
* Get interface ipv4 address
*/
string network::ip() const {
return m_status.ip;
}
/**
* Get interface ipv6 address
*/
string network::ip6() const {
return m_status.ip6;
}
/**
* Get download speed rate
*/

View File

@ -117,6 +117,7 @@ namespace modules {
label->reset_tokens();
label->replace_token("%ifname%", m_interface);
label->replace_token("%local_ip%", network->ip());
label->replace_token("%local_ip6%", network->ip6());
label->replace_token("%upspeed%", upspeed);
label->replace_token("%downspeed%", downspeed);