feat(net): Add nl80211 support (#1009)
This patch enables support for nl80211. In case the libnl-genl-3.0 library isn't found, it will fall back to Wext instead. The library to use can also be manually set with the CMake option WITH_LIBNL. The Wireless-Extensions (WE or Wext) are deprecated and long replaced by cfg80211. Although Wext isn't used by WiFi drivers anymore, CFG80211_WEXT allows old tools to communicate with modern drivers by providing a wrapper API.
This commit is contained in:
parent
d43a4a8d9d
commit
3afc341c7b
@ -106,7 +106,7 @@ A compiler with C++14 support ([clang-3.4+](http://llvm.org/releases/download.ht
|
|||||||
- jsoncpp *required by `internal/i3`*
|
- jsoncpp *required by `internal/i3`*
|
||||||
- libmpdclient *required by `internal/mpd`*
|
- libmpdclient *required by `internal/mpd`*
|
||||||
- libcurl *required by `internal/github`*
|
- libcurl *required by `internal/github`*
|
||||||
- wireless_tools *required by `internal/network`*
|
- libnl-genl or wireless_tools *required by `internal/network`*
|
||||||
|
|
||||||
Find a more complete list on the [dedicated wiki page](https://github.com/jaagr/polybar/wiki/Compiling).
|
Find a more complete list on the [dedicated wiki page](https://github.com/jaagr/polybar/wiki/Compiling).
|
||||||
|
|
||||||
|
16
build.sh
16
build.sh
@ -38,21 +38,21 @@ function main
|
|||||||
|
|
||||||
msg "Setting build options"
|
msg "Setting build options"
|
||||||
|
|
||||||
read -r -p "$(msg "Use GCC even if Clang is installed -------------------------------- [y/N]: ")" -n 1 p && echo
|
read -r -p "$(msg "Use GCC even if Clang is installed ----------------------------- [y/N]: ")" -n 1 p && echo
|
||||||
[[ "${p^^}" != "Y" ]] && try_to_use_clang="ON"
|
[[ "${p^^}" != "Y" ]] && try_to_use_clang="ON"
|
||||||
read -r -p "$(msg "Include support for \"internal/i3\" (requires i3) ------------------- [y/N]: ")" -n 1 p && echo
|
read -r -p "$(msg "Include support for \"internal/i3\" (requires i3) ---------------- [y/N]: ")" -n 1 p && echo
|
||||||
[[ "${p^^}" != "Y" ]] && enable_i3="OFF"
|
[[ "${p^^}" != "Y" ]] && enable_i3="OFF"
|
||||||
read -r -p "$(msg "Include support for \"internal/alsa\" (requires alsalib) ------------ [y/N]: ")" -n 1 p && echo
|
read -r -p "$(msg "Include support for \"internal/alsa\" (requires alsalib) --------- [y/N]: ")" -n 1 p && echo
|
||||||
[[ "${p^^}" != "Y" ]] && enable_alsa="OFF"
|
[[ "${p^^}" != "Y" ]] && enable_alsa="OFF"
|
||||||
read -r -p "$(msg "Include support for \"internal/pulseaudio\" (requires libpulse) ----- [y/N]: ")" -n 1 p && echo
|
read -r -p "$(msg "Include support for \"internal/pulseaudio\" (requires libpulse) -- [y/N]: ")" -n 1 p && echo
|
||||||
[[ "${p^^}" != "Y" ]] && enable_pulseaudio="OFF"
|
[[ "${p^^}" != "Y" ]] && enable_pulseaudio="OFF"
|
||||||
read -r -p "$(msg "Include support for \"internal/network\" (requires wireless_tools) -- [y/N]: ")" -n 1 p && echo
|
read -r -p "$(msg "Include support for \"internal/network\" (requires libnl/libiw) -- [y/N]: ")" -n 1 p && echo
|
||||||
[[ "${p^^}" != "Y" ]] && enable_network="OFF"
|
[[ "${p^^}" != "Y" ]] && enable_network="OFF"
|
||||||
read -r -p "$(msg "Include support for \"internal/mpd\" (requires libmpdclient) -------- [y/N]: ")" -n 1 p && echo
|
read -r -p "$(msg "Include support for \"internal/mpd\" (requires libmpdclient) ----- [y/N]: ")" -n 1 p && echo
|
||||||
[[ "${p^^}" != "Y" ]] && enable_mpd="OFF"
|
[[ "${p^^}" != "Y" ]] && enable_mpd="OFF"
|
||||||
read -r -p "$(msg "Include support for \"internal/github\" (requires libcurl) ---------- [y/N]: ")" -n 1 p && echo
|
read -r -p "$(msg "Include support for \"internal/github\" (requires libcurl) ------- [y/N]: ")" -n 1 p && echo
|
||||||
[[ "${p^^}" != "Y" ]] && enable_curl="OFF"
|
[[ "${p^^}" != "Y" ]] && enable_curl="OFF"
|
||||||
read -r -p "$(msg "Build \"polybar-msg\" used to send ipc messages --------------------- [y/N]: ")" -n 1 p && echo
|
read -r -p "$(msg "Build \"polybar-msg\" used to send ipc messages ------------------ [y/N]: ")" -n 1 p && echo
|
||||||
[[ "${p^^}" != "Y" ]] && build_ipc_msg="OFF"
|
[[ "${p^^}" != "Y" ]] && build_ipc_msg="OFF"
|
||||||
|
|
||||||
local cxx="c++"
|
local cxx="c++"
|
||||||
|
@ -6,7 +6,12 @@ checklib(ENABLE_ALSA "pkg-config" alsa)
|
|||||||
checklib(ENABLE_CURL "pkg-config" libcurl)
|
checklib(ENABLE_CURL "pkg-config" libcurl)
|
||||||
checklib(ENABLE_I3 "binary" i3)
|
checklib(ENABLE_I3 "binary" i3)
|
||||||
checklib(ENABLE_MPD "pkg-config" libmpdclient)
|
checklib(ENABLE_MPD "pkg-config" libmpdclient)
|
||||||
checklib(ENABLE_NETWORK "cmake" Libiw)
|
checklib(WITH_LIBNL "pkg-config" libnl-genl-3.0)
|
||||||
|
if(WITH_LIBNL)
|
||||||
|
checklib(ENABLE_NETWORK "pkg-config" libnl-genl-3.0)
|
||||||
|
else()
|
||||||
|
checklib(ENABLE_NETWORK "cmake" Libiw)
|
||||||
|
endif()
|
||||||
checklib(ENABLE_PULSEAUDIO "pkg-config" libpulse)
|
checklib(ENABLE_PULSEAUDIO "pkg-config" libpulse)
|
||||||
checklib(ENABLE_PULSEAUDIO "binary" pulseaudio)
|
checklib(ENABLE_PULSEAUDIO "binary" pulseaudio)
|
||||||
checklib(WITH_XKB "pkg-config" xcb-xkb)
|
checklib(WITH_XKB "pkg-config" xcb-xkb)
|
||||||
@ -28,6 +33,7 @@ option(ENABLE_ALSA "Enable alsa support" ON)
|
|||||||
option(ENABLE_CURL "Enable curl support" ON)
|
option(ENABLE_CURL "Enable curl support" ON)
|
||||||
option(ENABLE_I3 "Enable i3 support" ON)
|
option(ENABLE_I3 "Enable i3 support" ON)
|
||||||
option(ENABLE_MPD "Enable mpd support" ON)
|
option(ENABLE_MPD "Enable mpd support" ON)
|
||||||
|
option(WITH_LIBNL "Use netlink interface for wireless" ON)
|
||||||
option(ENABLE_NETWORK "Enable network support" ON)
|
option(ENABLE_NETWORK "Enable network support" ON)
|
||||||
option(ENABLE_XKEYBOARD "Enable xkeyboard support" ON)
|
option(ENABLE_XKEYBOARD "Enable xkeyboard support" ON)
|
||||||
option(ENABLE_PULSEAUDIO "Enable PulseAudio support" ON)
|
option(ENABLE_PULSEAUDIO "Enable PulseAudio support" ON)
|
||||||
|
@ -10,7 +10,11 @@ querylib(TRUE "pkg-config" cairo-fc libs dirs)
|
|||||||
querylib(ENABLE_ALSA "pkg-config" alsa libs dirs)
|
querylib(ENABLE_ALSA "pkg-config" alsa libs dirs)
|
||||||
querylib(ENABLE_CURL "pkg-config" libcurl libs dirs)
|
querylib(ENABLE_CURL "pkg-config" libcurl libs dirs)
|
||||||
querylib(ENABLE_MPD "pkg-config" libmpdclient libs dirs)
|
querylib(ENABLE_MPD "pkg-config" libmpdclient libs dirs)
|
||||||
querylib(ENABLE_NETWORK "cmake" Libiw libs dirs)
|
if(WITH_LIBNL)
|
||||||
|
querylib(ENABLE_NETWORK "pkg-config" libnl-genl-3.0 libs dirs)
|
||||||
|
else()
|
||||||
|
querylib(ENABLE_NETWORK "cmake" Libiw libs dirs)
|
||||||
|
endif()
|
||||||
querylib(ENABLE_PULSEAUDIO "pkg-config" libpulse libs dirs)
|
querylib(ENABLE_PULSEAUDIO "pkg-config" libpulse libs dirs)
|
||||||
|
|
||||||
querylib(WITH_XCOMPOSITE "pkg-config" xcb-composite libs dirs)
|
querylib(WITH_XCOMPOSITE "pkg-config" xcb-composite libs dirs)
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <ifaddrs.h>
|
#include <ifaddrs.h>
|
||||||
#include <iwlib.h>
|
|
||||||
|
|
||||||
#ifdef inline
|
#ifdef inline
|
||||||
#undef inline
|
#undef inline
|
||||||
@ -17,6 +16,15 @@
|
|||||||
#include "components/logger.hpp"
|
#include "components/logger.hpp"
|
||||||
#include "utils/math.hpp"
|
#include "utils/math.hpp"
|
||||||
|
|
||||||
|
#if WITH_LIBNL
|
||||||
|
#include <net/if.h>
|
||||||
|
|
||||||
|
struct nl_msg;
|
||||||
|
struct nlattr;
|
||||||
|
#else
|
||||||
|
#include <iwlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
|
|
||||||
class file_descriptor;
|
class file_descriptor;
|
||||||
@ -103,6 +111,39 @@ namespace net {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
|
#if WITH_LIBNL
|
||||||
|
// class : wireless_network {{{
|
||||||
|
|
||||||
|
class wireless_network : public network {
|
||||||
|
public:
|
||||||
|
wireless_network(string interface) : network(interface), m_ifid(if_nametoindex(interface.c_str())){};
|
||||||
|
|
||||||
|
bool query(bool accumulate = false) override;
|
||||||
|
bool connected() const override;
|
||||||
|
string essid() const;
|
||||||
|
int signal() const;
|
||||||
|
int quality() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static int scan_cb(struct nl_msg* msg, void* instance);
|
||||||
|
|
||||||
|
bool associated_or_joined(struct nlattr** bss);
|
||||||
|
void parse_essid(struct nlattr** bss);
|
||||||
|
void parse_frequency(struct nlattr** bss);
|
||||||
|
void parse_quality(struct nlattr** bss);
|
||||||
|
void parse_signal(struct nlattr** bss);
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned int m_ifid{};
|
||||||
|
string m_essid{};
|
||||||
|
int m_frequency{};
|
||||||
|
quality_range m_signalstrength{};
|
||||||
|
quality_range m_linkquality{};
|
||||||
|
};
|
||||||
|
|
||||||
|
// }}}
|
||||||
|
#else
|
||||||
// class : wireless_network {{{
|
// class : wireless_network {{{
|
||||||
|
|
||||||
class wireless_network : public network {
|
class wireless_network : public network {
|
||||||
@ -128,9 +169,10 @@ namespace net {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
|
#endif
|
||||||
|
|
||||||
using wireless_t = unique_ptr<wireless_network>;
|
using wireless_t = unique_ptr<wireless_network>;
|
||||||
using wired_t = unique_ptr<wired_network>;
|
using wired_t = unique_ptr<wired_network>;
|
||||||
}
|
} // namespace net
|
||||||
|
|
||||||
POLYBAR_NS_END
|
POLYBAR_NS_END
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#cmakedefine01 ENABLE_ALSA
|
#cmakedefine01 ENABLE_ALSA
|
||||||
#cmakedefine01 ENABLE_MPD
|
#cmakedefine01 ENABLE_MPD
|
||||||
#cmakedefine01 ENABLE_NETWORK
|
#cmakedefine01 ENABLE_NETWORK
|
||||||
|
#cmakedefine01 WITH_LIBNL
|
||||||
#cmakedefine01 ENABLE_I3
|
#cmakedefine01 ENABLE_I3
|
||||||
#cmakedefine01 ENABLE_CURL
|
#cmakedefine01 ENABLE_CURL
|
||||||
#cmakedefine01 ENABLE_PULSEAUDIO
|
#cmakedefine01 ENABLE_PULSEAUDIO
|
||||||
|
@ -23,6 +23,13 @@ endif()
|
|||||||
if(NOT ENABLE_NETWORK)
|
if(NOT ENABLE_NETWORK)
|
||||||
list(REMOVE_ITEM files modules/network.cpp)
|
list(REMOVE_ITEM files modules/network.cpp)
|
||||||
list(REMOVE_ITEM files adapters/net.cpp)
|
list(REMOVE_ITEM files adapters/net.cpp)
|
||||||
|
list(REMOVE_ITEM files adapters/net_iw.cpp)
|
||||||
|
list(REMOVE_ITEM files adapters/net_nl.cpp)
|
||||||
|
endif()
|
||||||
|
if(WITH_LIBNL)
|
||||||
|
list(REMOVE_ITEM files adapters/net_iw.cpp)
|
||||||
|
else()
|
||||||
|
list(REMOVE_ITEM files adapters/net_nl.cpp)
|
||||||
endif()
|
endif()
|
||||||
if(NOT ENABLE_I3)
|
if(NOT ENABLE_I3)
|
||||||
list(REMOVE_ITEM files modules/i3.cpp)
|
list(REMOVE_ITEM files modules/i3.cpp)
|
||||||
|
@ -1,21 +1,16 @@
|
|||||||
#include "adapters/net.hpp"
|
#include "adapters/net.hpp"
|
||||||
|
|
||||||
#include <cerrno>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <fstream>
|
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <sstream>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <linux/ethtool.h>
|
#include <linux/ethtool.h>
|
||||||
#include <linux/if_link.h>
|
#include <linux/if_link.h>
|
||||||
#include <linux/sockios.h>
|
#include <linux/sockios.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
|
#include <netdb.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <climits>
|
|
||||||
#include <csignal>
|
|
||||||
|
|
||||||
#ifdef inline
|
#ifdef inline
|
||||||
#undef inline
|
#undef inline
|
||||||
@ -192,9 +187,9 @@ namespace net {
|
|||||||
driver.cmd = ETHTOOL_GDRVINFO;
|
driver.cmd = ETHTOOL_GDRVINFO;
|
||||||
|
|
||||||
memset(&request, 0, sizeof(request));
|
memset(&request, 0, sizeof(request));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Only copy array size minus one bytes over to ensure there is a
|
* Only copy array size minus one bytes over to ensure there is a
|
||||||
* terminating NUL byte (which is guaranteed by memset)
|
* terminating NUL byte (which is guaranteed by memset)
|
||||||
*/
|
*/
|
||||||
strncpy(request.ifr_name, m_interface.c_str(), IFNAMSIZ - 1);
|
strncpy(request.ifr_name, m_interface.c_str(), IFNAMSIZ - 1);
|
||||||
@ -306,133 +301,7 @@ namespace net {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
// class : wireless_network {{{
|
|
||||||
|
|
||||||
/**
|
} // namespace net
|
||||||
* Query the wireless device for information
|
|
||||||
* about the current connection
|
|
||||||
*/
|
|
||||||
bool wireless_network::query(bool accumulate) {
|
|
||||||
if (!network::query(accumulate)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto socket_fd = file_util::make_file_descriptor(iw_sockets_open());
|
|
||||||
if (!*socket_fd) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct iwreq req {};
|
|
||||||
|
|
||||||
if (iw_get_ext(*socket_fd, m_interface.c_str(), SIOCGIWMODE, &req) == -1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ignore interfaces in ad-hoc mode
|
|
||||||
if (req.u.mode == IW_MODE_ADHOC) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
query_essid(*socket_fd);
|
|
||||||
query_quality(*socket_fd);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check current connection state
|
|
||||||
*/
|
|
||||||
bool wireless_network::connected() const {
|
|
||||||
if (!network::test_interface()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !m_essid.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ESSID reported by last query
|
|
||||||
*/
|
|
||||||
string wireless_network::essid() const {
|
|
||||||
return m_essid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Signal strength percentage reported by last query
|
|
||||||
*/
|
|
||||||
int wireless_network::signal() const {
|
|
||||||
return m_signalstrength.percentage();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Link quality percentage reported by last query
|
|
||||||
*/
|
|
||||||
int wireless_network::quality() const {
|
|
||||||
return m_linkquality.percentage();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Query for ESSID
|
|
||||||
*/
|
|
||||||
void wireless_network::query_essid(const int& socket_fd) {
|
|
||||||
char essid[IW_ESSID_MAX_SIZE + 1];
|
|
||||||
|
|
||||||
struct iwreq req {};
|
|
||||||
req.u.essid.pointer = &essid;
|
|
||||||
req.u.essid.length = sizeof(essid);
|
|
||||||
req.u.essid.flags = 0;
|
|
||||||
|
|
||||||
if (iw_get_ext(socket_fd, m_interface.c_str(), SIOCGIWESSID, &req) != -1) {
|
|
||||||
m_essid = string{essid};
|
|
||||||
} else {
|
|
||||||
m_essid.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Query for device driver quality values
|
|
||||||
*/
|
|
||||||
void wireless_network::query_quality(const int& socket_fd) {
|
|
||||||
iwrange range{};
|
|
||||||
iwstats stats{};
|
|
||||||
|
|
||||||
// Fill range
|
|
||||||
if (iw_get_range_info(socket_fd, m_interface.c_str(), &range) == -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Fill stats
|
|
||||||
if (iw_get_stats(socket_fd, m_interface.c_str(), &stats, &range, 1) == -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the driver supplies the quality value
|
|
||||||
if (stats.qual.updated & IW_QUAL_QUAL_INVALID) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Check if the driver supplies the quality level value
|
|
||||||
if (stats.qual.updated & IW_QUAL_LEVEL_INVALID) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the link quality has been uodated
|
|
||||||
if (stats.qual.updated & IW_QUAL_QUAL_UPDATED) {
|
|
||||||
m_linkquality.val = stats.qual.qual;
|
|
||||||
m_linkquality.max = range.max_qual.qual;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the signal strength has been uodated
|
|
||||||
if (stats.qual.updated & IW_QUAL_LEVEL_UPDATED) {
|
|
||||||
m_signalstrength.val = stats.qual.level;
|
|
||||||
m_signalstrength.max = range.max_qual.level;
|
|
||||||
|
|
||||||
// Check if the values are defined in dBm
|
|
||||||
if (stats.qual.level > range.max_qual.level) {
|
|
||||||
m_signalstrength.val -= 0x100;
|
|
||||||
m_signalstrength.max = (stats.qual.level - range.max_qual.level) - 0x100;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
}
|
|
||||||
|
|
||||||
POLYBAR_NS_END
|
POLYBAR_NS_END
|
||||||
|
137
src/adapters/net_iw.cpp
Normal file
137
src/adapters/net_iw.cpp
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
#include "adapters/net.hpp"
|
||||||
|
|
||||||
|
#include "utils/file.hpp"
|
||||||
|
|
||||||
|
POLYBAR_NS
|
||||||
|
|
||||||
|
namespace net {
|
||||||
|
// class : wireless_network {{{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query the wireless device for information
|
||||||
|
* about the current connection
|
||||||
|
*/
|
||||||
|
bool wireless_network::query(bool accumulate) {
|
||||||
|
if (!network::query(accumulate)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto socket_fd = file_util::make_file_descriptor(iw_sockets_open());
|
||||||
|
if (!*socket_fd) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct iwreq req {};
|
||||||
|
|
||||||
|
if (iw_get_ext(*socket_fd, m_interface.c_str(), SIOCGIWMODE, &req) == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore interfaces in ad-hoc mode
|
||||||
|
if (req.u.mode == IW_MODE_ADHOC) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
query_essid(*socket_fd);
|
||||||
|
query_quality(*socket_fd);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check current connection state
|
||||||
|
*/
|
||||||
|
bool wireless_network::connected() const {
|
||||||
|
if (!network::test_interface()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return !m_essid.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ESSID reported by last query
|
||||||
|
*/
|
||||||
|
string wireless_network::essid() const {
|
||||||
|
return m_essid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signal strength percentage reported by last query
|
||||||
|
*/
|
||||||
|
int wireless_network::signal() const {
|
||||||
|
return m_signalstrength.percentage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Link quality percentage reported by last query
|
||||||
|
*/
|
||||||
|
int wireless_network::quality() const {
|
||||||
|
return m_linkquality.percentage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query for ESSID
|
||||||
|
*/
|
||||||
|
void wireless_network::query_essid(const int& socket_fd) {
|
||||||
|
char essid[IW_ESSID_MAX_SIZE + 1];
|
||||||
|
|
||||||
|
struct iwreq req {};
|
||||||
|
req.u.essid.pointer = &essid;
|
||||||
|
req.u.essid.length = sizeof(essid);
|
||||||
|
req.u.essid.flags = 0;
|
||||||
|
|
||||||
|
if (iw_get_ext(socket_fd, m_interface.c_str(), SIOCGIWESSID, &req) != -1) {
|
||||||
|
m_essid = string{essid};
|
||||||
|
} else {
|
||||||
|
m_essid.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query for device driver quality values
|
||||||
|
*/
|
||||||
|
void wireless_network::query_quality(const int& socket_fd) {
|
||||||
|
iwrange range{};
|
||||||
|
iwstats stats{};
|
||||||
|
|
||||||
|
// Fill range
|
||||||
|
if (iw_get_range_info(socket_fd, m_interface.c_str(), &range) == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Fill stats
|
||||||
|
if (iw_get_stats(socket_fd, m_interface.c_str(), &stats, &range, 1) == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the driver supplies the quality value
|
||||||
|
if (stats.qual.updated & IW_QUAL_QUAL_INVALID) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Check if the driver supplies the quality level value
|
||||||
|
if (stats.qual.updated & IW_QUAL_LEVEL_INVALID) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the link quality has been uodated
|
||||||
|
if (stats.qual.updated & IW_QUAL_QUAL_UPDATED) {
|
||||||
|
m_linkquality.val = stats.qual.qual;
|
||||||
|
m_linkquality.max = range.max_qual.qual;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the signal strength has been uodated
|
||||||
|
if (stats.qual.updated & IW_QUAL_LEVEL_UPDATED) {
|
||||||
|
m_signalstrength.val = stats.qual.level;
|
||||||
|
m_signalstrength.max = range.max_qual.level;
|
||||||
|
|
||||||
|
// Check if the values are defined in dBm
|
||||||
|
if (stats.qual.level > range.max_qual.level) {
|
||||||
|
m_signalstrength.val -= 0x100;
|
||||||
|
m_signalstrength.max = (stats.qual.level - range.max_qual.level) - 0x100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// }}}
|
||||||
|
} // namespace net
|
||||||
|
|
||||||
|
POLYBAR_NS_END
|
233
src/adapters/net_nl.cpp
Normal file
233
src/adapters/net_nl.cpp
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
#include "adapters/net.hpp"
|
||||||
|
|
||||||
|
#include <linux/nl80211.h>
|
||||||
|
#include <netlink/genl/ctrl.h>
|
||||||
|
#include <netlink/genl/genl.h>
|
||||||
|
|
||||||
|
#include "utils/file.hpp"
|
||||||
|
|
||||||
|
POLYBAR_NS
|
||||||
|
|
||||||
|
namespace net {
|
||||||
|
// class : wireless_network {{{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query the wireless device for information
|
||||||
|
* about the current connection
|
||||||
|
*/
|
||||||
|
bool wireless_network::query(bool accumulate) {
|
||||||
|
if (!network::query(accumulate)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct nl_sock* sk = nl_socket_alloc();
|
||||||
|
if (sk == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (genl_connect(sk) < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int driver_id = genl_ctrl_resolve(sk, "nl80211");
|
||||||
|
if (driver_id < 0) {
|
||||||
|
nl_socket_free(sk);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, scan_cb, this) != 0) {
|
||||||
|
nl_socket_free(sk);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct nl_msg* msg = nlmsg_alloc();
|
||||||
|
if (msg == nullptr) {
|
||||||
|
nl_socket_free(sk);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, driver_id, 0, NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0) == nullptr) ||
|
||||||
|
nla_put_u32(msg, NL80211_ATTR_IFINDEX, m_ifid) < 0) {
|
||||||
|
nlmsg_free(msg);
|
||||||
|
nl_socket_free(sk);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// nl_send_sync always frees msg
|
||||||
|
if (nl_send_sync(sk, msg) < 0) {
|
||||||
|
nl_socket_free(sk);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nl_socket_free(sk);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check current connection state
|
||||||
|
*/
|
||||||
|
bool wireless_network::connected() const {
|
||||||
|
if (!network::test_interface()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return !m_essid.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ESSID reported by last query
|
||||||
|
*/
|
||||||
|
string wireless_network::essid() const {
|
||||||
|
return m_essid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signal strength percentage reported by last query
|
||||||
|
*/
|
||||||
|
int wireless_network::signal() const {
|
||||||
|
return m_signalstrength.percentage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Link quality percentage reported by last query
|
||||||
|
*/
|
||||||
|
int wireless_network::quality() const {
|
||||||
|
return m_linkquality.percentage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to parse scan results
|
||||||
|
*/
|
||||||
|
int wireless_network::scan_cb(struct nl_msg* msg, void* instance) {
|
||||||
|
auto wn = static_cast<wireless_network*>(instance);
|
||||||
|
auto gnlh = static_cast<genlmsghdr*>(nlmsg_data(nlmsg_hdr(msg)));
|
||||||
|
struct nlattr* tb[NL80211_ATTR_MAX + 1];
|
||||||
|
struct nlattr* bss[NL80211_BSS_MAX + 1];
|
||||||
|
|
||||||
|
struct nla_policy bss_policy[NL80211_BSS_MAX + 1]{};
|
||||||
|
bss_policy[NL80211_BSS_TSF].type = NLA_U64;
|
||||||
|
bss_policy[NL80211_BSS_FREQUENCY].type = NLA_U32;
|
||||||
|
bss_policy[NL80211_BSS_BSSID].type = NLA_UNSPEC;
|
||||||
|
bss_policy[NL80211_BSS_BEACON_INTERVAL].type = NLA_U16;
|
||||||
|
bss_policy[NL80211_BSS_CAPABILITY].type = NLA_U16;
|
||||||
|
bss_policy[NL80211_BSS_INFORMATION_ELEMENTS].type = NLA_UNSPEC;
|
||||||
|
bss_policy[NL80211_BSS_SIGNAL_MBM].type = NLA_U32;
|
||||||
|
bss_policy[NL80211_BSS_SIGNAL_UNSPEC].type = NLA_U8;
|
||||||
|
bss_policy[NL80211_BSS_STATUS].type = NLA_U32;
|
||||||
|
|
||||||
|
if (nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), nullptr) < 0) {
|
||||||
|
return NL_SKIP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tb[NL80211_ATTR_BSS] == nullptr) {
|
||||||
|
return NL_SKIP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS], bss_policy) != 0) {
|
||||||
|
return NL_SKIP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wn->associated_or_joined(bss)) {
|
||||||
|
return NL_SKIP;
|
||||||
|
}
|
||||||
|
|
||||||
|
wn->parse_essid(bss);
|
||||||
|
wn->parse_frequency(bss);
|
||||||
|
wn->parse_signal(bss);
|
||||||
|
wn->parse_quality(bss);
|
||||||
|
|
||||||
|
return NL_SKIP;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check for a connection to a AP
|
||||||
|
*/
|
||||||
|
bool wireless_network::associated_or_joined(struct nlattr** bss) {
|
||||||
|
if (bss[NL80211_BSS_STATUS] == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto status = nla_get_u32(bss[NL80211_BSS_STATUS]);
|
||||||
|
|
||||||
|
switch (status) {
|
||||||
|
case NL80211_BSS_STATUS_ASSOCIATED:
|
||||||
|
case NL80211_BSS_STATUS_IBSS_JOINED:
|
||||||
|
case NL80211_BSS_STATUS_AUTHENTICATED:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the ESSID
|
||||||
|
*/
|
||||||
|
void wireless_network::parse_essid(struct nlattr** bss) {
|
||||||
|
m_essid.clear();
|
||||||
|
|
||||||
|
if (bss[NL80211_BSS_INFORMATION_ELEMENTS] != nullptr) {
|
||||||
|
// Information Element ID from ieee80211.h
|
||||||
|
#define WLAN_EID_SSID 0
|
||||||
|
|
||||||
|
auto ies = static_cast<char*>(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]));
|
||||||
|
auto ies_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
|
||||||
|
const auto hdr_len = 2;
|
||||||
|
|
||||||
|
while (ies_len > hdr_len && ies[0] != WLAN_EID_SSID) {
|
||||||
|
ies_len -= ies[1] + hdr_len;
|
||||||
|
ies += ies[1] + hdr_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ies_len > hdr_len && ies_len > ies[1] + hdr_len) {
|
||||||
|
auto essid_begin = ies + hdr_len;
|
||||||
|
auto essid_end = essid_begin + ies[1];
|
||||||
|
|
||||||
|
// Only use printable characters of the current locale
|
||||||
|
std::copy_if(essid_begin, essid_end, std::back_inserter(m_essid),
|
||||||
|
[](char c) { return isprint(static_cast<unsigned char>(c)); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set frequency
|
||||||
|
*/
|
||||||
|
void wireless_network::parse_frequency(struct nlattr** bss) {
|
||||||
|
if (bss[NL80211_BSS_FREQUENCY] != nullptr) {
|
||||||
|
// in MHz
|
||||||
|
m_frequency = static_cast<int>(nla_get_u32(bss[NL80211_BSS_FREQUENCY]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set device driver quality values
|
||||||
|
*/
|
||||||
|
void wireless_network::parse_quality(struct nlattr** bss) {
|
||||||
|
if (bss[NL80211_BSS_SIGNAL_UNSPEC] != nullptr) {
|
||||||
|
// Signal strength in unspecified units, scaled to 0..100 (u8)
|
||||||
|
m_linkquality.val = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]);
|
||||||
|
m_linkquality.max = 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the signalstrength
|
||||||
|
*/
|
||||||
|
void wireless_network::parse_signal(struct nlattr** bss) {
|
||||||
|
if (bss[NL80211_BSS_SIGNAL_MBM] != nullptr) {
|
||||||
|
// signalstrength in dBm
|
||||||
|
int signalstrength = static_cast<int>(nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM])) / 100;
|
||||||
|
|
||||||
|
// WiFi-hardware usually operates in the range -90 to -20dBm.
|
||||||
|
const int hardware_max = -20;
|
||||||
|
const int hardware_min = -90;
|
||||||
|
signalstrength = std::max(hardware_min, std::min(signalstrength, hardware_max));
|
||||||
|
|
||||||
|
// Shift for positive values
|
||||||
|
m_signalstrength.val = signalstrength - hardware_min;
|
||||||
|
m_signalstrength.max = hardware_max - hardware_min;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace net
|
||||||
|
|
||||||
|
POLYBAR_NS_END
|
Loading…
Reference in New Issue
Block a user