station: add ConnectBssid() developer method
This method will initiate a connection to a specific BSS rather than relying on a network based connection (which the user has no control over which specific BSS is selected).
This commit is contained in:
parent
b543bf76f1
commit
3afa5e570d
137
src/station.c
137
src/station.c
|
@ -286,6 +286,25 @@ static int bss_signal_strength_compare(const void *a, const void *b, void *user)
|
||||||
return (bss->signal_strength > new_bss->signal_strength) ? 1 : -1;
|
return (bss->signal_strength > new_bss->signal_strength) ? 1 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int station_parse_bss_security(struct station *station,
|
||||||
|
struct scan_bss *bss,
|
||||||
|
enum security *security_out)
|
||||||
|
{
|
||||||
|
struct ie_rsn_info info;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = scan_bss_get_rsn_info(bss, &info);
|
||||||
|
if (r < 0) {
|
||||||
|
if (r != -ENOENT)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
*security_out = security_determine(bss->capability, NULL);
|
||||||
|
} else
|
||||||
|
*security_out = security_determine(bss->capability, &info);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns the network object the BSS was added to or NULL if ignored.
|
* Returns the network object the BSS was added to or NULL if ignored.
|
||||||
*/
|
*/
|
||||||
|
@ -293,8 +312,6 @@ static struct network *station_add_seen_bss(struct station *station,
|
||||||
struct scan_bss *bss)
|
struct scan_bss *bss)
|
||||||
{
|
{
|
||||||
struct network *network;
|
struct network *network;
|
||||||
struct ie_rsn_info info;
|
|
||||||
int r;
|
|
||||||
enum security security;
|
enum security security;
|
||||||
const char *path;
|
const char *path;
|
||||||
char ssid[33];
|
char ssid[33];
|
||||||
|
@ -323,16 +340,9 @@ static struct network *station_add_seen_bss(struct station *station,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&info, 0, sizeof(info));
|
if (station_parse_bss_security(station, bss, &security) < 0)
|
||||||
r = scan_bss_get_rsn_info(bss, &info);
|
|
||||||
if (r < 0) {
|
|
||||||
if (r != -ENOENT)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
security = security_determine(bss->capability, NULL);
|
|
||||||
} else
|
|
||||||
security = security_determine(bss->capability, &info);
|
|
||||||
|
|
||||||
path = iwd_network_get_path(station, ssid, security);
|
path = iwd_network_get_path(station, ssid, security);
|
||||||
|
|
||||||
network = l_hashmap_lookup(station->networks, path);
|
network = l_hashmap_lookup(station->networks, path);
|
||||||
|
@ -1872,8 +1882,6 @@ static bool station_roam_scan_notify(int err, struct l_queue *bss_list,
|
||||||
|
|
||||||
while ((bss = l_queue_pop_head(bss_list))) {
|
while ((bss = l_queue_pop_head(bss_list))) {
|
||||||
double rank;
|
double rank;
|
||||||
struct ie_rsn_info info;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
/* Skip the BSS we are connected to if doing an AP roam */
|
/* Skip the BSS we are connected to if doing an AP roam */
|
||||||
if (station->ap_directed_roaming && !memcmp(bss->addr,
|
if (station->ap_directed_roaming && !memcmp(bss->addr,
|
||||||
|
@ -1886,16 +1894,9 @@ static bool station_roam_scan_notify(int err, struct l_queue *bss_list,
|
||||||
memcmp(bss->ssid, hs->ssid, hs->ssid_len))
|
memcmp(bss->ssid, hs->ssid, hs->ssid_len))
|
||||||
goto next;
|
goto next;
|
||||||
|
|
||||||
memset(&info, 0, sizeof(info));
|
if (station_parse_bss_security(station, bss, &security) < 0)
|
||||||
r = scan_bss_get_rsn_info(bss, &info);
|
|
||||||
if (r < 0) {
|
|
||||||
if (r != -ENOENT)
|
|
||||||
goto next;
|
goto next;
|
||||||
|
|
||||||
security = security_determine(bss->capability, NULL);
|
|
||||||
} else
|
|
||||||
security = security_determine(bss->capability, &info);
|
|
||||||
|
|
||||||
if (security != orig_security)
|
if (security != orig_security)
|
||||||
goto next;
|
goto next;
|
||||||
|
|
||||||
|
@ -3023,21 +3024,11 @@ static struct l_dbus_message *station_dbus_get_hidden_access_points(
|
||||||
entry; entry = entry->next) {
|
entry; entry = entry->next) {
|
||||||
struct scan_bss *bss = entry->data;
|
struct scan_bss *bss = entry->data;
|
||||||
int16_t signal_strength = bss->signal_strength;
|
int16_t signal_strength = bss->signal_strength;
|
||||||
struct ie_rsn_info info;
|
|
||||||
enum security security;
|
enum security security;
|
||||||
int r;
|
|
||||||
|
|
||||||
memset(&info, 0, sizeof(info));
|
if (station_parse_bss_security(station, bss, &security) < 0)
|
||||||
r = scan_bss_get_rsn_info(bss, &info);
|
|
||||||
if (r < 0) {
|
|
||||||
if (r != -ENOENT)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
security = security_determine(bss->capability, NULL);
|
|
||||||
} else {
|
|
||||||
security = security_determine(bss->capability, &info);
|
|
||||||
}
|
|
||||||
|
|
||||||
l_dbus_message_builder_enter_struct(builder, "sns");
|
l_dbus_message_builder_enter_struct(builder, "sns");
|
||||||
l_dbus_message_builder_append_basic(builder, 's',
|
l_dbus_message_builder_append_basic(builder, 's',
|
||||||
util_address_to_string(bss->addr));
|
util_address_to_string(bss->addr));
|
||||||
|
@ -3540,6 +3531,12 @@ static struct station *station_create(struct netdev *netdev)
|
||||||
|
|
||||||
station_fill_scan_freq_subsets(station);
|
station_fill_scan_freq_subsets(station);
|
||||||
|
|
||||||
|
if (iwd_is_developer_mode())
|
||||||
|
l_dbus_object_add_interface(dbus,
|
||||||
|
netdev_get_path(station->netdev),
|
||||||
|
IWD_STATION_DEBUG_INTERFACE,
|
||||||
|
station);
|
||||||
|
|
||||||
return station;
|
return station;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3553,6 +3550,10 @@ static void station_free(struct station *station)
|
||||||
l_dbus_object_remove_interface(dbus_get_bus(),
|
l_dbus_object_remove_interface(dbus_get_bus(),
|
||||||
netdev_get_path(station->netdev),
|
netdev_get_path(station->netdev),
|
||||||
IWD_STATION_DIAGNOSTIC_INTERFACE);
|
IWD_STATION_DIAGNOSTIC_INTERFACE);
|
||||||
|
if (iwd_is_developer_mode())
|
||||||
|
l_dbus_object_remove_interface(dbus_get_bus(),
|
||||||
|
netdev_get_path(station->netdev),
|
||||||
|
IWD_STATION_DEBUG_INTERFACE);
|
||||||
|
|
||||||
if (station->netconfig) {
|
if (station->netconfig) {
|
||||||
netconfig_destroy(station->netconfig);
|
netconfig_destroy(station->netconfig);
|
||||||
|
@ -3761,6 +3762,21 @@ invalid_args:
|
||||||
return dbus_error_invalid_args(message);
|
return dbus_error_invalid_args(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct network *station_find_network_from_bss(struct station *station,
|
||||||
|
struct scan_bss *bss)
|
||||||
|
{
|
||||||
|
enum security security;
|
||||||
|
char ssid[33];
|
||||||
|
|
||||||
|
memcpy(ssid, bss->ssid, bss->ssid_len);
|
||||||
|
ssid[bss->ssid_len] = '\0';
|
||||||
|
|
||||||
|
if (station_parse_bss_security(station, bss, &security) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return station_network_find(station, ssid, security);
|
||||||
|
}
|
||||||
|
|
||||||
static void station_setup_diagnostic_interface(
|
static void station_setup_diagnostic_interface(
|
||||||
struct l_dbus_interface *interface)
|
struct l_dbus_interface *interface)
|
||||||
{
|
{
|
||||||
|
@ -3777,6 +3793,56 @@ static void station_destroy_diagnostic_interface(void *user_data)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct l_dbus_message *station_force_connect_bssid(struct l_dbus *dbus,
|
||||||
|
struct l_dbus_message *message,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
struct station *station = user_data;
|
||||||
|
struct l_queue *bss_list;
|
||||||
|
struct scan_bss *target;
|
||||||
|
struct network *network;
|
||||||
|
struct l_dbus_message_iter iter;
|
||||||
|
uint8_t *mac;
|
||||||
|
uint32_t mac_len;
|
||||||
|
|
||||||
|
if (!l_dbus_message_get_arguments(message, "ay", &iter))
|
||||||
|
goto invalid_args;
|
||||||
|
|
||||||
|
if (!l_dbus_message_iter_get_fixed_array(&iter, &mac, &mac_len))
|
||||||
|
goto invalid_args;
|
||||||
|
|
||||||
|
if (mac_len != 6)
|
||||||
|
return dbus_error_invalid_args(message);
|
||||||
|
|
||||||
|
bss_list = station_get_bss_list(station);
|
||||||
|
|
||||||
|
target = l_queue_find(bss_list, bss_match_bssid, mac);
|
||||||
|
if (!target)
|
||||||
|
return dbus_error_invalid_args(message);
|
||||||
|
|
||||||
|
if (util_ssid_is_hidden(target->ssid_len, target->ssid))
|
||||||
|
return dbus_error_not_found(message);
|
||||||
|
|
||||||
|
network = station_find_network_from_bss(station, target);
|
||||||
|
if (!network)
|
||||||
|
return dbus_error_invalid_args(message);
|
||||||
|
|
||||||
|
l_debug("Attempting forced connection to BSS "MAC, MAC_STR(mac));
|
||||||
|
|
||||||
|
return __network_connect(network, target, message);
|
||||||
|
|
||||||
|
invalid_args:
|
||||||
|
return dbus_error_invalid_args(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void station_setup_debug_interface(
|
||||||
|
struct l_dbus_interface *interface)
|
||||||
|
{
|
||||||
|
l_dbus_interface_method(interface, "ConnectBssid", 0,
|
||||||
|
station_force_connect_bssid, "", "ay",
|
||||||
|
"mac");
|
||||||
|
}
|
||||||
|
|
||||||
static void ap_roam_frame_event(const struct mmpdu_header *hdr,
|
static void ap_roam_frame_event(const struct mmpdu_header *hdr,
|
||||||
const void *body, size_t body_len,
|
const void *body, size_t body_len,
|
||||||
int rssi, void *user_data)
|
int rssi, void *user_data)
|
||||||
|
@ -3848,6 +3914,12 @@ static int station_init(void)
|
||||||
station_setup_diagnostic_interface,
|
station_setup_diagnostic_interface,
|
||||||
station_destroy_diagnostic_interface,
|
station_destroy_diagnostic_interface,
|
||||||
false);
|
false);
|
||||||
|
if (iwd_is_developer_mode())
|
||||||
|
l_dbus_register_interface(dbus_get_bus(),
|
||||||
|
IWD_STATION_DEBUG_INTERFACE,
|
||||||
|
station_setup_debug_interface,
|
||||||
|
NULL,
|
||||||
|
false);
|
||||||
|
|
||||||
if (!l_settings_get_uint(iwd_get_config(), "General",
|
if (!l_settings_get_uint(iwd_get_config(), "General",
|
||||||
"ManagementFrameProtection",
|
"ManagementFrameProtection",
|
||||||
|
@ -3889,6 +3961,9 @@ static void station_exit(void)
|
||||||
{
|
{
|
||||||
l_dbus_unregister_interface(dbus_get_bus(),
|
l_dbus_unregister_interface(dbus_get_bus(),
|
||||||
IWD_STATION_DIAGNOSTIC_INTERFACE);
|
IWD_STATION_DIAGNOSTIC_INTERFACE);
|
||||||
|
if (iwd_is_developer_mode())
|
||||||
|
l_dbus_unregister_interface(dbus_get_bus(),
|
||||||
|
IWD_STATION_DEBUG_INTERFACE);
|
||||||
l_dbus_unregister_interface(dbus_get_bus(), IWD_STATION_INTERFACE);
|
l_dbus_unregister_interface(dbus_get_bus(), IWD_STATION_INTERFACE);
|
||||||
netdev_watch_remove(netdev_watch);
|
netdev_watch_remove(netdev_watch);
|
||||||
l_queue_destroy(station_list, NULL);
|
l_queue_destroy(station_list, NULL);
|
||||||
|
|
Loading…
Reference in New Issue