mirror of
https://github.com/systemd/systemd.git
synced 2024-12-26 03:22:00 +03:00
Merge pull request #13828 from keszybz/networkctl-print-wlan
networkctl support for ssid and bssid
This commit is contained in:
commit
6f3ad94590
@ -21,6 +21,7 @@
|
||||
#include "bus-error.h"
|
||||
#include "bus-util.h"
|
||||
#include "device-util.h"
|
||||
#include "escape.h"
|
||||
#include "ether-addr-util.h"
|
||||
#include "ethtool-util.h"
|
||||
#include "fd-util.h"
|
||||
@ -46,10 +47,14 @@
|
||||
#include "strxcpyx.h"
|
||||
#include "terminal-util.h"
|
||||
#include "verbs.h"
|
||||
#include "wifi-util.h"
|
||||
|
||||
/* Kernel defines MODULE_NAME_LEN as 64 - sizeof(unsigned long). So, 64 is enough. */
|
||||
#define NETDEV_KIND_MAX 64
|
||||
|
||||
/* use 128 kB for receive socket kernel queue, we shouldn't need more here */
|
||||
#define RCVBUF_SIZE (128*1024)
|
||||
|
||||
static PagerFlags arg_pager_flags = 0;
|
||||
static bool arg_legend = true;
|
||||
static bool arg_all = false;
|
||||
@ -76,11 +81,12 @@ static char *link_get_type_string(unsigned short iftype, sd_device *d) {
|
||||
return p;
|
||||
}
|
||||
|
||||
static void operational_state_to_color(const char *state, const char **on, const char **off) {
|
||||
static void operational_state_to_color(const char *name, const char *state, const char **on, const char **off) {
|
||||
assert(on);
|
||||
assert(off);
|
||||
|
||||
if (STRPTR_IN_SET(state, "routable", "enslaved")) {
|
||||
if (STRPTR_IN_SET(state, "routable", "enslaved") ||
|
||||
(streq_ptr(name, "lo") && streq_ptr(state, "carrier"))) {
|
||||
*on = ansi_highlight_green();
|
||||
*off = ansi_normal();
|
||||
} else if (streq_ptr(state, "degraded")) {
|
||||
@ -124,6 +130,7 @@ typedef struct VxLanInfo {
|
||||
typedef struct LinkInfo {
|
||||
char name[IFNAMSIZ+1];
|
||||
char netdev_kind[NETDEV_KIND_MAX];
|
||||
sd_device *sd_device;
|
||||
int ifindex;
|
||||
unsigned short iftype;
|
||||
struct ether_addr mac_address;
|
||||
@ -159,6 +166,10 @@ typedef struct LinkInfo {
|
||||
Duplex duplex;
|
||||
NetDevPort port;
|
||||
|
||||
/* wlan info */
|
||||
char *ssid;
|
||||
struct ether_addr bssid;
|
||||
|
||||
bool has_mac_address:1;
|
||||
bool has_tx_queues:1;
|
||||
bool has_rx_queues:1;
|
||||
@ -166,12 +177,25 @@ typedef struct LinkInfo {
|
||||
bool has_stats:1;
|
||||
bool has_bitrates:1;
|
||||
bool has_ethtool_link_info:1;
|
||||
bool has_wlan_link_info:1;
|
||||
|
||||
bool needs_freeing:1;
|
||||
} LinkInfo;
|
||||
|
||||
static int link_info_compare(const LinkInfo *a, const LinkInfo *b) {
|
||||
return CMP(a->ifindex, b->ifindex);
|
||||
}
|
||||
|
||||
static const LinkInfo* link_info_array_free(LinkInfo *array) {
|
||||
for (unsigned i = 0; array && array[i].needs_freeing; i++) {
|
||||
sd_device_unref(array[i].sd_device);
|
||||
free(array[i].ssid);
|
||||
}
|
||||
|
||||
return mfree(array);
|
||||
}
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(LinkInfo*, link_info_array_free);
|
||||
|
||||
static int decode_netdev(sd_netlink_message *m, LinkInfo *info) {
|
||||
const char *received_kind;
|
||||
int r;
|
||||
@ -348,9 +372,47 @@ static int acquire_link_bitrates(sd_bus *bus, LinkInfo *link) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void acquire_ether_link_info(int *fd, LinkInfo *link) {
|
||||
if (ethtool_get_link_info(fd, link->name,
|
||||
&link->autonegotiation,
|
||||
&link->speed,
|
||||
&link->duplex,
|
||||
&link->port) >= 0)
|
||||
link->has_ethtool_link_info = true;
|
||||
}
|
||||
|
||||
static void acquire_wlan_link_info(LinkInfo *link) {
|
||||
_cleanup_(sd_netlink_unrefp) sd_netlink *genl = NULL;
|
||||
const char *type = NULL;
|
||||
int r, k;
|
||||
|
||||
if (link->sd_device)
|
||||
(void) sd_device_get_devtype(link->sd_device, &type);
|
||||
if (!streq_ptr(type, "wlan"))
|
||||
return;
|
||||
|
||||
r = sd_genl_socket_open(&genl);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to open generic netlink socket: %m");
|
||||
return;
|
||||
}
|
||||
|
||||
(void) sd_netlink_inc_rcvbuf(genl, RCVBUF_SIZE);
|
||||
|
||||
r = wifi_get_ssid(genl, link->ifindex, &link->ssid);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "%s: failed to query ssid: %m", link->name);
|
||||
|
||||
k = wifi_get_bssid(genl, link->ifindex, &link->bssid);
|
||||
if (k < 0)
|
||||
log_debug_errno(k, "%s: failed to query bssid: %m", link->name);
|
||||
|
||||
link->has_wlan_link_info = r > 0 || k > 0;
|
||||
}
|
||||
|
||||
static int acquire_link_info(sd_bus *bus, sd_netlink *rtnl, char **patterns, LinkInfo **ret) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
|
||||
_cleanup_free_ LinkInfo *links = NULL;
|
||||
_cleanup_(link_info_array_freep) LinkInfo *links = NULL;
|
||||
_cleanup_close_ int fd = -1;
|
||||
size_t allocated = 0, c = 0, j;
|
||||
sd_netlink_message *i;
|
||||
@ -372,7 +434,7 @@ static int acquire_link_info(sd_bus *bus, sd_netlink *rtnl, char **patterns, Lin
|
||||
return log_error_errno(r, "Failed to enumerate links: %m");
|
||||
|
||||
for (i = reply; i; i = sd_netlink_message_next(i)) {
|
||||
if (!GREEDY_REALLOC0(links, allocated, c+1))
|
||||
if (!GREEDY_REALLOC0(links, allocated, c + 2)) /* We keep one trailing one as marker */
|
||||
return -ENOMEM;
|
||||
|
||||
r = decode_link(i, links + c, patterns);
|
||||
@ -381,11 +443,14 @@ static int acquire_link_info(sd_bus *bus, sd_netlink *rtnl, char **patterns, Lin
|
||||
if (r == 0)
|
||||
continue;
|
||||
|
||||
r = ethtool_get_link_info(&fd, links[c].name,
|
||||
&links[c].autonegotiation, &links[c].speed,
|
||||
&links[c].duplex, &links[c].port);
|
||||
if (r >= 0)
|
||||
links[c].has_ethtool_link_info = true;
|
||||
links[c].needs_freeing = true;
|
||||
|
||||
char devid[2 + DECIMAL_STR_MAX(int)];
|
||||
xsprintf(devid, "n%i", links[c].ifindex);
|
||||
(void) sd_device_new_from_device_id(&links[c].sd_device, devid);
|
||||
|
||||
acquire_ether_link_info(&fd, &links[c]);
|
||||
acquire_wlan_link_info(&links[c]);
|
||||
|
||||
c++;
|
||||
}
|
||||
@ -403,7 +468,7 @@ static int acquire_link_info(sd_bus *bus, sd_netlink *rtnl, char **patterns, Lin
|
||||
|
||||
static int list_links(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
|
||||
_cleanup_free_ LinkInfo *links = NULL;
|
||||
_cleanup_(link_info_array_freep) LinkInfo *links = NULL;
|
||||
_cleanup_(table_unrefp) Table *table = NULL;
|
||||
TableCell *cell;
|
||||
int c, i, r;
|
||||
@ -435,24 +500,19 @@ static int list_links(int argc, char *argv[], void *userdata) {
|
||||
|
||||
for (i = 0; i < c; i++) {
|
||||
_cleanup_free_ char *setup_state = NULL, *operational_state = NULL;
|
||||
_cleanup_(sd_device_unrefp) sd_device *d = NULL;
|
||||
const char *on_color_operational, *off_color_operational,
|
||||
*on_color_setup, *off_color_setup;
|
||||
char devid[2 + DECIMAL_STR_MAX(int)];
|
||||
_cleanup_free_ char *t = NULL;
|
||||
|
||||
(void) sd_network_link_get_operational_state(links[i].ifindex, &operational_state);
|
||||
operational_state_to_color(operational_state, &on_color_operational, &off_color_operational);
|
||||
operational_state_to_color(links[i].name, operational_state, &on_color_operational, &off_color_operational);
|
||||
|
||||
r = sd_network_link_get_setup_state(links[i].ifindex, &setup_state);
|
||||
if (r == -ENODATA) /* If there's no info available about this iface, it's unmanaged by networkd */
|
||||
setup_state = strdup("unmanaged");
|
||||
setup_state_to_color(setup_state, &on_color_setup, &off_color_setup);
|
||||
|
||||
xsprintf(devid, "n%i", links[i].ifindex);
|
||||
(void) sd_device_new_from_device_id(&d, devid);
|
||||
|
||||
t = link_get_type_string(links[i].iftype, d);
|
||||
t = link_get_type_string(links[i].iftype, links[i].sd_device);
|
||||
|
||||
r = table_add_many(table,
|
||||
TABLE_INT, links[i].ifindex,
|
||||
@ -998,8 +1058,6 @@ static int link_status_one(
|
||||
|
||||
_cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **search_domains = NULL, **route_domains = NULL;
|
||||
_cleanup_free_ char *setup_state = NULL, *operational_state = NULL, *tz = NULL;
|
||||
_cleanup_(sd_device_unrefp) sd_device *d = NULL;
|
||||
char devid[2 + DECIMAL_STR_MAX(int)];
|
||||
_cleanup_free_ char *t = NULL, *network = NULL;
|
||||
const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL, *link = NULL;
|
||||
const char *on_color_operational, *off_color_operational,
|
||||
@ -1013,7 +1071,7 @@ static int link_status_one(
|
||||
assert(info);
|
||||
|
||||
(void) sd_network_link_get_operational_state(info->ifindex, &operational_state);
|
||||
operational_state_to_color(operational_state, &on_color_operational, &off_color_operational);
|
||||
operational_state_to_color(info->name, operational_state, &on_color_operational, &off_color_operational);
|
||||
|
||||
r = sd_network_link_get_setup_state(info->ifindex, &setup_state);
|
||||
if (r == -ENODATA) /* If there's no info available about this iface, it's unmanaged by networkd */
|
||||
@ -1025,23 +1083,19 @@ static int link_status_one(
|
||||
(void) sd_network_link_get_route_domains(info->ifindex, &route_domains);
|
||||
(void) sd_network_link_get_ntp(info->ifindex, &ntp);
|
||||
|
||||
xsprintf(devid, "n%i", info->ifindex);
|
||||
if (info->sd_device) {
|
||||
(void) sd_device_get_property_value(info->sd_device, "ID_NET_LINK_FILE", &link);
|
||||
(void) sd_device_get_property_value(info->sd_device, "ID_NET_DRIVER", &driver);
|
||||
(void) sd_device_get_property_value(info->sd_device, "ID_PATH", &path);
|
||||
|
||||
(void) sd_device_new_from_device_id(&d, devid);
|
||||
if (sd_device_get_property_value(info->sd_device, "ID_VENDOR_FROM_DATABASE", &vendor) < 0)
|
||||
(void) sd_device_get_property_value(info->sd_device, "ID_VENDOR", &vendor);
|
||||
|
||||
if (d) {
|
||||
(void) sd_device_get_property_value(d, "ID_NET_LINK_FILE", &link);
|
||||
(void) sd_device_get_property_value(d, "ID_NET_DRIVER", &driver);
|
||||
(void) sd_device_get_property_value(d, "ID_PATH", &path);
|
||||
|
||||
if (sd_device_get_property_value(d, "ID_VENDOR_FROM_DATABASE", &vendor) < 0)
|
||||
(void) sd_device_get_property_value(d, "ID_VENDOR", &vendor);
|
||||
|
||||
if (sd_device_get_property_value(d, "ID_MODEL_FROM_DATABASE", &model) < 0)
|
||||
(void) sd_device_get_property_value(d, "ID_MODEL", &model);
|
||||
if (sd_device_get_property_value(info->sd_device, "ID_MODEL_FROM_DATABASE", &model) < 0)
|
||||
(void) sd_device_get_property_value(info->sd_device, "ID_MODEL", &model);
|
||||
}
|
||||
|
||||
t = link_get_type_string(info->iftype, d);
|
||||
t = link_get_type_string(info->iftype, info->sd_device);
|
||||
|
||||
(void) sd_network_link_get_network_file(info->ifindex, &network);
|
||||
|
||||
@ -1244,6 +1298,26 @@ static int link_status_one(
|
||||
}
|
||||
}
|
||||
|
||||
if (info->has_wlan_link_info) {
|
||||
_cleanup_free_ char *esc = NULL;
|
||||
char buf[ETHER_ADDR_TO_STRING_MAX];
|
||||
|
||||
r = table_add_many(table,
|
||||
TABLE_EMPTY,
|
||||
TABLE_STRING, "WiFi access point:");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (info->ssid)
|
||||
esc = cescape(info->ssid);
|
||||
|
||||
r = table_add_cell_stringf(table, NULL, "%s (%s)",
|
||||
strnull(esc),
|
||||
ether_addr_to_string(&info->bssid, buf));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (info->has_bitrates) {
|
||||
char tx[FORMAT_BYTES_MAX], rx[FORMAT_BYTES_MAX];
|
||||
|
||||
@ -1368,7 +1442,7 @@ static int system_status(sd_netlink *rtnl, sd_hwdb *hwdb) {
|
||||
assert(rtnl);
|
||||
|
||||
(void) sd_network_get_operational_state(&operational_state);
|
||||
operational_state_to_color(operational_state, &on_color_operational, &off_color_operational);
|
||||
operational_state_to_color(NULL, operational_state, &on_color_operational, &off_color_operational);
|
||||
|
||||
table = table_new("dot", "key", "value");
|
||||
if (!table)
|
||||
@ -1424,7 +1498,7 @@ static int link_status(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
||||
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
|
||||
_cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL;
|
||||
_cleanup_free_ LinkInfo *links = NULL;
|
||||
_cleanup_(link_info_array_freep) LinkInfo *links = NULL;
|
||||
int r, c, i;
|
||||
|
||||
(void) pager_open(arg_pager_flags);
|
||||
@ -1512,7 +1586,7 @@ static void lldp_capabilities_legend(uint16_t x) {
|
||||
|
||||
static int link_lldp_status(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
|
||||
_cleanup_free_ LinkInfo *links = NULL;
|
||||
_cleanup_(link_info_array_freep) LinkInfo *links = NULL;
|
||||
_cleanup_(table_unrefp) Table *table = NULL;
|
||||
int i, r, c, m = 0;
|
||||
uint16_t all = 0;
|
||||
|
@ -12,101 +12,9 @@
|
||||
#include "networkd-manager.h"
|
||||
#include "networkd-wifi.h"
|
||||
#include "string-util.h"
|
||||
|
||||
static int wifi_get_ssid(Link *link) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL;
|
||||
_cleanup_free_ char *ssid = NULL;
|
||||
sd_genl_family family;
|
||||
int r;
|
||||
|
||||
r = sd_genl_message_new(link->manager->genl, SD_GENL_NL80211, NL80211_CMD_GET_INTERFACE, &m);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Failed to create generic netlink message: %m");
|
||||
|
||||
r = sd_netlink_message_append_u32(m, NL80211_ATTR_IFINDEX, link->ifindex);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not append NL80211_ATTR_IFINDEX attribute: %m");
|
||||
|
||||
r = sd_netlink_call(link->manager->genl, m, 0, &reply);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Failed to request information about wifi interface: %m");
|
||||
if (!reply)
|
||||
return 0;
|
||||
|
||||
r = sd_netlink_message_get_errno(reply);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to get information about wifi interface: %m");
|
||||
|
||||
r = sd_genl_message_get_family(link->manager->genl, reply, &family);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to determine genl family: %m");
|
||||
if (family != SD_GENL_NL80211) {
|
||||
log_link_debug(link, "Received message of unexpected genl family %u, ignoring.", family);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_netlink_message_read_string_strdup(reply, NL80211_ATTR_SSID, &ssid);
|
||||
if (r < 0 && r != -ENODATA)
|
||||
return log_link_warning_errno(link, r, "Failed to get NL80211_ATTR_SSID attribute: %m");
|
||||
|
||||
free_and_replace(link->ssid, ssid);
|
||||
return r == -ENODATA ? 0 : 1;
|
||||
}
|
||||
|
||||
static int wifi_get_bssid(Link *link) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL;
|
||||
struct ether_addr mac = {};
|
||||
sd_genl_family family;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
assert(link->manager->genl);
|
||||
|
||||
r = sd_genl_message_new(link->manager->genl, SD_GENL_NL80211, NL80211_CMD_GET_STATION, &m);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Failed to create generic netlink message: %m");
|
||||
|
||||
r = sd_netlink_message_set_flags(m, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Failed to set dump flag: %m");
|
||||
|
||||
r = sd_netlink_message_append_u32(m, NL80211_ATTR_IFINDEX, link->ifindex);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not append NL80211_ATTR_IFINDEX attribute: %m");
|
||||
|
||||
r = sd_netlink_call(link->manager->genl, m, 0, &reply);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Failed to request information about wifi station: %m");
|
||||
if (!reply)
|
||||
return 0;
|
||||
|
||||
r = sd_netlink_message_get_errno(reply);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Failed to get information about wifi station: %m");
|
||||
|
||||
r = sd_genl_message_get_family(link->manager->genl, reply, &family);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to determine genl family: %m");
|
||||
if (family != SD_GENL_NL80211) {
|
||||
log_link_debug(link, "Received message of unexpected genl family %u, ignoring.", family);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_netlink_message_read_ether_addr(reply, NL80211_ATTR_MAC, &mac);
|
||||
if (r < 0 && r != -ENODATA)
|
||||
return log_link_warning_errno(link, r, "Failed to get NL80211_ATTR_MAC attribute: %m");
|
||||
|
||||
r = memcmp(&link->bssid, &mac, sizeof(mac));
|
||||
if (r == 0)
|
||||
return 0;
|
||||
|
||||
memcpy(&link->bssid, &mac, sizeof(mac));
|
||||
return 1;
|
||||
}
|
||||
#include "wifi-util.h"
|
||||
|
||||
int wifi_get_info(Link *link) {
|
||||
char buf[ETHER_ADDR_TO_STRING_MAX];
|
||||
const char *type;
|
||||
int r, s;
|
||||
|
||||
@ -124,15 +32,24 @@ int wifi_get_info(Link *link) {
|
||||
if (!streq(type, "wlan"))
|
||||
return 0;
|
||||
|
||||
r = wifi_get_ssid(link);
|
||||
_cleanup_free_ char *ssid = NULL;
|
||||
r = wifi_get_ssid(link->manager->genl, link->ifindex, &ssid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0 && streq_ptr(link->ssid, ssid))
|
||||
r = 0;
|
||||
free_and_replace(link->ssid, ssid);
|
||||
|
||||
s = wifi_get_bssid(link);
|
||||
struct ether_addr old_bssid = link->bssid;
|
||||
s = wifi_get_bssid(link->manager->genl, link->ifindex, &link->bssid);
|
||||
if (s < 0)
|
||||
return s;
|
||||
if (s > 0 && memcmp(&old_bssid, &link->bssid, sizeof old_bssid) == 0)
|
||||
s = 0;
|
||||
|
||||
if (r > 0 || s > 0) {
|
||||
char buf[ETHER_ADDR_TO_STRING_MAX];
|
||||
|
||||
if (link->ssid)
|
||||
log_link_info(link, "Connected WiFi access point: %s (%s)",
|
||||
link->ssid, ether_addr_to_string(&link->bssid, buf));
|
||||
|
@ -189,6 +189,8 @@ shared_sources = files('''
|
||||
watchdog.h
|
||||
web-util.c
|
||||
web-util.h
|
||||
wifi-util.c
|
||||
wifi-util.h
|
||||
xml.c
|
||||
xml.h
|
||||
'''.split())
|
||||
|
90
src/shared/wifi-util.c
Normal file
90
src/shared/wifi-util.c
Normal file
@ -0,0 +1,90 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include <net/ethernet.h>
|
||||
#include <linux/nl80211.h>
|
||||
|
||||
#include "sd-bus.h"
|
||||
|
||||
#include "log.h"
|
||||
#include "netlink-util.h"
|
||||
#include "wifi-util.h"
|
||||
|
||||
int wifi_get_ssid(sd_netlink *genl, int ifindex, char **ssid) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL;
|
||||
sd_genl_family family;
|
||||
int r;
|
||||
|
||||
r = sd_genl_message_new(genl, SD_GENL_NL80211, NL80211_CMD_GET_INTERFACE, &m);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to create generic netlink message: %m");
|
||||
|
||||
r = sd_netlink_message_append_u32(m, NL80211_ATTR_IFINDEX, ifindex);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Could not append NL80211_ATTR_IFINDEX attribute: %m");
|
||||
|
||||
r = sd_netlink_call(genl, m, 0, &reply);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to request information about wifi interface %d: %m", ifindex);
|
||||
if (!reply)
|
||||
return 0;
|
||||
|
||||
r = sd_netlink_message_get_errno(reply);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to get information about wifi interface %d: %m", ifindex);
|
||||
|
||||
r = sd_genl_message_get_family(genl, reply, &family);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to determine genl family: %m");
|
||||
if (family != SD_GENL_NL80211) {
|
||||
log_debug("Received message of unexpected genl family %u, ignoring.", family);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_netlink_message_read_string_strdup(reply, NL80211_ATTR_SSID, ssid);
|
||||
if (r < 0 && r != -ENODATA)
|
||||
return log_debug_errno(r, "Failed to get NL80211_ATTR_SSID attribute: %m");
|
||||
|
||||
return r == -ENODATA ? 0 : 1;
|
||||
}
|
||||
|
||||
int wifi_get_bssid(sd_netlink *genl, int ifindex, struct ether_addr *bssid) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL;
|
||||
sd_genl_family family;
|
||||
int r;
|
||||
|
||||
r = sd_genl_message_new(genl, SD_GENL_NL80211, NL80211_CMD_GET_STATION, &m);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to create generic netlink message: %m");
|
||||
|
||||
r = sd_netlink_message_set_flags(m, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to set dump flag: %m");
|
||||
|
||||
r = sd_netlink_message_append_u32(m, NL80211_ATTR_IFINDEX, ifindex);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Could not append NL80211_ATTR_IFINDEX attribute: %m");
|
||||
|
||||
r = sd_netlink_call(genl, m, 0, &reply);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to request information about wifi station: %m");
|
||||
if (!reply)
|
||||
return 0;
|
||||
|
||||
r = sd_netlink_message_get_errno(reply);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to get information about wifi station: %m");
|
||||
|
||||
r = sd_genl_message_get_family(genl, reply, &family);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to determine genl family: %m");
|
||||
if (family != SD_GENL_NL80211) {
|
||||
log_debug("Received message of unexpected genl family %u, ignoring.", family);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_netlink_message_read_ether_addr(reply, NL80211_ATTR_MAC, bssid);
|
||||
if (r < 0 && r != -ENODATA)
|
||||
return log_debug_errno(r, "Failed to get NL80211_ATTR_MAC attribute: %m");
|
||||
|
||||
return r == -ENODATA ? 0 : 1;
|
||||
}
|
8
src/shared/wifi-util.h
Normal file
8
src/shared/wifi-util.h
Normal file
@ -0,0 +1,8 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "netlink-util.h"
|
||||
|
||||
int wifi_get_ssid(sd_netlink *genl, int ifindex, char **ssid);
|
||||
int wifi_get_bssid(sd_netlink *genl, int ifindex, struct ether_addr *bssid);
|
Loading…
Reference in New Issue
Block a user