From 4a1dafb90779bda563b0968eacf5a2dcede2b703 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 19 Apr 2021 16:58:53 -0500 Subject: [PATCH] station: Move AP directed roam watch to station Logically this frame watch belongs in station. It was kept in device.c for the purported reason that the station object was removed with ifdown/ifup changes and hence the frame watch might need to be removed and re-added unnecessarily. Since the kernel does not actually allow to unregister a frame watch (only when the netdev is removed or its iftype changes), re-adding a frame watch might trigger a -EALREADY or similar error. Avoid this by registering the frame watch when a new netdev is detected in STATION mode, or when the interface type changes to STATION. --- src/device.c | 22 ---------------------- src/station.c | 51 +++++++++++++++++++++++++++++++++++++++++++++------ src/station.h | 4 ---- 3 files changed, 45 insertions(+), 32 deletions(-) diff --git a/src/device.c b/src/device.c index dc2c181a..02da2cdc 100644 --- a/src/device.c +++ b/src/device.c @@ -37,8 +37,6 @@ #include "src/scan.h" #include "src/netdev.h" #include "src/dbus.h" -#include "src/frame-xchg.h" -#include "src/station.h" struct device { uint32_t index; @@ -54,18 +52,6 @@ struct device { static uint32_t netdev_watch; -static void device_ap_roam_frame_event(const struct mmpdu_header *hdr, - const void *body, size_t body_len, int rssi, void *user_data) -{ - struct device *device = user_data; - struct station *station = station_find(device->index); - - if (!station) - return; - - station_ap_directed_roam(station, hdr, body, body_len); -} - static bool device_property_get_name(struct l_dbus *dbus, struct l_dbus_message *message, struct l_dbus_message_builder *builder, @@ -304,7 +290,6 @@ static struct device *device_create(struct wiphy *wiphy, struct netdev *netdev) struct device *device; struct l_dbus *dbus = dbus_get_bus(); uint32_t ifindex = netdev_get_ifindex(netdev); - const uint8_t action_ap_roam_prefix[2] = { 0x0a, 0x07 }; device = l_new(struct device, 1); device->index = ifindex; @@ -320,13 +305,6 @@ static struct device *device_create(struct wiphy *wiphy, struct netdev *netdev) l_info("Unable to register %s interface", L_DBUS_INTERFACE_PROPERTIES); - /* - * register for AP roam transition watch - */ - frame_watch_add(netdev_get_wdev_id(netdev), 0, 0x00d0, - action_ap_roam_prefix, sizeof(action_ap_roam_prefix), - device_ap_roam_frame_event, device, NULL); - device->powered = netdev_get_is_up(netdev); device->dbus_powered = true; diff --git a/src/station.c b/src/station.c index 064872c6..5e3338f0 100644 --- a/src/station.c +++ b/src/station.c @@ -55,6 +55,7 @@ #include "src/anqp.h" #include "src/anqputil.h" #include "src/diagnostic.h" +#include "src/frame-xchg.h" static struct l_queue *station_list; static uint32_t netdev_watch; @@ -2221,9 +2222,9 @@ static bool station_cannot_roam(struct station *station) #define WNM_REQUEST_MODE_TERMINATION_IMMINENT (1 << 3) #define WNM_REQUEST_MODE_ESS_DISASSOCIATION_IMMINENT (1 << 4) -void station_ap_directed_roam(struct station *station, - const struct mmpdu_header *hdr, - const void *body, size_t body_len) +static void station_ap_directed_roam(struct station *station, + const struct mmpdu_header *hdr, + const void *body, size_t body_len) { uint32_t pos = 0; uint8_t req_mode; @@ -3704,15 +3705,48 @@ static void station_destroy_diagnostic_interface(void *user_data) { } +static void ap_roam_frame_event(const struct mmpdu_header *hdr, + const void *body, size_t body_len, + int rssi, void *user_data) +{ + uint32_t ifindex = L_PTR_TO_UINT(user_data); + struct station *station = station_find(ifindex); + + if (!station) + return; + + station_ap_directed_roam(station, hdr, body, body_len); +} + +static void add_frame_watches(struct netdev *netdev) +{ + static const uint8_t action_ap_roam_prefix[2] = { 0x0a, 0x07 }; + + /* + * register for AP roam transition watch + */ + frame_watch_add(netdev_get_wdev_id(netdev), 0, 0x00d0, + action_ap_roam_prefix, sizeof(action_ap_roam_prefix), + ap_roam_frame_event, + L_UINT_TO_PTR(netdev_get_ifindex(netdev)), NULL); +} + static void station_netdev_watch(struct netdev *netdev, enum netdev_watch_event event, void *userdata) { switch (event) { - case NETDEV_WATCH_EVENT_UP: case NETDEV_WATCH_EVENT_NEW: - if (netdev_get_iftype(netdev) == NETDEV_IFTYPE_STATION && - netdev_get_is_up(netdev)) + if (netdev_get_iftype(netdev) == NETDEV_IFTYPE_STATION) { + add_frame_watches(netdev); + + if (netdev_get_is_up(netdev)) + station_create(netdev); + } + break; + case NETDEV_WATCH_EVENT_UP: + if (netdev_get_iftype(netdev) == NETDEV_IFTYPE_STATION) station_create(netdev); + break; case NETDEV_WATCH_EVENT_DOWN: case NETDEV_WATCH_EVENT_DEL: @@ -3720,6 +3754,11 @@ static void station_netdev_watch(struct netdev *netdev, netdev_get_path(netdev), IWD_STATION_INTERFACE); break; + case NETDEV_WATCH_EVENT_IFTYPE_CHANGE: + if (netdev_get_iftype(netdev) == NETDEV_IFTYPE_STATION) + add_frame_watches(netdev); + + break; default: break; } diff --git a/src/station.h b/src/station.h index f114733b..6918b146 100644 --- a/src/station.h +++ b/src/station.h @@ -83,10 +83,6 @@ void station_remove_anqp_watch(uint32_t id); bool station_set_autoconnect(struct station *station, bool autoconnect); -void station_ap_directed_roam(struct station *station, - const struct mmpdu_header *hdr, - const void *body, size_t body_len); - int __station_connect_network(struct station *station, struct network *network, struct scan_bss *bss); void station_connect_network(struct station *station, struct network *network,