Compare commits

..

7 Commits

Author SHA1 Message Date
Yu Watanabe 6f3ad94590
Merge pull request #13828 from keszybz/networkctl-print-wlan
networkctl support for ssid and bssid
2019-10-24 11:12:39 +09:00
Michal Suchanek 14cd12b3d5 udev/cdrom_id: Do not open CD-rom in exclusive mode.
When you have a CD automunt solution that talks directly to the kernel
independently of udev it races with cdrom_id for exclusive access to the
device failing unpredictably.

The whole is_mounted function in cdrom_id is broken: there is no saying
what happens between calling is_mounted and opening the device.

Hence assume that the device can be mounted asynchronously at any time,
do not use exclusive access, and do away with is_mouted.

Signed-off-by: Michal Suchanek <msuchanek@suse.de>
2019-10-24 00:09:18 +02:00
Zbigniew Jędrzejewski-Szmek 8d07de2534 networkctl: print ssid and bssid 2019-10-24 00:02:43 +02:00
Zbigniew Jędrzejewski-Szmek 172353b110 networkctl: create the sd_device structure just once
This is mostly in preparation for future changes: a proper freeing function
is now called on the LinkInfo items.
2019-10-24 00:02:43 +02:00
Zbigniew Jędrzejewski-Szmek b492aea093 network: split out functions to get ssid and bssid 2019-10-24 00:02:41 +02:00
Zbigniew Jędrzejewski-Szmek 516e9c802f networkctl: split out helper function 2019-10-23 12:29:04 +02:00
Zbigniew Jędrzejewski-Szmek ceb366df29 networkctl: show carrier in green for loopback iface
We don't ever expect anything different, so let's hightlight
that carrier in this case is OK.
2019-10-23 11:10:32 +02:00
6 changed files with 223 additions and 154 deletions

View File

@ -21,6 +21,7 @@
#include "bus-error.h" #include "bus-error.h"
#include "bus-util.h" #include "bus-util.h"
#include "device-util.h" #include "device-util.h"
#include "escape.h"
#include "ether-addr-util.h" #include "ether-addr-util.h"
#include "ethtool-util.h" #include "ethtool-util.h"
#include "fd-util.h" #include "fd-util.h"
@ -46,10 +47,14 @@
#include "strxcpyx.h" #include "strxcpyx.h"
#include "terminal-util.h" #include "terminal-util.h"
#include "verbs.h" #include "verbs.h"
#include "wifi-util.h"
/* Kernel defines MODULE_NAME_LEN as 64 - sizeof(unsigned long). So, 64 is enough. */ /* Kernel defines MODULE_NAME_LEN as 64 - sizeof(unsigned long). So, 64 is enough. */
#define NETDEV_KIND_MAX 64 #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 PagerFlags arg_pager_flags = 0;
static bool arg_legend = true; static bool arg_legend = true;
static bool arg_all = false; static bool arg_all = false;
@ -76,11 +81,12 @@ static char *link_get_type_string(unsigned short iftype, sd_device *d) {
return p; 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(on);
assert(off); 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(); *on = ansi_highlight_green();
*off = ansi_normal(); *off = ansi_normal();
} else if (streq_ptr(state, "degraded")) { } else if (streq_ptr(state, "degraded")) {
@ -124,6 +130,7 @@ typedef struct VxLanInfo {
typedef struct LinkInfo { typedef struct LinkInfo {
char name[IFNAMSIZ+1]; char name[IFNAMSIZ+1];
char netdev_kind[NETDEV_KIND_MAX]; char netdev_kind[NETDEV_KIND_MAX];
sd_device *sd_device;
int ifindex; int ifindex;
unsigned short iftype; unsigned short iftype;
struct ether_addr mac_address; struct ether_addr mac_address;
@ -159,6 +166,10 @@ typedef struct LinkInfo {
Duplex duplex; Duplex duplex;
NetDevPort port; NetDevPort port;
/* wlan info */
char *ssid;
struct ether_addr bssid;
bool has_mac_address:1; bool has_mac_address:1;
bool has_tx_queues:1; bool has_tx_queues:1;
bool has_rx_queues:1; bool has_rx_queues:1;
@ -166,12 +177,25 @@ typedef struct LinkInfo {
bool has_stats:1; bool has_stats:1;
bool has_bitrates:1; bool has_bitrates:1;
bool has_ethtool_link_info:1; bool has_ethtool_link_info:1;
bool has_wlan_link_info:1;
bool needs_freeing:1;
} LinkInfo; } LinkInfo;
static int link_info_compare(const LinkInfo *a, const LinkInfo *b) { static int link_info_compare(const LinkInfo *a, const LinkInfo *b) {
return CMP(a->ifindex, b->ifindex); 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) { static int decode_netdev(sd_netlink_message *m, LinkInfo *info) {
const char *received_kind; const char *received_kind;
int r; int r;
@ -348,9 +372,47 @@ static int acquire_link_bitrates(sd_bus *bus, LinkInfo *link) {
return 0; 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) { 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_(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; _cleanup_close_ int fd = -1;
size_t allocated = 0, c = 0, j; size_t allocated = 0, c = 0, j;
sd_netlink_message *i; 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"); return log_error_errno(r, "Failed to enumerate links: %m");
for (i = reply; i; i = sd_netlink_message_next(i)) { 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; return -ENOMEM;
r = decode_link(i, links + c, patterns); 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) if (r == 0)
continue; continue;
r = ethtool_get_link_info(&fd, links[c].name, links[c].needs_freeing = true;
&links[c].autonegotiation, &links[c].speed,
&links[c].duplex, &links[c].port); char devid[2 + DECIMAL_STR_MAX(int)];
if (r >= 0) xsprintf(devid, "n%i", links[c].ifindex);
links[c].has_ethtool_link_info = true; (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++; 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) { static int list_links(int argc, char *argv[], void *userdata) {
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; _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; _cleanup_(table_unrefp) Table *table = NULL;
TableCell *cell; TableCell *cell;
int c, i, r; int c, i, r;
@ -435,24 +500,19 @@ static int list_links(int argc, char *argv[], void *userdata) {
for (i = 0; i < c; i++) { for (i = 0; i < c; i++) {
_cleanup_free_ char *setup_state = NULL, *operational_state = NULL; _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, const char *on_color_operational, *off_color_operational,
*on_color_setup, *off_color_setup; *on_color_setup, *off_color_setup;
char devid[2 + DECIMAL_STR_MAX(int)];
_cleanup_free_ char *t = NULL; _cleanup_free_ char *t = NULL;
(void) sd_network_link_get_operational_state(links[i].ifindex, &operational_state); (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); 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 */ if (r == -ENODATA) /* If there's no info available about this iface, it's unmanaged by networkd */
setup_state = strdup("unmanaged"); setup_state = strdup("unmanaged");
setup_state_to_color(setup_state, &on_color_setup, &off_color_setup); setup_state_to_color(setup_state, &on_color_setup, &off_color_setup);
xsprintf(devid, "n%i", links[i].ifindex); t = link_get_type_string(links[i].iftype, links[i].sd_device);
(void) sd_device_new_from_device_id(&d, devid);
t = link_get_type_string(links[i].iftype, d);
r = table_add_many(table, r = table_add_many(table,
TABLE_INT, links[i].ifindex, 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_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_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; _cleanup_free_ char *t = NULL, *network = NULL;
const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL, *link = NULL; const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL, *link = NULL;
const char *on_color_operational, *off_color_operational, const char *on_color_operational, *off_color_operational,
@ -1013,7 +1071,7 @@ static int link_status_one(
assert(info); assert(info);
(void) sd_network_link_get_operational_state(info->ifindex, &operational_state); (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); 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 */ 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_route_domains(info->ifindex, &route_domains);
(void) sd_network_link_get_ntp(info->ifindex, &ntp); (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) { if (sd_device_get_property_value(info->sd_device, "ID_MODEL_FROM_DATABASE", &model) < 0)
(void) sd_device_get_property_value(d, "ID_NET_LINK_FILE", &link); (void) sd_device_get_property_value(info->sd_device, "ID_MODEL", &model);
(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);
} }
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); (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) { if (info->has_bitrates) {
char tx[FORMAT_BYTES_MAX], rx[FORMAT_BYTES_MAX]; 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); assert(rtnl);
(void) sd_network_get_operational_state(&operational_state); (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"); table = table_new("dot", "key", "value");
if (!table) 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_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
_cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = 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; int r, c, i;
(void) pager_open(arg_pager_flags); (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) { static int link_lldp_status(int argc, char *argv[], void *userdata) {
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; _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; _cleanup_(table_unrefp) Table *table = NULL;
int i, r, c, m = 0; int i, r, c, m = 0;
uint16_t all = 0; uint16_t all = 0;

View File

@ -12,101 +12,9 @@
#include "networkd-manager.h" #include "networkd-manager.h"
#include "networkd-wifi.h" #include "networkd-wifi.h"
#include "string-util.h" #include "string-util.h"
#include "wifi-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;
}
int wifi_get_info(Link *link) { int wifi_get_info(Link *link) {
char buf[ETHER_ADDR_TO_STRING_MAX];
const char *type; const char *type;
int r, s; int r, s;
@ -124,15 +32,24 @@ int wifi_get_info(Link *link) {
if (!streq(type, "wlan")) if (!streq(type, "wlan"))
return 0; 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) if (r < 0)
return r; 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) if (s < 0)
return s; return s;
if (s > 0 && memcmp(&old_bssid, &link->bssid, sizeof old_bssid) == 0)
s = 0;
if (r > 0 || s > 0) { if (r > 0 || s > 0) {
char buf[ETHER_ADDR_TO_STRING_MAX];
if (link->ssid) if (link->ssid)
log_link_info(link, "Connected WiFi access point: %s (%s)", log_link_info(link, "Connected WiFi access point: %s (%s)",
link->ssid, ether_addr_to_string(&link->bssid, buf)); link->ssid, ether_addr_to_string(&link->bssid, buf));

View File

@ -189,6 +189,8 @@ shared_sources = files('''
watchdog.h watchdog.h
web-util.c web-util.c
web-util.h web-util.h
wifi-util.c
wifi-util.h
xml.c xml.c
xml.h xml.h
'''.split()) '''.split())

90
src/shared/wifi-util.c Normal file
View 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
View 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);

View File

@ -85,28 +85,6 @@ static unsigned long long int cd_media_session_last_offset;
#define ASC(errcode) (((errcode) >> 8) & 0xFF) #define ASC(errcode) (((errcode) >> 8) & 0xFF)
#define ASCQ(errcode) ((errcode) & 0xFF) #define ASCQ(errcode) ((errcode) & 0xFF)
static bool is_mounted(const char *device) {
struct stat statbuf;
FILE *fp;
int maj, min;
bool mounted = false;
if (stat(device, &statbuf) < 0)
return false;
fp = fopen("/proc/self/mountinfo", "re");
if (!fp)
return false;
while (fscanf(fp, "%*s %*s %i:%i %*[^\n]", &maj, &min) == 2) {
if (makedev(maj, min) == statbuf.st_rdev) {
mounted = true;
break;
}
}
fclose(fp);
return mounted;
}
static void info_scsi_cmd_err(const char *cmd, int err) { static void info_scsi_cmd_err(const char *cmd, int err) {
if (err == -1) if (err == -1)
log_debug("%s failed", cmd); log_debug("%s failed", cmd);
@ -874,7 +852,7 @@ int main(int argc, char *argv[]) {
for (cnt = 20; cnt > 0; cnt--) { for (cnt = 20; cnt > 0; cnt--) {
struct timespec duration; struct timespec duration;
fd = open(node, O_RDONLY|O_NONBLOCK|O_CLOEXEC|(is_mounted(node) ? 0 : O_EXCL)); fd = open(node, O_RDONLY|O_NONBLOCK|O_CLOEXEC);
if (fd >= 0 || errno != EBUSY) if (fd >= 0 || errno != EBUSY)
break; break;
duration.tv_sec = 0; duration.tv_sec = 0;