mirror of
https://github.com/systemd/systemd.git
synced 2024-12-22 17:35:35 +03:00
network: manage WLAN phy
This commit is contained in:
parent
1d4312d5f9
commit
edb69db2b0
@ -143,6 +143,8 @@ sources = files('''
|
||||
networkd-util.h
|
||||
networkd-wifi.c
|
||||
networkd-wifi.h
|
||||
networkd-wiphy.c
|
||||
networkd-wiphy.h
|
||||
tc/cake.c
|
||||
tc/cake.h
|
||||
tc/codel.c
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "networkd-speed-meter.h"
|
||||
#include "networkd-state-file.h"
|
||||
#include "networkd-wifi.h"
|
||||
#include "networkd-wiphy.h"
|
||||
#include "ordered-set.h"
|
||||
#include "path-lookup.h"
|
||||
#include "path-util.h"
|
||||
@ -554,6 +555,9 @@ Manager* manager_free(Manager *m) {
|
||||
|
||||
m->netdevs = hashmap_free_with_destructor(m->netdevs, netdev_unref);
|
||||
|
||||
m->wiphy_by_name = hashmap_free(m->wiphy_by_name);
|
||||
m->wiphy_by_index = hashmap_free_with_destructor(m->wiphy_by_index, wiphy_free);
|
||||
|
||||
ordered_set_free_free(m->address_pools);
|
||||
|
||||
hashmap_free(m->route_table_names_by_number);
|
||||
@ -793,6 +797,20 @@ static int manager_enumerate_nexthop(Manager *m) {
|
||||
return manager_enumerate_internal(m, m->rtnl, req, manager_rtnl_process_nexthop);
|
||||
}
|
||||
|
||||
static int manager_enumerate_nl80211_wiphy(Manager *m) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(m->genl);
|
||||
|
||||
r = sd_genl_message_new(m->genl, NL80211_GENL_NAME, NL80211_CMD_GET_WIPHY, &req);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return manager_enumerate_internal(m, m->genl, req, manager_genl_process_nl80211_wiphy);
|
||||
}
|
||||
|
||||
static int manager_enumerate_nl80211_config(Manager *m) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
|
||||
int r;
|
||||
@ -878,6 +896,12 @@ int manager_enumerate(Manager *m) {
|
||||
else if (r < 0)
|
||||
return log_error_errno(r, "Could not enumerate routing policy rules: %m");
|
||||
|
||||
r = manager_enumerate_nl80211_wiphy(m);
|
||||
if (r == -EOPNOTSUPP)
|
||||
log_debug_errno(r, "Could not enumerate wireless LAN phy, ignoring: %m");
|
||||
else if (r < 0)
|
||||
return log_error_errno(r, "Could not enumerate wireless LAN phy: %m");
|
||||
|
||||
r = manager_enumerate_nl80211_config(m);
|
||||
if (r == -EOPNOTSUPP)
|
||||
log_debug_errno(r, "Could not enumerate wireless LAN interfaces, ignoring: %m");
|
||||
|
@ -84,6 +84,10 @@ struct Manager {
|
||||
Hashmap *route_table_numbers_by_name;
|
||||
Hashmap *route_table_names_by_number;
|
||||
|
||||
/* Wiphy */
|
||||
Hashmap *wiphy_by_index;
|
||||
Hashmap *wiphy_by_name;
|
||||
|
||||
/* For link speed meter */
|
||||
bool use_speed_meter;
|
||||
sd_event_source *speed_meter_event_source;
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "networkd-link.h"
|
||||
#include "networkd-manager.h"
|
||||
#include "networkd-wifi.h"
|
||||
#include "networkd-wiphy.h"
|
||||
#include "string-util.h"
|
||||
#include "wifi-util.h"
|
||||
|
||||
@ -72,6 +73,8 @@ int manager_genl_process_nl80211_config(sd_netlink *genl, sd_netlink_message *me
|
||||
log_debug_errno(r, "nl80211: failed to determine genl message command, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
if (IN_SET(cmd, NL80211_CMD_NEW_WIPHY, NL80211_CMD_DEL_WIPHY))
|
||||
return manager_genl_process_nl80211_wiphy(genl, message, manager);
|
||||
if (!IN_SET(cmd, NL80211_CMD_SET_INTERFACE, NL80211_CMD_NEW_INTERFACE, NL80211_CMD_DEL_INTERFACE)) {
|
||||
log_debug("nl80211: ignoring nl80211 %s(%u) message.",
|
||||
strna(nl80211_cmd_to_string(cmd)), cmd);
|
||||
|
205
src/network/networkd-wiphy.c
Normal file
205
src/network/networkd-wiphy.c
Normal file
@ -0,0 +1,205 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <linux/nl80211.h>
|
||||
|
||||
#include "device-util.h"
|
||||
#include "networkd-manager.h"
|
||||
#include "networkd-wiphy.h"
|
||||
#include "parse-util.h"
|
||||
#include "wifi-util.h"
|
||||
|
||||
Wiphy *wiphy_free(Wiphy *w) {
|
||||
if (!w)
|
||||
return NULL;
|
||||
|
||||
if (w->manager) {
|
||||
hashmap_remove_value(w->manager->wiphy_by_index, UINT32_TO_PTR(w->index), w);
|
||||
if (w->name)
|
||||
hashmap_remove_value(w->manager->wiphy_by_name, w->name, w);
|
||||
}
|
||||
|
||||
free(w->name);
|
||||
return mfree(w);
|
||||
}
|
||||
|
||||
static int wiphy_new(Manager *manager, uint32_t index, Wiphy **ret) {
|
||||
_cleanup_(wiphy_freep) Wiphy *w = NULL;
|
||||
int r;
|
||||
|
||||
assert(manager);
|
||||
|
||||
w = new(Wiphy, 1);
|
||||
if (!w)
|
||||
return -ENOMEM;
|
||||
|
||||
*w = (Wiphy) {
|
||||
.index = index,
|
||||
};
|
||||
|
||||
r = hashmap_ensure_put(&manager->wiphy_by_index, NULL, UINT32_TO_PTR(w->index), w);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
w->manager = manager;
|
||||
|
||||
if (ret)
|
||||
*ret = w;
|
||||
|
||||
TAKE_PTR(w);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wiphy_get_by_index(Manager *manager, uint32_t index, Wiphy **ret) {
|
||||
Wiphy *w;
|
||||
|
||||
assert(manager);
|
||||
|
||||
w = hashmap_get(manager->wiphy_by_index, UINT32_TO_PTR(index));
|
||||
if (!w)
|
||||
return -ENODEV;
|
||||
|
||||
if (ret)
|
||||
*ret = w;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wiphy_get_by_name(Manager *manager, const char *name, Wiphy **ret) {
|
||||
Wiphy *w;
|
||||
|
||||
assert(manager);
|
||||
assert(name);
|
||||
|
||||
w = hashmap_get(manager->wiphy_by_name, name);
|
||||
if (!w)
|
||||
return -ENODEV;
|
||||
|
||||
if (ret)
|
||||
*ret = w;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wiphy_update_name(Wiphy *w, sd_netlink_message *message) {
|
||||
const char *name;
|
||||
int r;
|
||||
|
||||
assert(w);
|
||||
assert(w->manager);
|
||||
assert(message);
|
||||
|
||||
r = sd_netlink_message_read_string(message, NL80211_ATTR_WIPHY_NAME, &name);
|
||||
if (r == -ENODATA)
|
||||
return 0;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (streq_ptr(w->name, name))
|
||||
return 0;
|
||||
|
||||
if (w->name)
|
||||
hashmap_remove_value(w->manager->wiphy_by_name, w->name, w);
|
||||
|
||||
r = free_and_strdup(&w->name, name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return hashmap_ensure_put(&w->manager->wiphy_by_name, &string_hash_ops, w->name, w);
|
||||
}
|
||||
|
||||
static int wiphy_update(Wiphy *w, sd_netlink_message *message) {
|
||||
int r;
|
||||
|
||||
assert(w);
|
||||
assert(message);
|
||||
|
||||
r = wiphy_update_name(w, message);
|
||||
if (r < 0)
|
||||
return log_wiphy_debug_errno(w, r, "Failed to update wiphy name: %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int manager_genl_process_nl80211_wiphy(sd_netlink *genl, sd_netlink_message *message, Manager *manager) {
|
||||
const char *family;
|
||||
uint32_t index;
|
||||
uint8_t cmd;
|
||||
Wiphy *w = NULL;
|
||||
int r;
|
||||
|
||||
assert(genl);
|
||||
assert(message);
|
||||
assert(manager);
|
||||
|
||||
if (sd_netlink_message_is_error(message)) {
|
||||
r = sd_netlink_message_get_errno(message);
|
||||
if (r < 0)
|
||||
log_message_warning_errno(message, r, "nl80211: received error message, ignoring");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_genl_message_get_family_name(genl, message, &family);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "nl80211: failed to determine genl family, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
if (!streq(family, NL80211_GENL_NAME)) {
|
||||
log_debug("nl80211: Received message of unexpected genl family '%s', ignoring.", family);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_genl_message_get_command(genl, message, &cmd);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "nl80211: failed to determine genl message command, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_netlink_message_read_u32(message, NL80211_ATTR_WIPHY, &index);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "nl80211: received %s(%u) message without valid index, ignoring: %m",
|
||||
strna(nl80211_cmd_to_string(cmd)), cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
(void) wiphy_get_by_index(manager, index, &w);
|
||||
|
||||
switch (cmd) {
|
||||
case NL80211_CMD_NEW_WIPHY: {
|
||||
bool is_new = !w;
|
||||
|
||||
if (!w) {
|
||||
r = wiphy_new(manager, index, &w);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "Failed to allocate wiphy, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
r = wiphy_update(w, message);
|
||||
if (r < 0) {
|
||||
log_wiphy_warning_errno(w, r, "Failed to update wiphy, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_wiphy_debug(w, "Received %s phy.", is_new ? "new" : "updated");
|
||||
break;
|
||||
}
|
||||
case NL80211_CMD_DEL_WIPHY:
|
||||
|
||||
if (!w) {
|
||||
log_debug("The kernel removes wiphy we do not know, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_wiphy_debug(w, "Removed.");
|
||||
wiphy_free(w);
|
||||
break;
|
||||
|
||||
default:
|
||||
log_wiphy_debug(w, "nl80211: received %s(%u) message.",
|
||||
strna(nl80211_cmd_to_string(cmd)), cmd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
51
src/network/networkd-wiphy.h
Normal file
51
src/network/networkd-wiphy.h
Normal file
@ -0,0 +1,51 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "sd-device.h"
|
||||
|
||||
#include "macro.h"
|
||||
|
||||
typedef struct Manager Manager;
|
||||
|
||||
typedef struct Wiphy {
|
||||
Manager *manager;
|
||||
|
||||
uint32_t index;
|
||||
char *name;
|
||||
} Wiphy;
|
||||
|
||||
Wiphy *wiphy_free(Wiphy *w);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Wiphy*, wiphy_free);
|
||||
|
||||
int wiphy_get_by_index(Manager *manager, uint32_t index, Wiphy **ret);
|
||||
int wiphy_get_by_name(Manager *manager, const char *name, Wiphy **ret);
|
||||
|
||||
int manager_genl_process_nl80211_wiphy(sd_netlink *genl, sd_netlink_message *message, Manager *manager);
|
||||
|
||||
#define log_wiphy_full_errno_zerook(w, level, error, ...) \
|
||||
({ \
|
||||
const Wiphy *_w = (w); \
|
||||
log_interface_full_errno_zerook(_w ? _w->name : NULL, level, error, __VA_ARGS__); \
|
||||
})
|
||||
|
||||
#define log_wiphy_full_errno(w, level, error, ...) \
|
||||
({ \
|
||||
int _error = (error); \
|
||||
ASSERT_NON_ZERO(_error); \
|
||||
log_wiphy_full_errno_zerook(w, level, _error, __VA_ARGS__); \
|
||||
})
|
||||
|
||||
#define log_wiphy_full(w, level, ...) (void) log_wiphy_full_errno_zerook(w, level, 0, __VA_ARGS__)
|
||||
|
||||
#define log_wiphy_debug(w, ...) log_wiphy_full(w, LOG_DEBUG, __VA_ARGS__)
|
||||
#define log_wiphy_info(w, ...) log_wiphy_full(w, LOG_INFO, __VA_ARGS__)
|
||||
#define log_wiphy_notice(w, ...) log_wiphy_full(w, LOG_NOTICE, __VA_ARGS__)
|
||||
#define log_wiphy_warning(w, ...) log_wiphy_full(w, LOG_WARNING, __VA_ARGS__)
|
||||
#define log_wiphy_error(w, ...) log_wiphy_full(w, LOG_ERR, __VA_ARGS__)
|
||||
|
||||
#define log_wiphy_debug_errno(w, error, ...) log_wiphy_full_errno(w, LOG_DEBUG, error, __VA_ARGS__)
|
||||
#define log_wiphy_info_errno(w, error, ...) log_wiphy_full_errno(w, LOG_INFO, error, __VA_ARGS__)
|
||||
#define log_wiphy_notice_errno(w, error, ...) log_wiphy_full_errno(w, LOG_NOTICE, error, __VA_ARGS__)
|
||||
#define log_wiphy_warning_errno(w, error, ...) log_wiphy_full_errno(w, LOG_WARNING, error, __VA_ARGS__)
|
||||
#define log_wiphy_error_errno(w, error, ...) log_wiphy_full_errno(w, LOG_ERR, error, __VA_ARGS__)
|
Loading…
Reference in New Issue
Block a user