diff --git a/src/device.c b/src/device.c index f045cbee..a343c3ea 100644 --- a/src/device.c +++ b/src/device.c @@ -26,6 +26,7 @@ #include #include +#include #include @@ -49,6 +50,12 @@ struct device_watchlist_item { device_destroy_func_t destroy; }; +struct autoconnect_entry { + uint16_t rank; + struct network *network; + struct scan_bss *bss; +}; + static struct l_queue *device_watches = NULL; static uint32_t device_next_watch_id = 0; @@ -139,6 +146,65 @@ void __iwd_device_foreach(iwd_device_foreach_func func, void *user_data) } } +static const char *iwd_network_get_path(struct device *device, + const uint8_t *ssid, size_t ssid_len, + enum security security) +{ + static char path[256]; + unsigned int pos, i; + + pos = snprintf(path, sizeof(path), "%s/", device_get_path(device)); + + for (i = 0; i < ssid_len && pos < sizeof(path); i++) + pos += snprintf(path + pos, sizeof(path) - pos, "%02x", + ssid[i]); + + snprintf(path + pos, sizeof(path) - pos, "_%s", + security_to_str(security)); + + return path; +} + +static const char *device_state_to_string(enum device_state state) +{ + switch (state) { + case DEVICE_STATE_DISCONNECTED: + return "disconnected"; + case DEVICE_STATE_AUTOCONNECT: + return "autoconnect"; + case DEVICE_STATE_CONNECTING: + return "connecting"; + case DEVICE_STATE_CONNECTED: + return "connected"; + case DEVICE_STATE_DISCONNECTING: + return "disconnecting"; + } + + return "invalid"; +} + +static void device_autoconnect_next(struct device *device) +{ + struct autoconnect_entry *entry; + int r; + + while ((entry = l_queue_pop_head(device->autoconnect_list))) { + l_debug("Considering autoconnecting to BSS '%s' with SSID: %s," + " freq: %u, rank: %u, strength: %i", + util_address_to_string(entry->bss->addr), + network_get_ssid(entry->network), + entry->bss->frequency, entry->rank, + entry->bss->signal_strength); + + /* TODO: Blacklist the network from auto-connect */ + r = network_autoconnect(entry->network, entry->bss); + l_free(entry); + + if (!r) + return; + } +} + static void bss_free(void *data) { struct scan_bss *bss = data; @@ -157,6 +223,192 @@ static void network_free(void *data) network_remove(network, -ESHUTDOWN); } +static int autoconnect_rank_compare(const void *a, const void *b, void *user) +{ + const struct autoconnect_entry *new_ae = a; + const struct autoconnect_entry *ae = b; + + return ae->rank - new_ae->rank; +} + +static bool process_network(const void *key, void *data, void *user_data) +{ + struct network *network = data; + struct device *device = user_data; + + if (!network_bss_list_isempty(network)) { + /* Build the network list ordered by rank */ + network_rank_update(network); + + l_queue_insert(device->networks_sorted, network, + network_rank_compare, NULL); + + return false; + } + + /* Drop networks that have no more BSSs in range */ + l_debug("No remaining BSSs for SSID: %s -- Removing network", + network_get_ssid(network)); + network_remove(network, -ERANGE); + + return true; +} + +static void process_bss(struct device *device, struct scan_bss *bss, + struct timespec *timestamp) +{ + struct network *network; + enum security security; + const char *path; + double rankmod; + struct autoconnect_entry *entry; + + l_debug("Found BSS '%s' with SSID: %s, freq: %u, rank: %u, " + "strength: %i", + util_address_to_string(bss->addr), + util_ssid_to_utf8(bss->ssid_len, bss->ssid), + bss->frequency, bss->rank, bss->signal_strength); + + if (!util_ssid_is_utf8(bss->ssid_len, bss->ssid)) { + l_warn("Ignoring BSS with non-UTF8 SSID"); + return; + } + + /* + * If both an RSN and a WPA elements are present currently + * RSN takes priority and the WPA IE is ignored. + */ + if (bss->rsne) { + struct ie_rsn_info rsne; + int res = ie_parse_rsne_from_data(bss->rsne, bss->rsne[1] + 2, + &rsne); + if (res < 0) { + l_debug("Cannot parse RSN field (%d, %s)", + res, strerror(-res)); + return; + } + + security = scan_get_security(bss->capability, &rsne); + + if (security == SECURITY_PSK) + bss->sha256 = + rsne.akm_suites & IE_RSN_AKM_SUITE_PSK_SHA256; + else if (security == SECURITY_8021X) + bss->sha256 = + rsne.akm_suites & IE_RSN_AKM_SUITE_8021X_SHA256; + } else if (bss->wpa) { + struct ie_rsn_info wpa; + int res = ie_parse_wpa_from_data(bss->wpa, bss->wpa[1] + 2, + &wpa); + if (res < 0) { + l_debug("Cannot parse WPA IE (%d, %s)", + res, strerror(-res)); + return; + } + + security = scan_get_security(bss->capability, &wpa); + } else + security = scan_get_security(bss->capability, NULL); + + path = iwd_network_get_path(device, bss->ssid, bss->ssid_len, + security); + + network = l_hashmap_lookup(device->networks, path); + if (!network) { + network = network_create(device, bss->ssid, bss->ssid_len, + security); + + if (!network_register(network, path)) { + network_remove(network, -EINVAL); + return; + } + + l_hashmap_insert(device->networks, + network_get_path(network), network); + l_debug("Added new Network \"%s\" security %s", + network_get_ssid(network), security_to_str(security)); + } + + if (network_bss_list_isempty(network)) + network_seen(network, timestamp); + + network_bss_add(network, bss); + + /* See if network is autoconnectable (is a known network) */ + if (!network_rankmod(network, &rankmod)) + return; + + entry = l_new(struct autoconnect_entry, 1); + entry->network = network; + entry->bss = bss; + entry->rank = bss->rank * rankmod; + l_queue_insert(device->autoconnect_list, entry, + autoconnect_rank_compare, NULL); +} + +static bool bss_match(const void *a, const void *b) +{ + const struct scan_bss *bss_a = a; + const struct scan_bss *bss_b = b; + + return !memcmp(bss_a->addr, bss_b->addr, sizeof(bss_a->addr)); +} + +static bool new_scan_results(uint32_t wiphy_id, uint32_t ifindex, + struct l_queue *bss_list, void *userdata) +{ + struct device *device = userdata; + struct network *network; + const struct l_queue_entry *bss_entry; + struct timespec now; + + clock_gettime(CLOCK_REALTIME, &now); + + device->old_bss_list = device->bss_list; + device->bss_list = bss_list; + + while ((network = l_queue_pop_head(device->networks_sorted))) + network_bss_list_clear(network); + + l_queue_destroy(device->autoconnect_list, l_free); + device->autoconnect_list = l_queue_new(); + + for (bss_entry = l_queue_get_entries(bss_list); bss_entry; + bss_entry = bss_entry->next) { + struct scan_bss *bss = bss_entry->data; + + process_bss(device, bss, &now); + } + + l_hashmap_foreach_remove(device->networks, process_network, device); + + if (device->connected_bss) { + struct scan_bss *bss; + + bss = l_queue_find(device->bss_list, bss_match, + device->connected_bss); + + if (!bss) { + l_warn("Connected BSS not in scan results!"); + l_queue_push_tail(device->bss_list, + device->connected_bss); + network_bss_add(device->connected_network, + device->connected_bss); + l_queue_remove(device->old_bss_list, + device->connected_bss); + } else + device->connected_bss = bss; + } + + l_queue_destroy(device->old_bss_list, bss_free); + device->old_bss_list = NULL; + + if (device->state == DEVICE_STATE_AUTOCONNECT) + device_autoconnect_next(device); + + return true; +} + struct network *device_get_connected_network(struct device *device) { return device->connected_network; @@ -194,6 +446,31 @@ const uint8_t *device_get_address(struct device *device) return netdev_get_address(device->netdev); } +void device_enter_state(struct device *device, enum device_state state) +{ + l_debug("Old State: %s, new state: %s", + device_state_to_string(device->state), + device_state_to_string(state)); + + switch (state) { + case DEVICE_STATE_AUTOCONNECT: + scan_periodic_start(device->index, new_scan_results, device); + break; + case DEVICE_STATE_DISCONNECTED: + scan_periodic_stop(device->index); + break; + case DEVICE_STATE_CONNECTED: + scan_periodic_stop(device->index); + break; + case DEVICE_STATE_CONNECTING: + break; + case DEVICE_STATE_DISCONNECTING: + break; + } + + device->state = state; +} + void device_disassociated(struct device *device) { struct network *network = device->connected_network; @@ -377,6 +654,190 @@ void device_connect_network(struct device *device, struct network *network, IWD_NETWORK_INTERFACE, "Connected"); } +static void device_scan_triggered(int err, void *user_data) +{ + struct device *device = user_data; + struct l_dbus_message *reply; + + l_debug("device_scan_triggered: %i", err); + + if (err < 0) { + dbus_pending_reply(&device->scan_pending, + dbus_error_failed(device->scan_pending)); + return; + } + + l_debug("Scan triggered for %s", netdev_get_name(device->netdev)); + + reply = l_dbus_message_new_method_return(device->scan_pending); + l_dbus_message_set_arguments(reply, ""); + dbus_pending_reply(&device->scan_pending, reply); +} + +static struct l_dbus_message *device_scan(struct l_dbus *dbus, + struct l_dbus_message *message, + void *user_data) +{ + struct device *device = user_data; + + l_debug("Scan called from DBus"); + + if (device->scan_pending) + return dbus_error_busy(message); + + device->scan_pending = l_dbus_message_ref(message); + + if (!scan_passive(device->index, device_scan_triggered, + new_scan_results, device, NULL)) + return dbus_error_failed(message); + + return NULL; +} + +static void device_disconnect_cb(struct netdev *netdev, bool success, + void *user_data) +{ + struct device *device = user_data; + struct l_dbus_message *reply; + + if (!success) { + dbus_pending_reply(&device->disconnect_pending, + dbus_error_failed(device->disconnect_pending)); + return; + } + + device_disassociated(device); + + reply = l_dbus_message_new_method_return(device->disconnect_pending); + l_dbus_message_set_arguments(reply, ""); + dbus_pending_reply(&device->disconnect_pending, reply); +} + +static struct l_dbus_message *device_disconnect(struct l_dbus *dbus, + struct l_dbus_message *message, + void *user_data) +{ + struct device *device = user_data; + + l_debug(""); + + if (device->state == DEVICE_STATE_CONNECTING || + device->state == DEVICE_STATE_DISCONNECTING) + return dbus_error_busy(message); + + if (!device->connected_bss) + return dbus_error_not_connected(message); + + if (netdev_disconnect(device->netdev, device_disconnect_cb, device) < 0) + return dbus_error_failed(message); + + device_enter_state(device, DEVICE_STATE_DISCONNECTING); + + device->disconnect_pending = l_dbus_message_ref(message); + + return NULL; +} + +static struct l_dbus_message *device_get_networks(struct l_dbus *dbus, + struct l_dbus_message *message, + void *user_data) +{ + struct device *device = user_data; + struct l_dbus_message *reply; + struct l_dbus_message_builder *builder; + const struct l_queue_entry *entry; + + reply = l_dbus_message_new_method_return(message); + builder = l_dbus_message_builder_new(reply); + + l_dbus_message_builder_enter_array(builder, "(osns)"); + + for (entry = l_queue_get_entries(device->networks_sorted); entry; + entry = entry->next) { + const struct network *network = entry->data; + enum security security = network_get_security(network); + int32_t signal_strength = network_get_signal_strength(network); + + l_dbus_message_builder_enter_struct(builder, "osns"); + l_dbus_message_builder_append_basic(builder, 'o', + network_get_path(network)); + l_dbus_message_builder_append_basic(builder, 's', + network_get_ssid(network)); + l_dbus_message_builder_append_basic(builder, 'n', + &signal_strength); + l_dbus_message_builder_append_basic(builder, 's', + security_to_str(security)); + l_dbus_message_builder_leave_struct(builder); + } + + l_dbus_message_builder_leave_array(builder); + + l_dbus_message_builder_finalize(builder); + l_dbus_message_builder_destroy(builder); + + return reply; +} + +static bool device_property_get_name(struct l_dbus *dbus, + struct l_dbus_message *message, + struct l_dbus_message_builder *builder, + void *user_data) +{ + struct device *device = user_data; + + l_dbus_message_builder_append_basic(builder, 's', + netdev_get_name(device->netdev)); + return true; +} + +static bool device_property_get_address(struct l_dbus *dbus, + struct l_dbus_message *message, + struct l_dbus_message_builder *builder, + void *user_data) +{ + struct device *device = user_data; + const char *str; + + str = util_address_to_string(netdev_get_address(device->netdev)); + l_dbus_message_builder_append_basic(builder, 's', str); + + return true; +} + +static bool device_property_get_connected_network(struct l_dbus *dbus, + struct l_dbus_message *message, + struct l_dbus_message_builder *builder, + void *user_data) +{ + struct device *device = user_data; + if (!device->connected_network) + return false; + + l_dbus_message_builder_append_basic(builder, 'o', + network_get_path(device->connected_network)); + + return true; +} + +static void setup_device_interface(struct l_dbus_interface *interface) +{ + l_dbus_interface_method(interface, "Scan", 0, + device_scan, "", ""); + l_dbus_interface_method(interface, "Disconnect", 0, + device_disconnect, "", ""); + l_dbus_interface_method(interface, "GetOrderedNetworks", 0, + device_get_networks, "a(osns)", "", + "networks"); + + l_dbus_interface_property(interface, "Name", 0, "s", + device_property_get_name, NULL); + l_dbus_interface_property(interface, "Address", 0, "s", + device_property_get_address, NULL); + l_dbus_interface_property(interface, "ConnectedNetwork", 0, "o", + device_property_get_connected_network, + NULL); +} + struct device *device_create(struct wiphy *wiphy, struct netdev *netdev) { struct device *device; @@ -449,6 +910,12 @@ void device_remove(struct device *device) bool device_init(void) { + if (!l_dbus_register_interface(dbus_get_bus(), + IWD_DEVICE_INTERFACE, + setup_device_interface, + NULL, true)) + return false; + device_watches = l_queue_new(); device_list = l_queue_new(); @@ -462,5 +929,7 @@ bool device_exit(void) l_queue_destroy(device_watches, device_watchlist_item_free); + l_dbus_unregister_interface(dbus_get_bus(), IWD_DEVICE_INTERFACE); + return true; } diff --git a/src/wiphy.c b/src/wiphy.c index 26077a2a..68e8dc3b 100644 --- a/src/wiphy.c +++ b/src/wiphy.c @@ -28,22 +28,15 @@ #include #include #include -#include #include #include "linux/nl80211.h" #include "src/iwd.h" -#include "src/common.h" #include "src/ie.h" #include "src/crypto.h" -#include "src/dbus.h" #include "src/scan.h" -#include "src/util.h" -#include "src/netdev.h" -#include "src/network.h" -#include "src/device.h" #include "src/wiphy.h" static struct l_genl_family *nl80211 = NULL; @@ -58,79 +51,8 @@ struct wiphy { struct scan_freq_set *supported_freqs; }; -struct autoconnect_entry { - uint16_t rank; - struct network *network; - struct scan_bss *bss; -}; - static struct l_queue *wiphy_list = NULL; -static bool new_scan_results(uint32_t wiphy_id, uint32_t ifindex, - struct l_queue *bss_list, void *userdata); - -static const char *iwd_network_get_path(struct device *device, - const uint8_t *ssid, size_t ssid_len, - enum security security) -{ - static char path[256]; - unsigned int pos, i; - - pos = snprintf(path, sizeof(path), "%s/", device_get_path(device)); - - for (i = 0; i < ssid_len && pos < sizeof(path); i++) - pos += snprintf(path + pos, sizeof(path) - pos, "%02x", - ssid[i]); - - snprintf(path + pos, sizeof(path) - pos, "_%s", - security_to_str(security)); - - return path; -} - -static const char *device_state_to_string(enum device_state state) -{ - switch (state) { - case DEVICE_STATE_DISCONNECTED: - return "disconnected"; - case DEVICE_STATE_AUTOCONNECT: - return "autoconnect"; - case DEVICE_STATE_CONNECTING: - return "connecting"; - case DEVICE_STATE_CONNECTED: - return "connected"; - case DEVICE_STATE_DISCONNECTING: - return "disconnecting"; - } - - return "invalid"; -} - -void device_enter_state(struct device *device, enum device_state state) -{ - l_debug("Old State: %s, new state: %s", - device_state_to_string(device->state), - device_state_to_string(state)); - - switch (state) { - case DEVICE_STATE_AUTOCONNECT: - scan_periodic_start(device->index, new_scan_results, device); - break; - case DEVICE_STATE_DISCONNECTED: - scan_periodic_stop(device->index); - break; - case DEVICE_STATE_CONNECTED: - scan_periodic_stop(device->index); - break; - case DEVICE_STATE_CONNECTING: - break; - case DEVICE_STATE_DISCONNECTING: - break; - } - - device->state = state; -} - enum ie_rsn_cipher_suite wiphy_select_cipher(struct wiphy *wiphy, uint16_t mask) { mask &= wiphy->pairwise_ciphers; @@ -144,233 +66,6 @@ enum ie_rsn_cipher_suite wiphy_select_cipher(struct wiphy *wiphy, uint16_t mask) return 0; } - -static void bss_free(void *data) -{ - struct scan_bss *bss = data; - const char *addr; - - addr = util_address_to_string(bss->addr); - - l_debug("Freeing BSS %s", addr); - - scan_bss_free(bss); -} - -static void device_scan_triggered(int err, void *user_data) -{ - struct device *device = user_data; - struct l_dbus_message *reply; - - l_debug("device_scan_triggered: %i", err); - - if (err < 0) { - dbus_pending_reply(&device->scan_pending, - dbus_error_failed(device->scan_pending)); - return; - } - - l_debug("Scan triggered for %s", netdev_get_name(device->netdev)); - - reply = l_dbus_message_new_method_return(device->scan_pending); - l_dbus_message_set_arguments(reply, ""); - dbus_pending_reply(&device->scan_pending, reply); -} - -static struct l_dbus_message *device_scan(struct l_dbus *dbus, - struct l_dbus_message *message, - void *user_data) -{ - struct device *device = user_data; - - l_debug("Scan called from DBus"); - - if (device->scan_pending) - return dbus_error_busy(message); - - device->scan_pending = l_dbus_message_ref(message); - - if (!scan_passive(device->index, device_scan_triggered, - new_scan_results, device, NULL)) - return dbus_error_failed(message); - - return NULL; -} - -static void device_disconnect_cb(struct netdev *netdev, bool success, - void *user_data) -{ - struct device *device = user_data; - struct l_dbus_message *reply; - - if (!success) { - dbus_pending_reply(&device->disconnect_pending, - dbus_error_failed(device->disconnect_pending)); - return; - } - - device_disassociated(device); - - reply = l_dbus_message_new_method_return(device->disconnect_pending); - l_dbus_message_set_arguments(reply, ""); - dbus_pending_reply(&device->disconnect_pending, reply); -} - -static struct l_dbus_message *device_disconnect(struct l_dbus *dbus, - struct l_dbus_message *message, - void *user_data) -{ - struct device *device = user_data; - - l_debug(""); - - if (device->state == DEVICE_STATE_CONNECTING || - device->state == DEVICE_STATE_DISCONNECTING) - return dbus_error_busy(message); - - if (!device->connected_bss) - return dbus_error_not_connected(message); - - if (netdev_disconnect(device->netdev, device_disconnect_cb, device) < 0) - return dbus_error_failed(message); - - device_enter_state(device, DEVICE_STATE_DISCONNECTING); - - device->disconnect_pending = l_dbus_message_ref(message); - - return NULL; -} - -static struct l_dbus_message *device_get_networks(struct l_dbus *dbus, - struct l_dbus_message *message, - void *user_data) -{ - struct device *device = user_data; - struct l_dbus_message *reply; - struct l_dbus_message_builder *builder; - const struct l_queue_entry *entry; - - reply = l_dbus_message_new_method_return(message); - builder = l_dbus_message_builder_new(reply); - - l_dbus_message_builder_enter_array(builder, "(osns)"); - - for (entry = l_queue_get_entries(device->networks_sorted); entry; - entry = entry->next) { - const struct network *network = entry->data; - enum security security = network_get_security(network); - int32_t signal_strength = network_get_signal_strength(network); - - l_dbus_message_builder_enter_struct(builder, "osns"); - l_dbus_message_builder_append_basic(builder, 'o', - network_get_path(network)); - l_dbus_message_builder_append_basic(builder, 's', - network_get_ssid(network)); - l_dbus_message_builder_append_basic(builder, 'n', - &signal_strength); - l_dbus_message_builder_append_basic(builder, 's', - security_to_str(security)); - l_dbus_message_builder_leave_struct(builder); - } - - l_dbus_message_builder_leave_array(builder); - - l_dbus_message_builder_finalize(builder); - l_dbus_message_builder_destroy(builder); - - return reply; -} - -static bool device_property_get_name(struct l_dbus *dbus, - struct l_dbus_message *message, - struct l_dbus_message_builder *builder, - void *user_data) -{ - struct device *device = user_data; - - l_dbus_message_builder_append_basic(builder, 's', - netdev_get_name(device->netdev)); - return true; -} - -static bool device_property_get_address(struct l_dbus *dbus, - struct l_dbus_message *message, - struct l_dbus_message_builder *builder, - void *user_data) -{ - struct device *device = user_data; - const char *str; - - str = util_address_to_string(netdev_get_address(device->netdev)); - l_dbus_message_builder_append_basic(builder, 's', str); - - return true; -} - -static bool device_property_get_connected_network(struct l_dbus *dbus, - struct l_dbus_message *message, - struct l_dbus_message_builder *builder, - void *user_data) -{ - struct device *device = user_data; - if (!device->connected_network) - return false; - - l_dbus_message_builder_append_basic(builder, 'o', - network_get_path(device->connected_network)); - - return true; -} - -static void setup_device_interface(struct l_dbus_interface *interface) -{ - l_dbus_interface_method(interface, "Scan", 0, - device_scan, "", ""); - l_dbus_interface_method(interface, "Disconnect", 0, - device_disconnect, "", ""); - l_dbus_interface_method(interface, "GetOrderedNetworks", 0, - device_get_networks, "a(osns)", "", - "networks"); - - l_dbus_interface_property(interface, "Name", 0, "s", - device_property_get_name, NULL); - l_dbus_interface_property(interface, "Address", 0, "s", - device_property_get_address, NULL); - l_dbus_interface_property(interface, "ConnectedNetwork", 0, "o", - device_property_get_connected_network, - NULL); -} - -static bool bss_match(const void *a, const void *b) -{ - const struct scan_bss *bss_a = a; - const struct scan_bss *bss_b = b; - - return !memcmp(bss_a->addr, bss_b->addr, sizeof(bss_a->addr)); -} - -static void device_autoconnect_next(struct device *device) -{ - struct autoconnect_entry *entry; - int r; - - while ((entry = l_queue_pop_head(device->autoconnect_list))) { - l_debug("Considering autoconnecting to BSS '%s' with SSID: %s," - " freq: %u, rank: %u, strength: %i", - util_address_to_string(entry->bss->addr), - network_get_ssid(entry->network), - entry->bss->frequency, entry->rank, - entry->bss->signal_strength); - - /* TODO: Blacklist the network from auto-connect */ - r = network_autoconnect(entry->network, entry->bss); - l_free(entry); - - if (!r) - return; - } -} - static void wiphy_free(void *data) { struct wiphy *wiphy = data; @@ -389,184 +84,6 @@ static bool wiphy_match(const void *a, const void *b) return (wiphy->id == id); } -static bool process_network(const void *key, void *data, void *user_data) -{ - struct network *network = data; - struct device *device = user_data; - - if (!network_bss_list_isempty(network)) { - /* Build the network list ordered by rank */ - network_rank_update(network); - - l_queue_insert(device->networks_sorted, network, - network_rank_compare, NULL); - - return false; - } - - /* Drop networks that have no more BSSs in range */ - l_debug("No remaining BSSs for SSID: %s -- Removing network", - network_get_ssid(network)); - network_remove(network, -ERANGE); - - return true; -} - -static int autoconnect_rank_compare(const void *a, const void *b, void *user) -{ - const struct autoconnect_entry *new_ae = a; - const struct autoconnect_entry *ae = b; - - return ae->rank - new_ae->rank; -} - -static void process_bss(struct device *device, struct scan_bss *bss, - struct timespec *timestamp) -{ - struct network *network; - enum security security; - const char *path; - double rankmod; - struct autoconnect_entry *entry; - - l_debug("Found BSS '%s' with SSID: %s, freq: %u, rank: %u, " - "strength: %i", - util_address_to_string(bss->addr), - util_ssid_to_utf8(bss->ssid_len, bss->ssid), - bss->frequency, bss->rank, bss->signal_strength); - - if (!util_ssid_is_utf8(bss->ssid_len, bss->ssid)) { - l_warn("Ignoring BSS with non-UTF8 SSID"); - return; - } - - /* - * If both an RSN and a WPA elements are present currently - * RSN takes priority and the WPA IE is ignored. - */ - if (bss->rsne) { - struct ie_rsn_info rsne; - int res = ie_parse_rsne_from_data(bss->rsne, bss->rsne[1] + 2, - &rsne); - if (res < 0) { - l_debug("Cannot parse RSN field (%d, %s)", - res, strerror(-res)); - return; - } - - security = scan_get_security(bss->capability, &rsne); - - if (security == SECURITY_PSK) - bss->sha256 = - rsne.akm_suites & IE_RSN_AKM_SUITE_PSK_SHA256; - else if (security == SECURITY_8021X) - bss->sha256 = - rsne.akm_suites & IE_RSN_AKM_SUITE_8021X_SHA256; - } else if (bss->wpa) { - struct ie_rsn_info wpa; - int res = ie_parse_wpa_from_data(bss->wpa, bss->wpa[1] + 2, - &wpa); - if (res < 0) { - l_debug("Cannot parse WPA IE (%d, %s)", - res, strerror(-res)); - return; - } - - security = scan_get_security(bss->capability, &wpa); - } else - security = scan_get_security(bss->capability, NULL); - - path = iwd_network_get_path(device, bss->ssid, bss->ssid_len, - security); - - network = l_hashmap_lookup(device->networks, path); - if (!network) { - network = network_create(device, bss->ssid, bss->ssid_len, - security); - - if (!network_register(network, path)) { - network_remove(network, -EINVAL); - return; - } - - l_hashmap_insert(device->networks, - network_get_path(network), network); - l_debug("Added new Network \"%s\" security %s", - network_get_ssid(network), security_to_str(security)); - } - - if (network_bss_list_isempty(network)) - network_seen(network, timestamp); - - network_bss_add(network, bss); - - /* See if network is autoconnectable (is a known network) */ - if (!network_rankmod(network, &rankmod)) - return; - - entry = l_new(struct autoconnect_entry, 1); - entry->network = network; - entry->bss = bss; - entry->rank = bss->rank * rankmod; - l_queue_insert(device->autoconnect_list, entry, - autoconnect_rank_compare, NULL); -} - -static bool new_scan_results(uint32_t wiphy_id, uint32_t ifindex, - struct l_queue *bss_list, void *userdata) -{ - struct device *device = userdata; - struct network *network; - const struct l_queue_entry *bss_entry; - struct timespec now; - - clock_gettime(CLOCK_REALTIME, &now); - - device->old_bss_list = device->bss_list; - device->bss_list = bss_list; - - while ((network = l_queue_pop_head(device->networks_sorted))) - network_bss_list_clear(network); - - l_queue_destroy(device->autoconnect_list, l_free); - device->autoconnect_list = l_queue_new(); - - for (bss_entry = l_queue_get_entries(bss_list); bss_entry; - bss_entry = bss_entry->next) { - struct scan_bss *bss = bss_entry->data; - - process_bss(device, bss, &now); - } - - l_hashmap_foreach_remove(device->networks, process_network, device); - - if (device->connected_bss) { - struct scan_bss *bss; - - bss = l_queue_find(device->bss_list, bss_match, - device->connected_bss); - - if (!bss) { - l_warn("Connected BSS not in scan results!"); - l_queue_push_tail(device->bss_list, - device->connected_bss); - network_bss_add(device->connected_network, - device->connected_bss); - l_queue_remove(device->old_bss_list, - device->connected_bss); - } else - device->connected_bss = bss; - } - - l_queue_destroy(device->old_bss_list, bss_free); - device->old_bss_list = NULL; - - if (device->state == DEVICE_STATE_AUTOCONNECT) - device_autoconnect_next(device); - - return true; -} - struct wiphy *wiphy_find(int wiphy_id) { return l_queue_find(wiphy_list, wiphy_match, L_UINT_TO_PTR(wiphy_id)); @@ -935,12 +452,6 @@ bool wiphy_init(struct l_genl_family *in) l_queue_destroy(wiphy_list, NULL); } - if (!l_dbus_register_interface(dbus_get_bus(), - IWD_DEVICE_INTERFACE, - setup_device_interface, - NULL, true)) - return false; - nl80211 = in; if (!l_genl_family_register(nl80211, "config", wiphy_config_notify, @@ -978,7 +489,5 @@ bool wiphy_exit(void) nl80211 = NULL; - l_dbus_unregister_interface(dbus_get_bus(), IWD_DEVICE_INTERFACE); - return true; }