mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2025-02-16 23:40:43 +01:00
device: enable connection to the hidden networks
1) Change signature of process_bss to return a confirmation that bss has been added to a network otherwise we can discard it. 2) Implements logic for the discovery and connection to a hidden network.
This commit is contained in:
parent
72c6862255
commit
d8c8ebdf3a
168
src/device.c
168
src/device.c
@ -247,7 +247,7 @@ static bool process_network(const void *key, void *data, void *user_data)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void process_bss(struct device *device, struct scan_bss *bss,
|
static bool process_bss(struct device *device, struct scan_bss *bss,
|
||||||
struct timespec *timestamp)
|
struct timespec *timestamp)
|
||||||
{
|
{
|
||||||
struct network *network;
|
struct network *network;
|
||||||
@ -268,12 +268,12 @@ static void process_bss(struct device *device, struct scan_bss *bss,
|
|||||||
if (util_ssid_is_hidden(bss->ssid_len, bss->ssid)) {
|
if (util_ssid_is_hidden(bss->ssid_len, bss->ssid)) {
|
||||||
l_warn("Ignoring BSS with hidden SSID");
|
l_warn("Ignoring BSS with hidden SSID");
|
||||||
device->seen_hidden_networks = true;
|
device->seen_hidden_networks = true;
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!util_ssid_is_utf8(bss->ssid_len, bss->ssid)) {
|
if (!util_ssid_is_utf8(bss->ssid_len, bss->ssid)) {
|
||||||
l_warn("Ignoring BSS with non-UTF8 SSID");
|
l_warn("Ignoring BSS with non-UTF8 SSID");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(ssid, bss->ssid, bss->ssid_len);
|
memcpy(ssid, bss->ssid, bss->ssid_len);
|
||||||
@ -283,7 +283,7 @@ static void process_bss(struct device *device, struct scan_bss *bss,
|
|||||||
r = scan_bss_get_rsn_info(bss, &info);
|
r = scan_bss_get_rsn_info(bss, &info);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
if (r != -ENOENT)
|
if (r != -ENOENT)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
security = security_determine(bss->capability, NULL);
|
security = security_determine(bss->capability, NULL);
|
||||||
} else
|
} else
|
||||||
@ -297,7 +297,7 @@ static void process_bss(struct device *device, struct scan_bss *bss,
|
|||||||
|
|
||||||
if (!network_register(network, path)) {
|
if (!network_register(network, path)) {
|
||||||
network_remove(network, -EINVAL);
|
network_remove(network, -EINVAL);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
l_hashmap_insert(device->networks,
|
l_hashmap_insert(device->networks,
|
||||||
@ -312,11 +312,11 @@ static void process_bss(struct device *device, struct scan_bss *bss,
|
|||||||
network_bss_add(network, bss);
|
network_bss_add(network, bss);
|
||||||
|
|
||||||
if (device->state != DEVICE_STATE_AUTOCONNECT)
|
if (device->state != DEVICE_STATE_AUTOCONNECT)
|
||||||
return;
|
return true;
|
||||||
|
|
||||||
/* See if network is autoconnectable (is a known network) */
|
/* See if network is autoconnectable (is a known network) */
|
||||||
if (!network_rankmod(network, &rankmod))
|
if (!network_rankmod(network, &rankmod))
|
||||||
return;
|
return true;
|
||||||
|
|
||||||
entry = l_new(struct autoconnect_entry, 1);
|
entry = l_new(struct autoconnect_entry, 1);
|
||||||
entry->network = network;
|
entry->network = network;
|
||||||
@ -324,6 +324,8 @@ static void process_bss(struct device *device, struct scan_bss *bss,
|
|||||||
entry->rank = bss->rank * rankmod;
|
entry->rank = bss->rank * rankmod;
|
||||||
l_queue_insert(device->autoconnect_list, entry,
|
l_queue_insert(device->autoconnect_list, entry,
|
||||||
autoconnect_rank_compare, NULL);
|
autoconnect_rank_compare, NULL);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool bss_match(const void *a, const void *b)
|
static bool bss_match(const void *a, const void *b)
|
||||||
@ -2113,6 +2115,156 @@ static struct l_dbus_message *device_set_mode_sta(struct device *device,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool device_network_is_known(const char *ssid, enum security security)
|
||||||
|
{
|
||||||
|
const struct network_info *network_info =
|
||||||
|
network_info_find(ssid, security);
|
||||||
|
|
||||||
|
if (network_info && network_info->is_known)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void device_hidden_network_scan_triggered(int err, void *user_data)
|
||||||
|
{
|
||||||
|
struct device *device = user_data;
|
||||||
|
|
||||||
|
l_debug("");
|
||||||
|
|
||||||
|
if (!err)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dbus_pending_reply(&device->connect_pending,
|
||||||
|
dbus_error_failed(device->connect_pending));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool device_hidden_network_scan_results(uint32_t wiphy_id,
|
||||||
|
uint32_t ifindex, int err,
|
||||||
|
struct l_queue *bss_list,
|
||||||
|
void *userdata)
|
||||||
|
{
|
||||||
|
struct device *device = userdata;
|
||||||
|
struct network *network_psk;
|
||||||
|
struct network *network_open;
|
||||||
|
struct network *network;
|
||||||
|
const char *ssid;
|
||||||
|
uint8_t ssid_len;
|
||||||
|
struct l_dbus_message *reply;
|
||||||
|
struct timespec now;
|
||||||
|
struct scan_bss *bss;
|
||||||
|
|
||||||
|
l_debug("");
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
reply = dbus_error_failed(device->connect_pending);
|
||||||
|
goto bss_list_not_owned_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!l_dbus_message_get_arguments(device->connect_pending, "s",
|
||||||
|
&ssid)) {
|
||||||
|
reply = dbus_error_invalid_args(device->connect_pending);
|
||||||
|
goto bss_list_not_owned_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
clock_gettime(CLOCK_REALTIME, &now);
|
||||||
|
ssid_len = strlen(ssid);
|
||||||
|
|
||||||
|
while ((bss = l_queue_pop_head(bss_list))) {
|
||||||
|
if (bss->ssid_len != ssid_len ||
|
||||||
|
memcmp(bss->ssid, ssid, ssid_len))
|
||||||
|
goto next;
|
||||||
|
|
||||||
|
if (process_bss(device, bss, &now)) {
|
||||||
|
l_queue_push_tail(device->bss_list, bss);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
next:
|
||||||
|
scan_bss_free(bss);
|
||||||
|
}
|
||||||
|
|
||||||
|
l_queue_destroy(bss_list, NULL);
|
||||||
|
|
||||||
|
network_psk = device_network_find(device, ssid, SECURITY_PSK);
|
||||||
|
network_open = device_network_find(device, ssid, SECURITY_NONE);
|
||||||
|
|
||||||
|
if (!network_psk && !network_open) {
|
||||||
|
reply = dbus_error_not_found(device->connect_pending);
|
||||||
|
|
||||||
|
goto bss_list_owned_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (network_psk && network_open) {
|
||||||
|
reply = dbus_error_service_set_overlap(device->connect_pending);
|
||||||
|
|
||||||
|
goto bss_list_owned_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
network = network_psk ? : network_open;
|
||||||
|
|
||||||
|
network_connect_new_hidden_network(network, device->connect_pending);
|
||||||
|
|
||||||
|
l_dbus_message_unref(device->connect_pending);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
bss_list_owned_error:
|
||||||
|
dbus_pending_reply(&device->connect_pending, reply);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
bss_list_not_owned_error:
|
||||||
|
dbus_pending_reply(&device->connect_pending, reply);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct l_dbus_message *device_connect_hidden_network(struct l_dbus *dbus,
|
||||||
|
struct l_dbus_message *message,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
struct device *device = user_data;
|
||||||
|
const char *ssid;
|
||||||
|
struct scan_parameters params = {
|
||||||
|
.flush = true,
|
||||||
|
.randomize_mac_addr_hint = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
l_debug("");
|
||||||
|
|
||||||
|
if (device->state == DEVICE_STATE_OFF)
|
||||||
|
return dbus_error_failed(message);
|
||||||
|
|
||||||
|
if (device->connect_pending || device_is_busy(device))
|
||||||
|
return dbus_error_busy(message);
|
||||||
|
|
||||||
|
if (!l_dbus_message_get_arguments(message, "s", &ssid))
|
||||||
|
return dbus_error_invalid_args(message);
|
||||||
|
|
||||||
|
if (strlen(ssid) > 32)
|
||||||
|
return dbus_error_invalid_args(message);
|
||||||
|
|
||||||
|
if (device_network_is_known(ssid, SECURITY_PSK) ||
|
||||||
|
device_network_is_known(ssid, SECURITY_NONE))
|
||||||
|
return dbus_error_already_provisioned(message);
|
||||||
|
|
||||||
|
if (device_network_find(device, ssid, SECURITY_PSK) ||
|
||||||
|
device_network_find(device, ssid, SECURITY_NONE))
|
||||||
|
return dbus_error_not_hidden(message);
|
||||||
|
|
||||||
|
params.ssid = ssid;
|
||||||
|
|
||||||
|
if (!scan_active_full(device->index, ¶ms,
|
||||||
|
device_hidden_network_scan_triggered,
|
||||||
|
device_hidden_network_scan_results,
|
||||||
|
device, NULL))
|
||||||
|
return dbus_error_failed(message);
|
||||||
|
|
||||||
|
device->connect_pending = l_dbus_message_ref(message);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static bool device_property_get_name(struct l_dbus *dbus,
|
static bool device_property_get_name(struct l_dbus *dbus,
|
||||||
struct l_dbus_message *message,
|
struct l_dbus_message *message,
|
||||||
struct l_dbus_message_builder *builder,
|
struct l_dbus_message_builder *builder,
|
||||||
@ -2408,6 +2560,8 @@ static void setup_device_interface(struct l_dbus_interface *interface)
|
|||||||
l_dbus_interface_method(interface, "UnregisterSignalLevelAgent", 0,
|
l_dbus_interface_method(interface, "UnregisterSignalLevelAgent", 0,
|
||||||
device_signal_agent_unregister,
|
device_signal_agent_unregister,
|
||||||
"", "o", "path");
|
"", "o", "path");
|
||||||
|
l_dbus_interface_method(interface, "ConnectHiddenNetwork", 0,
|
||||||
|
device_connect_hidden_network, "", "s", "name");
|
||||||
l_dbus_interface_property(interface, "Name", 0, "s",
|
l_dbus_interface_property(interface, "Name", 0, "s",
|
||||||
device_property_get_name, NULL);
|
device_property_get_name, NULL);
|
||||||
l_dbus_interface_property(interface, "Address", 0, "s",
|
l_dbus_interface_property(interface, "Address", 0, "s",
|
||||||
|
@ -1000,6 +1000,8 @@ void network_connect_new_hidden_network(struct network *network,
|
|||||||
|
|
||||||
l_debug("");
|
l_debug("");
|
||||||
|
|
||||||
|
network_info_set_hidden(network);
|
||||||
|
|
||||||
bss = network_bss_select(network);
|
bss = network_bss_select(network);
|
||||||
if (!bss) {
|
if (!bss) {
|
||||||
/* This should never happened for the hidden networks. */
|
/* This should never happened for the hidden networks. */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user