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.
This commit is contained in:
Denis Kenzior 2021-04-19 16:58:53 -05:00
parent a83bb33ea5
commit 4a1dafb907
3 changed files with 45 additions and 32 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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,