#include <string.h>
#include <stdint.h>
#include <syslog.h>
+#include <ctype.h>
#include <glib.h>
#include <gdbus.h>
void *data;
};
-struct _GSupplicantNetwork {
- GSupplicantInterface *interface;
- char *path;
- char *group;
- char *name;
- unsigned char ssid[32];
- unsigned int ssid_len;
- dbus_int16_t signal;
- GSupplicantMode mode;
- GSupplicantSecurity security;
- dbus_bool_t wps;
- GHashTable *bss_table;
- GHashTable *config_table;
-};
-
struct g_supplicant_bss {
GSupplicantInterface *interface;
char *path;
dbus_bool_t ieee8021x;
};
+struct _GSupplicantNetwork {
+ GSupplicantInterface *interface;
+ char *path;
+ char *group;
+ char *name;
+ unsigned char ssid[32];
+ unsigned int ssid_len;
+ dbus_int16_t signal;
+ struct g_supplicant_bss *best_bss;
+ GSupplicantMode mode;
+ GSupplicantSecurity security;
+ dbus_bool_t wps;
+ GHashTable *bss_table;
+ GHashTable *config_table;
+};
+
static inline void debug(const char *format, ...)
{
char str[256];
callbacks_pointer->network_removed(network);
}
+static void callback_network_changed(GSupplicantNetwork *network,
+ const char *property)
+{
+ if (callbacks_pointer == NULL)
+ return;
+
+ if (callbacks_pointer->network_changed == NULL)
+ return;
+
+ callbacks_pointer->network_changed(network, property);
+}
+
static void remove_interface(gpointer data)
{
GSupplicantInterface *interface = data;
network->ssid_len = bss->ssid_len;
memcpy(network->ssid, bss->ssid, bss->ssid_len);
network->signal = bss->signal;
+ network->best_bss = bss;
network->wps = FALSE;
if ((bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPS) != 0)
callback_network_added(network);
done:
+ if (bss->signal > network->signal) {
+ network->signal = bss->signal;
+ network->best_bss = bss;
+ callback_network_changed(network, "Signal");
+ }
+
g_hash_table_replace(interface->bss_mapping, bss->path, network);
g_hash_table_replace(network->bss_table, bss->path, bss);
if (ie == NULL || ie_len < 2)
return;
- for (ie_end = ie+ie_len; ie+ie[1]+1 <= ie_end; ie += ie[1]+2) {
+ for (ie_end = ie + ie_len; ie < ie_end && ie + ie[1] + 1 <= ie_end;
+ ie += ie[1] + 2) {
+
if (ie[0] != WMM_WPA1_WPS_INFO || ie[1] < WPS_INFO_MIN_LEN ||
memcmp(ie+2, WPS_OUI, sizeof(WPS_OUI)) != 0)
continue;
bss_property, bss);
}
+static void update_signal(gpointer key, gpointer value,
+ gpointer user_data)
+{
+ struct g_supplicant_bss *bss = value;
+ GSupplicantNetwork *network = user_data;
+
+ if (bss->signal > network->signal) {
+ network->signal = bss->signal;
+ network->best_bss = bss;
+ }
+}
+
+static void update_network_signal(GSupplicantNetwork *network)
+{
+ if (g_hash_table_size(network->bss_table) <= 1)
+ return;
+
+ g_hash_table_foreach(network->bss_table,
+ update_signal, network);
+
+ SUPPLICANT_DBG("New network signal %d", network->signal);
+}
+
static void interface_bss_removed(DBusMessageIter *iter, void *user_data)
{
GSupplicantInterface *interface = user_data;
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);
}
return;
supplicant_dbus_property_foreach(iter, bss_property, bss);
+
+ if (bss->signal == network->signal)
+ return;
+
+ /*
+ * If the new signal is lower than the SSID signal, we need
+ * to check for the new maximum.
+ */
+ if (bss->signal < network->signal) {
+ if (bss != network->best_bss)
+ return;
+ network->signal = bss->signal;
+ update_network_signal(network);
+ } else {
+ network->signal = bss->signal;
+ network->best_bss = bss;
+ }
+
+ SUPPLICANT_DBG("New network signal for %s %d dBm", network->ssid, network->signal);
+
+ callback_network_changed(network, "Signal");
}
static void wps_credentials(const char *key, DBusMessageIter *iter,
}
}
+static dbus_bool_t is_psk_raw_key(const char *psk)
+{
+ int i;
+
+ /* A raw key is always 64 bytes length... */
+ if (strlen(psk) != 64)
+ return FALSE;
+
+ /* ... and its content is in hex representation */
+ for (i = 0; i < 64; i++)
+ if (!isxdigit((unsigned char) psk[i]))
+ return FALSE;
+
+ return TRUE;
+}
+
static void add_network_security_psk(DBusMessageIter *dict,
GSupplicantSSID *ssid)
{
- if (ssid->passphrase && strlen(ssid->passphrase) > 0)
+ if (ssid->passphrase && strlen(ssid->passphrase) > 0) {
+
+ if (is_psk_raw_key(ssid->passphrase) == TRUE)
+ supplicant_dbus_property_append_fixed_array(dict,
+ "psk", DBUS_TYPE_BYTE,
+ &ssid->passphrase, 64);
+ else
supplicant_dbus_dict_append_basic(dict, "psk",
- DBUS_TYPE_STRING,
+ DBUS_TYPE_STRING,
&ssid->passphrase);
+ }
}
static void add_network_security_tls(DBusMessageIter *dict,
* The 2nd phase authentication method
* The 2nd phase passphrase
*
- * The Client certificate is optional although strongly required
+ * The Client certificate is optional although strongly recommended
* When setting it, we need in addition
* The Client private key file
* The Client private key file password
if (ssid->passphrase == NULL)
return;
- if (ssid->ca_cert_path == NULL)
- return;
-
if (ssid->phase2_auth == NULL)
return;
DBUS_TYPE_STRING,
&ssid->passphrase);
- supplicant_dbus_dict_append_basic(dict, "ca_cert",
+ if (ssid->ca_cert_path)
+ supplicant_dbus_dict_append_basic(dict, "ca_cert",
DBUS_TYPE_STRING,
&ssid->ca_cert_path);
case G_SUPPLICANT_SECURITY_WEP:
key_mgmt = "NONE";
add_network_security_wep(dict, ssid);
+ add_network_security_ciphers(dict, ssid);
break;
case G_SUPPLICANT_SECURITY_PSK:
key_mgmt = "WPA-PSK";