refactor(Network): clean nl socket
This commit is contained in:
parent
0dba3abc1d
commit
0ad2bc7516
|
@ -22,6 +22,7 @@ class Network : public ALabel {
|
||||||
static int scanCb(struct nl_msg*, void*);
|
static int scanCb(struct nl_msg*, void*);
|
||||||
|
|
||||||
void disconnected();
|
void disconnected();
|
||||||
|
void initNL80211();
|
||||||
int getExternalInterface();
|
int getExternalInterface();
|
||||||
void parseEssid(struct nlattr**);
|
void parseEssid(struct nlattr**);
|
||||||
void parseSignal(struct nlattr**);
|
void parseSignal(struct nlattr**);
|
||||||
|
@ -33,6 +34,8 @@ class Network : public ALabel {
|
||||||
sa_family_t family_;
|
sa_family_t family_;
|
||||||
int sock_fd_;
|
int sock_fd_;
|
||||||
struct sockaddr_nl nladdr_ = {0};
|
struct sockaddr_nl nladdr_ = {0};
|
||||||
|
struct nl_sock* sk_ = nullptr;
|
||||||
|
int nl80211_id_;
|
||||||
|
|
||||||
std::string essid_;
|
std::string essid_;
|
||||||
std::string ifname_;
|
std::string ifname_;
|
||||||
|
|
|
@ -28,6 +28,7 @@ waybar::modules::Network::Network(const Json::Value& config)
|
||||||
ifname_ = ifname;
|
ifname_ = ifname;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
initNL80211();
|
||||||
label_.set_name("network");
|
label_.set_name("network");
|
||||||
// Trigger first values
|
// Trigger first values
|
||||||
getInfo();
|
getInfo();
|
||||||
|
@ -76,6 +77,7 @@ waybar::modules::Network::Network(const Json::Value& config)
|
||||||
waybar::modules::Network::~Network()
|
waybar::modules::Network::~Network()
|
||||||
{
|
{
|
||||||
close(sock_fd_);
|
close(sock_fd_);
|
||||||
|
nl_socket_free(sk_);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto waybar::modules::Network::update() -> void
|
auto waybar::modules::Network::update() -> void
|
||||||
|
@ -112,6 +114,24 @@ void waybar::modules::Network::disconnected()
|
||||||
ifid_ = -1;
|
ifid_ = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void waybar::modules::Network::initNL80211()
|
||||||
|
{
|
||||||
|
sk_ = nl_socket_alloc();
|
||||||
|
if (genl_connect(sk_) != 0) {
|
||||||
|
nl_socket_free(sk_);
|
||||||
|
throw std::runtime_error("Can't connect to netlink socket");
|
||||||
|
}
|
||||||
|
if (nl_socket_modify_cb(sk_, NL_CB_VALID, NL_CB_CUSTOM, scanCb, this) < 0) {
|
||||||
|
nl_socket_free(sk_);
|
||||||
|
throw std::runtime_error("Can't connect to netlink socket");
|
||||||
|
}
|
||||||
|
nl80211_id_ = genl_ctrl_resolve(sk_, "nl80211");
|
||||||
|
if (nl80211_id_ < 0) {
|
||||||
|
nl_socket_free(sk_);
|
||||||
|
throw std::runtime_error("Can't resolve nl80211 interface");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Based on https://gist.github.com/Yawning/c70d804d4b8ae78cc698
|
// Based on https://gist.github.com/Yawning/c70d804d4b8ae78cc698
|
||||||
int waybar::modules::Network::getExternalInterface()
|
int waybar::modules::Network::getExternalInterface()
|
||||||
{
|
{
|
||||||
|
@ -263,37 +283,37 @@ uint64_t waybar::modules::Network::netlinkResponse(int fd, void *resp,
|
||||||
}
|
}
|
||||||
|
|
||||||
int waybar::modules::Network::scanCb(struct nl_msg *msg, void *data) {
|
int waybar::modules::Network::scanCb(struct nl_msg *msg, void *data) {
|
||||||
auto net = static_cast<waybar::modules::Network *>(data);
|
auto net = static_cast<waybar::modules::Network *>(data);
|
||||||
auto gnlh = static_cast<genlmsghdr *>(nlmsg_data(nlmsg_hdr(msg)));
|
auto gnlh = static_cast<genlmsghdr *>(nlmsg_data(nlmsg_hdr(msg)));
|
||||||
struct nlattr* tb[NL80211_ATTR_MAX + 1];
|
struct nlattr* tb[NL80211_ATTR_MAX + 1];
|
||||||
struct nlattr* bss[NL80211_BSS_MAX + 1];
|
struct nlattr* bss[NL80211_BSS_MAX + 1];
|
||||||
struct nla_policy bss_policy[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_TSF].type = NLA_U64;
|
||||||
bss_policy[NL80211_BSS_FREQUENCY].type = NLA_U32;
|
bss_policy[NL80211_BSS_FREQUENCY].type = NLA_U32;
|
||||||
bss_policy[NL80211_BSS_BSSID].type = NLA_UNSPEC;
|
bss_policy[NL80211_BSS_BSSID].type = NLA_UNSPEC;
|
||||||
bss_policy[NL80211_BSS_BEACON_INTERVAL].type = NLA_U16;
|
bss_policy[NL80211_BSS_BEACON_INTERVAL].type = NLA_U16;
|
||||||
bss_policy[NL80211_BSS_CAPABILITY].type = NLA_U16;
|
bss_policy[NL80211_BSS_CAPABILITY].type = NLA_U16;
|
||||||
bss_policy[NL80211_BSS_INFORMATION_ELEMENTS].type = NLA_UNSPEC;
|
bss_policy[NL80211_BSS_INFORMATION_ELEMENTS].type = NLA_UNSPEC;
|
||||||
bss_policy[NL80211_BSS_SIGNAL_MBM].type = NLA_U32;
|
bss_policy[NL80211_BSS_SIGNAL_MBM].type = NLA_U32;
|
||||||
bss_policy[NL80211_BSS_SIGNAL_UNSPEC].type = NLA_U8;
|
bss_policy[NL80211_BSS_SIGNAL_UNSPEC].type = NLA_U8;
|
||||||
bss_policy[NL80211_BSS_STATUS].type = NLA_U32;
|
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) {
|
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 (!net->associatedOrJoined(bss)) {
|
|
||||||
return NL_SKIP;
|
|
||||||
}
|
|
||||||
net->parseEssid(bss);
|
|
||||||
net->parseSignal(bss);
|
|
||||||
// TODO(someone): parse quality
|
|
||||||
return NL_SKIP;
|
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 (!net->associatedOrJoined(bss)) {
|
||||||
|
return NL_SKIP;
|
||||||
|
}
|
||||||
|
net->parseEssid(bss);
|
||||||
|
net->parseSignal(bss);
|
||||||
|
// TODO(someone): parse quality
|
||||||
|
return NL_SKIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::modules::Network::parseEssid(struct nlattr **bss)
|
void waybar::modules::Network::parseEssid(struct nlattr **bss)
|
||||||
|
@ -317,62 +337,47 @@ void waybar::modules::Network::parseEssid(struct nlattr **bss)
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::modules::Network::parseSignal(struct nlattr **bss) {
|
void waybar::modules::Network::parseSignal(struct nlattr **bss) {
|
||||||
if (bss[NL80211_BSS_SIGNAL_MBM] != nullptr) {
|
if (bss[NL80211_BSS_SIGNAL_MBM] != nullptr) {
|
||||||
// signalstrength in dBm
|
// signalstrength in dBm
|
||||||
signal_strength_dbm_ =
|
signal_strength_dbm_ =
|
||||||
static_cast<int>(nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM])) / 100;
|
static_cast<int>(nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM])) / 100;
|
||||||
|
|
||||||
// WiFi-hardware usually operates in the range -90 to -20dBm.
|
// WiFi-hardware usually operates in the range -90 to -20dBm.
|
||||||
const int hardwareMax = -20;
|
const int hardwareMax = -20;
|
||||||
const int hardwareMin = -90;
|
const int hardwareMin = -90;
|
||||||
signal_strength_ = ((signal_strength_dbm_ - hardwareMin)
|
signal_strength_ = ((signal_strength_dbm_ - hardwareMin)
|
||||||
/ double{hardwareMax - hardwareMin}) * 100;
|
/ double{hardwareMax - hardwareMin}) * 100;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool waybar::modules::Network::associatedOrJoined(struct nlattr** bss)
|
bool waybar::modules::Network::associatedOrJoined(struct nlattr** bss)
|
||||||
{
|
{
|
||||||
if (bss[NL80211_BSS_STATUS] == nullptr) {
|
if (bss[NL80211_BSS_STATUS] == nullptr) {
|
||||||
return false;
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto waybar::modules::Network::getInfo() -> void
|
auto waybar::modules::Network::getInfo() -> void
|
||||||
{
|
{
|
||||||
struct nl_sock *sk = nl_socket_alloc();
|
struct nl_msg* nl_msg = nlmsg_alloc();
|
||||||
if (genl_connect(sk) != 0) {
|
if (nl_msg == nullptr) {
|
||||||
nl_socket_free(sk);
|
nl_socket_free(sk_);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, scanCb, this) < 0) {
|
if (genlmsg_put(nl_msg, NL_AUTO_PORT, NL_AUTO_SEQ, nl80211_id_, 0, NLM_F_DUMP,
|
||||||
nl_socket_free(sk);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const int nl80211_id = genl_ctrl_resolve(sk, "nl80211");
|
|
||||||
if (nl80211_id < 0) {
|
|
||||||
nl_socket_free(sk);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
struct nl_msg *msg = nlmsg_alloc();
|
|
||||||
if (msg == nullptr) {
|
|
||||||
nl_socket_free(sk);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, nl80211_id, 0, NLM_F_DUMP,
|
|
||||||
NL80211_CMD_GET_SCAN, 0) == nullptr
|
NL80211_CMD_GET_SCAN, 0) == nullptr
|
||||||
|| nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifid_) < 0) {
|
|| nla_put_u32(nl_msg, NL80211_ATTR_IFINDEX, ifid_) < 0) {
|
||||||
nlmsg_free(msg);
|
nlmsg_free(nl_msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
nl_send_sync(sk, msg);
|
nl_send_sync(sk_, nl_msg);
|
||||||
nl_socket_free(sk);
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue