summaryrefslogtreecommitdiff
path: root/gsupplicant/supplicant.c
diff options
context:
space:
mode:
Diffstat (limited to 'gsupplicant/supplicant.c')
-rw-r--r--gsupplicant/supplicant.c161
1 files changed, 135 insertions, 26 deletions
diff --git a/gsupplicant/supplicant.c b/gsupplicant/supplicant.c
index 4f790122..6052f7b6 100644
--- a/gsupplicant/supplicant.c
+++ b/gsupplicant/supplicant.c
@@ -614,6 +614,30 @@ static void callback_network_associated(GSupplicantNetwork *network)
callbacks_pointer->network_associated(network);
}
+static void callback_sta_authorized(GSupplicantInterface *interface,
+ const char *addr)
+{
+ if (!callbacks_pointer)
+ return;
+
+ if (!callbacks_pointer->sta_authorized)
+ return;
+
+ callbacks_pointer->sta_authorized(interface, addr);
+}
+
+static void callback_sta_deauthorized(GSupplicantInterface *interface,
+ const char *addr)
+{
+ if (!callbacks_pointer)
+ return;
+
+ if (!callbacks_pointer->sta_deauthorized)
+ return;
+
+ callbacks_pointer->sta_deauthorized(interface, addr);
+}
+
static void callback_peer_found(GSupplicantPeer *peer)
{
if (!callbacks_pointer)
@@ -755,6 +779,8 @@ static void remove_bss(gpointer data)
{
struct g_supplicant_bss *bss = data;
+ supplicant_dbus_property_call_cancel_all(bss);
+
g_free(bss->path);
g_free(bss);
}
@@ -1499,7 +1525,6 @@ static void interface_network_added(DBusMessageIter *iter, void *user_data)
static void interface_network_removed(DBusMessageIter *iter, void *user_data)
{
SUPPLICANT_DBG("");
- return;
}
static char *create_name(unsigned char *ssid, int ssid_len)
@@ -1575,6 +1600,7 @@ static int add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
GSupplicantInterface *interface = bss->interface;
GSupplicantNetwork *network;
char *group;
+ bool is_new_network;
group = create_group(bss);
SUPPLICANT_DBG("New group created: %s", group);
@@ -1586,10 +1612,13 @@ static int add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
if (network) {
g_free(group);
SUPPLICANT_DBG("Network %s already exist", network->name);
+ is_new_network = false;
goto done;
}
+ is_new_network = true;
+
network = g_try_new0(GSupplicantNetwork, 1);
if (!network) {
g_free(group);
@@ -1609,6 +1638,11 @@ static int add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
network->frequency = bss->frequency;
network->best_bss = bss;
+ if ((bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPS) != 0) {
+ network->wps = TRUE;
+ network->wps_capabilities = bss->wps_capabilities;
+ }
+
SUPPLICANT_DBG("New network %s created", network->name);
network->bss_table = g_hash_table_new_full(g_str_hash, g_str_equal,
@@ -1626,7 +1660,10 @@ done:
/* We update network's WPS properties if only bss provides WPS. */
if ((bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPS) != 0) {
network->wps = TRUE;
- network->wps_capabilities |= bss->wps_capabilities;
+ network->wps_capabilities = bss->wps_capabilities;
+
+ if (!is_new_network)
+ callback_network_changed(network, "WPSCapabilities");
}
/*
@@ -2064,7 +2101,7 @@ static void interface_bss_added_without_keys(DBusMessageIter *iter,
supplicant_dbus_property_get_all(bss->path,
SUPPLICANT_INTERFACE ".BSS",
- bss_property, bss, NULL);
+ bss_property, bss, bss);
bss_compute_security(bss);
if (add_or_replace_bss_to_network(bss) < 0)
@@ -2169,6 +2206,7 @@ static void interface_bss_removed(DBusMessageIter *iter, void *user_data)
GSupplicantNetwork *network;
struct g_supplicant_bss *bss = NULL;
const char *path = NULL;
+ bool is_current_network_bss = false;
dbus_message_iter_get_basic(iter, &path);
if (!path)
@@ -2182,6 +2220,7 @@ static void interface_bss_removed(DBusMessageIter *iter, void *user_data)
if (network->best_bss == bss) {
network->best_bss = NULL;
network->signal = BSS_UNKNOWN_STRENGTH;
+ is_current_network_bss = true;
}
g_hash_table_remove(bss_mapping, path);
@@ -2191,8 +2230,12 @@ static void interface_bss_removed(DBusMessageIter *iter, void *user_data)
update_network_signal(network);
- if (g_hash_table_size(network->bss_table) == 0)
+ if (g_hash_table_size(network->bss_table) == 0) {
g_hash_table_remove(interface->network_table, network->group);
+ } else {
+ if (is_current_network_bss && network->best_bss)
+ callback_network_changed(network, "");
+ }
}
static void set_config_methods(DBusMessageIter *iter, void *user_data)
@@ -2718,11 +2761,48 @@ static void signal_network_removed(const char *path, DBusMessageIter *iter)
interface_network_removed(iter, interface);
}
+static void signal_sta_authorized(const char *path, DBusMessageIter *iter)
+{
+ GSupplicantInterface *interface;
+ const char *addr = NULL;
+
+ SUPPLICANT_DBG("");
+
+ interface = g_hash_table_lookup(interface_table, path);
+ if (!interface)
+ return;
+
+ dbus_message_iter_get_basic(iter, &addr);
+ if (!addr)
+ return;
+
+ callback_sta_authorized(interface, addr);
+}
+
+static void signal_sta_deauthorized(const char *path, DBusMessageIter *iter)
+{
+ GSupplicantInterface *interface;
+ const char *addr = NULL;
+
+ SUPPLICANT_DBG("");
+
+ interface = g_hash_table_lookup(interface_table, path);
+ if (!interface)
+ return;
+
+ dbus_message_iter_get_basic(iter, &addr);
+ if (!addr)
+ return;
+
+ callback_sta_deauthorized(interface, addr);
+}
+
static void signal_bss_changed(const char *path, DBusMessageIter *iter)
{
GSupplicantInterface *interface;
GSupplicantNetwork *network;
GSupplicantSecurity old_security;
+ unsigned int old_wps_capabilities;
struct g_supplicant_bss *bss;
SUPPLICANT_DBG("");
@@ -2747,18 +2827,18 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter)
if (old_security != bss->security) {
struct g_supplicant_bss *new_bss;
- SUPPLICANT_DBG("New network security for %s", bss->ssid);
+ SUPPLICANT_DBG("New network security for %s with path %s",
+ bss->ssid, bss->path);
- /* Security change policy:
- * - we first copy the current bss into a new one with
- * its own pointer (path)
- * - we remove the current bss related network which will
- * tell the plugin about such removal. This is done due
- * to the fact that a security change means a group change
- * so a complete network change.
- * (current bss becomes invalid as well)
- * - we add the new bss: it adds new network and tell the
- * plugin about it. */
+ /*
+ * Security change policy:
+ * - We first copy the current bss into a new one with
+ * its own pointer (path)
+ * - Clear the old bss pointer and remove the network completely
+ * if there are no more BSSs in the bss table.
+ * - The new bss will be added either to an existing network
+ * or an additional network will be created
+ */
new_bss = g_try_new0(struct g_supplicant_bss, 1);
if (!new_bss)
@@ -2767,20 +2847,43 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter)
memcpy(new_bss, bss, sizeof(struct g_supplicant_bss));
new_bss->path = g_strdup(bss->path);
- g_hash_table_remove(interface->network_table, network->group);
+ if (network->best_bss == bss) {
+ network->best_bss = NULL;
+ network->signal = BSS_UNKNOWN_STRENGTH;
+ }
+
+ g_hash_table_remove(bss_mapping, path);
+
+ g_hash_table_remove(interface->bss_mapping, path);
+ g_hash_table_remove(network->bss_table, path);
+
+ update_network_signal(network);
+
+ if (g_hash_table_size(network->bss_table) == 0)
+ g_hash_table_remove(interface->network_table,
+ network->group);
if (add_or_replace_bss_to_network(new_bss) < 0) {
- /* Remove entries in hash tables to handle the
- * failure in add_or_replace_bss_to_network
+ /*
+ * Prevent a memory leak on failure in
+ * add_or_replace_bss_to_network
*/
- g_hash_table_remove(bss_mapping, path);
- g_hash_table_remove(interface->bss_mapping, path);
- g_hash_table_remove(network->bss_table, path);
+ SUPPLICANT_DBG("Failed to add bss %s to network table",
+ new_bss->path);
+ g_free(new_bss->path);
+ g_free(new_bss);
}
return;
}
+ old_wps_capabilities = network->wps_capabilities;
+
+ if (old_wps_capabilities != bss->wps_capabilities) {
+ network->wps_capabilities = bss->wps_capabilities;
+ callback_network_changed(network, "WPSCapabilities");
+ }
+
/* Consider only property changes of the connected BSS */
if (network == interface->current_network && bss != network->best_bss)
return;
@@ -3468,6 +3571,8 @@ static struct {
{ SUPPLICANT_INTERFACE ".Interface", "BSSRemoved", signal_bss_removed },
{ SUPPLICANT_INTERFACE ".Interface", "NetworkAdded", signal_network_added },
{ SUPPLICANT_INTERFACE ".Interface", "NetworkRemoved", signal_network_removed },
+ { SUPPLICANT_INTERFACE ".Interface", "StaAuthorized", signal_sta_authorized },
+ { SUPPLICANT_INTERFACE ".Interface", "StaDeauthorized", signal_sta_deauthorized },
{ SUPPLICANT_INTERFACE ".BSS", "PropertiesChanged", signal_bss_changed },
@@ -4204,11 +4309,13 @@ static void interface_scan_params(DBusMessageIter *iter, void *user_data)
supplicant_dbus_dict_append_basic(&dict, "Type",
DBUS_TYPE_STRING, &type);
- supplicant_dbus_dict_append_array(&dict, "SSIDs",
- DBUS_TYPE_STRING,
- append_ssids,
- data->scan_params);
+ if (data->scan_params->ssids) {
+ supplicant_dbus_dict_append_array(&dict, "SSIDs",
+ DBUS_TYPE_STRING,
+ append_ssids,
+ data->scan_params);
+ }
supplicant_add_scan_frequency(&dict, add_scan_frequencies,
data->scan_params);
} else
@@ -4597,7 +4704,9 @@ static void add_network_security_peap(DBusMessageIter *dict,
}
- if (g_str_has_prefix(ssid->phase2_auth, "EAP-")) {
+ if(g_strcmp0(ssid->phase2_auth, "GTC") == 0 && g_strcmp0(ssid->eap, "ttls") == 0)
+ phase2_auth = g_strdup_printf("autheap=%s", ssid->phase2_auth);
+ else if (g_str_has_prefix(ssid->phase2_auth, "EAP-")) {
phase2_auth = g_strdup_printf("autheap=%s",
ssid->phase2_auth + strlen("EAP-"));
} else