*
* WPA supplicant library with GLib integration
*
- * Copyright (C) 2010 Intel Corporation. All rights reserved.
+ * Copyright (C) 2012 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
dbus_int16_t signal;
GSupplicantMode mode;
GSupplicantSecurity security;
+ dbus_bool_t rsn_selected;
+ unsigned int wpa_keymgmt;
+ unsigned int wpa_pairwise;
+ unsigned int wpa_group;
+ unsigned int rsn_keymgmt;
+ unsigned int rsn_pairwise;
+ unsigned int rsn_group;
unsigned int keymgmt;
- unsigned int pairwise;
- unsigned int group;
dbus_bool_t privacy;
dbus_bool_t psk;
dbus_bool_t ieee8021x;
+ unsigned int wps_capabilities;
};
struct _GSupplicantNetwork {
GSupplicantMode mode;
GSupplicantSecurity security;
dbus_bool_t wps;
+ unsigned int wps_capabilities;
GHashTable *bss_table;
GHashTable *config_table;
};
g_hash_table_destroy(interface->net_mapping);
g_hash_table_destroy(interface->network_table);
+ if (interface->scan_callback != NULL) {
+ SUPPLICANT_DBG("call interface %p callback %p scanning %d",
+ interface, interface->scan_callback,
+ interface->scanning);
+
+ interface->scan_callback(-EIO, interface, interface->scan_data);
+ interface->scan_callback = NULL;
+ interface->scan_data = NULL;
+
+ if (interface->scanning == TRUE) {
+ interface->scanning = FALSE;
+ callback_scan_finished(interface);
+ }
+ }
+
callback_interface_removed(interface);
g_free(interface->wps_cred.key);
if (interface == NULL)
return 0;
+ if (interface->max_scan_ssids == 0)
+ return WPAS_MAX_SCAN_SSIDS;
+
return interface->max_scan_ssids;
}
+static void set_network_enabled(DBusMessageIter *iter, void *user_data)
+{
+ dbus_bool_t enable = *(dbus_bool_t *)user_data;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &enable);
+}
+
+int g_supplicant_interface_enable_selected_network(GSupplicantInterface *interface,
+ dbus_bool_t enable)
+{
+ if (interface == NULL)
+ return -1;
+
+ if (interface->network_path == NULL)
+ return -1;
+
+ SUPPLICANT_DBG(" ");
+ return supplicant_dbus_property_set(interface->network_path,
+ SUPPLICANT_INTERFACE ".Network",
+ "Enabled", DBUS_TYPE_BOOLEAN_AS_STRING,
+ set_network_enabled, NULL, &enable);
+}
+
+dbus_bool_t g_supplicant_interface_get_ready(GSupplicantInterface *interface)
+{
+ if (interface == NULL)
+ return FALSE;
+
+ return interface->ready;
+}
+
GSupplicantInterface *g_supplicant_network_get_interface(
GSupplicantNetwork *network)
{
return network->wps;
}
+dbus_bool_t g_supplicant_network_is_wps_active(GSupplicantNetwork *network)
+{
+ if (network == NULL)
+ return FALSE;
+
+ if (network->wps_capabilities & G_SUPPLICANT_WPS_CONFIGURED)
+ return TRUE;
+
+ return FALSE;
+}
+
+dbus_bool_t g_supplicant_network_is_wps_pbc(GSupplicantNetwork *network)
+{
+ if (network == NULL)
+ return FALSE;
+
+ if (network->wps_capabilities & G_SUPPLICANT_WPS_PBC)
+ return TRUE;
+
+ return FALSE;
+}
+
+dbus_bool_t g_supplicant_network_is_wps_advertizing(GSupplicantNetwork *network)
+{
+ if (network == NULL)
+ return FALSE;
+
+ if (network->wps_capabilities & G_SUPPLICANT_WPS_REGISTRAR)
+ return TRUE;
+
+ return FALSE;
+}
+
static void merge_network(GSupplicantNetwork *network)
{
GString *str;
static char *create_name(unsigned char *ssid, int ssid_len)
{
- char *name;
- int i;
+ GString *string;
+ const gchar *remainder, *invalid;
+ int valid_bytes, remaining_bytes;
if (ssid_len < 1 || ssid[0] == '\0')
- name = NULL;
- else
- name = g_try_malloc0(ssid_len + 1);
-
- if (name == NULL)
return g_strdup("");
- for (i = 0; i < ssid_len; i++) {
- if (g_ascii_isprint(ssid[i]))
- name[i] = ssid[i];
- else
- name[i] = ' ';
+ string = NULL;
+ remainder = (const gchar *)ssid;
+ remaining_bytes = ssid_len;
+
+ while (remaining_bytes != 0) {
+ if (g_utf8_validate(remainder, remaining_bytes,
+ &invalid) == TRUE) {
+ break;
+ }
+
+ valid_bytes = invalid - remainder;
+
+ if (string == NULL)
+ string = g_string_sized_new(remaining_bytes);
+
+ g_string_append_len(string, remainder, valid_bytes);
+
+ /* append U+FFFD REPLACEMENT CHARACTER */
+ g_string_append(string, "\357\277\275");
+
+ remaining_bytes -= valid_bytes + 1;
+ remainder = invalid + 1;
}
- return name;
+ if (string == NULL)
+ return g_strndup((const gchar *)ssid, ssid_len + 1);
+
+ g_string_append(string, remainder);
+
+ return g_string_free(string, FALSE);
}
static char *create_group(struct g_supplicant_bss *bss)
return g_string_free(str, FALSE);
}
-static void add_bss_to_network(struct g_supplicant_bss *bss)
+static void add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
{
GSupplicantInterface *interface = bss->interface;
GSupplicantNetwork *network;
char *group;
group = create_group(bss);
+ SUPPLICANT_DBG("New group created: %s", group);
+
if (group == NULL)
return;
network = g_hash_table_lookup(interface->network_table, group);
if (network != NULL) {
g_free(group);
+ SUPPLICANT_DBG("Network %s already exist", network->name);
+
goto done;
}
network->frequency = bss->frequency;
network->best_bss = bss;
- network->wps = FALSE;
- if ((bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPS) != 0)
- network->wps = TRUE;
+ SUPPLICANT_DBG("New network %s created", network->name);
network->bss_table = g_hash_table_new_full(g_str_hash, g_str_equal,
NULL, remove_bss);
callback_network_added(network);
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;
+ }
+
if (bss->signal > network->signal) {
network->signal = bss->signal;
network->best_bss = bss;
static void bss_keymgmt(DBusMessageIter *iter, void *user_data)
{
- struct g_supplicant_bss *bss = user_data;
+ unsigned int *keymgmt = user_data;
const char *str = NULL;
int i;
for (i = 0; keymgmt_map[i].str != NULL; i++)
if (strcmp(str, keymgmt_map[i].str) == 0) {
- bss->keymgmt |= keymgmt_map[i].val;
+ SUPPLICANT_DBG("Keymgmt: %s", str);
+ *keymgmt |= keymgmt_map[i].val;
break;
}
}
static void bss_group(DBusMessageIter *iter, void *user_data)
{
- struct g_supplicant_bss *bss = user_data;
+ unsigned int *group = user_data;
const char *str = NULL;
int i;
for (i = 0; group_map[i].str != NULL; i++)
if (strcmp(str, group_map[i].str) == 0) {
- bss->group |= group_map[i].val;
+ SUPPLICANT_DBG("Group: %s", str);
+ *group |= group_map[i].val;
break;
}
}
static void bss_pairwise(DBusMessageIter *iter, void *user_data)
{
- struct g_supplicant_bss *bss = user_data;
+ unsigned int *pairwise = user_data;
const char *str = NULL;
int i;
for (i = 0; pairwise_map[i].str != NULL; i++)
if (strcmp(str, pairwise_map[i].str) == 0) {
- bss->pairwise |= pairwise_map[i].val;
+ SUPPLICANT_DBG("Pairwise: %s", str);
+ *pairwise |= pairwise_map[i].val;
break;
}
}
static void bss_wpa(const char *key, DBusMessageIter *iter,
void *user_data)
{
- if (g_strcmp0(key, "KeyMgmt") == 0)
- supplicant_dbus_array_foreach(iter, bss_keymgmt, user_data);
- else if (g_strcmp0(key, "Group") == 0)
- supplicant_dbus_array_foreach(iter, bss_group, user_data);
- else if (g_strcmp0(key, "Pairwise") == 0)
- supplicant_dbus_array_foreach(iter, bss_pairwise, user_data);
+ struct g_supplicant_bss *bss = user_data;
+ unsigned int value = 0;
+
+ SUPPLICANT_DBG("Key: %s", key);
+
+ if (g_strcmp0(key, "KeyMgmt") == 0) {
+ supplicant_dbus_array_foreach(iter, bss_keymgmt, &value);
+ if (bss->rsn_selected == TRUE)
+ bss->rsn_keymgmt = value;
+ else
+ bss->wpa_keymgmt = value;
+ } else if (g_strcmp0(key, "Group") == 0) {
+ supplicant_dbus_array_foreach(iter, bss_group, &value);
+
+ if (bss->rsn_selected == TRUE)
+ bss->rsn_group = value;
+ else
+ bss->wpa_group = value;
+ } else if (g_strcmp0(key, "Pairwise") == 0) {
+ supplicant_dbus_array_foreach(iter, bss_pairwise, &value);
+
+ if (bss->rsn_selected == TRUE)
+ bss->rsn_pairwise = value;
+ else
+ bss->wpa_pairwise = value;
+ }
}
static unsigned int get_tlv(unsigned char *ie, unsigned int ie_size,
const unsigned char WPS_OUI[] = { 0x00, 0x50, 0xf2, 0x04 };
unsigned char *ie, *ie_end;
DBusMessageIter array;
+ unsigned int value;
int ie_len;
#define WMM_WPA1_WPS_INFO 221
#define WPS_INFO_MIN_LEN 6
#define WPS_VERSION_TLV 0x104A
#define WPS_STATE_TLV 0x1044
+#define WPS_METHODS_TLV 0x1012
+#define WPS_REGISTRAR_TLV 0x1041
#define WPS_VERSION 0x10
+#define WPS_PBC 0x04
+#define WPS_PIN 0x00
+#define WPS_CONFIGURED 0x02
dbus_message_iter_recurse(iter, &array);
dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
if (ie == NULL || ie_len < 2)
return;
+ bss->wps_capabilities = 0;
+ bss->keymgmt = 0;
+
for (ie_end = ie + ie_len; ie < ie_end && ie + ie[1] + 1 <= ie_end;
ie += ie[1] + 2) {
SUPPLICANT_DBG("IE: match WPS_OUI");
- if (get_tlv(&ie[6], ie[1],
- WPS_VERSION_TLV) == WPS_VERSION &&
- get_tlv(&ie[6], ie[1],
- WPS_STATE_TLV) != 0)
+ value = get_tlv(&ie[6], ie[1], WPS_STATE_TLV);
+ if (get_tlv(&ie[6], ie[1], WPS_VERSION_TLV) == WPS_VERSION &&
+ value != 0) {
bss->keymgmt |= G_SUPPLICANT_KEYMGMT_WPS;
+
+ if (value == WPS_CONFIGURED)
+ bss->wps_capabilities |=
+ G_SUPPLICANT_WPS_CONFIGURED;
+ }
+
+ value = get_tlv(&ie[6], ie[1], WPS_METHODS_TLV);
+ if (value != 0) {
+ if (GUINT16_FROM_BE(value) == WPS_PBC)
+ bss->wps_capabilities |= G_SUPPLICANT_WPS_PBC;
+ if (GUINT16_FROM_BE(value) == WPS_PIN)
+ bss->wps_capabilities |= G_SUPPLICANT_WPS_PIN;
+ } else
+ bss->wps_capabilities |=
+ G_SUPPLICANT_WPS_PBC | G_SUPPLICANT_WPS_PIN;
+
+ /* If the AP sends this it means it's advertizing
+ * as a registrar and the WPS process is launched
+ * on its side */
+ if (get_tlv(&ie[6], ie[1], WPS_REGISTRAR_TLV) != 0)
+ bss->wps_capabilities |= G_SUPPLICANT_WPS_REGISTRAR;
+
+ SUPPLICANT_DBG("WPS Methods 0x%x", bss->wps_capabilities);
}
}
+static void bss_compute_security(struct g_supplicant_bss *bss)
+{
+ /*
+ * Combining RSN and WPA keymgmt
+ * We combine it since parsing IEs might have set something for WPS. */
+ bss->keymgmt |= bss->rsn_keymgmt | bss->wpa_keymgmt;
+
+ bss->ieee8021x = FALSE;
+ bss->psk = FALSE;
+
+ if (bss->keymgmt &
+ (G_SUPPLICANT_KEYMGMT_WPA_EAP |
+ G_SUPPLICANT_KEYMGMT_WPA_FT_EAP |
+ G_SUPPLICANT_KEYMGMT_WPA_EAP_256))
+ bss->ieee8021x = TRUE;
+
+ if (bss->keymgmt &
+ (G_SUPPLICANT_KEYMGMT_WPA_PSK |
+ G_SUPPLICANT_KEYMGMT_WPA_FT_PSK |
+ G_SUPPLICANT_KEYMGMT_WPA_PSK_256))
+ bss->psk = TRUE;
+
+ if (bss->ieee8021x == TRUE)
+ bss->security = G_SUPPLICANT_SECURITY_IEEE8021X;
+ else if (bss->psk == TRUE)
+ bss->security = G_SUPPLICANT_SECURITY_PSK;
+ else if (bss->privacy == TRUE)
+ bss->security = G_SUPPLICANT_SECURITY_WEP;
+ else
+ bss->security = G_SUPPLICANT_SECURITY_NONE;
+}
+
+
static void bss_property(const char *key, DBusMessageIter *iter,
void *user_data)
{
SUPPLICANT_DBG("key %s", key);
- if (key == NULL) {
- if (bss->ieee8021x == TRUE)
- bss->security = G_SUPPLICANT_SECURITY_IEEE8021X;
- else if (bss->psk == TRUE)
- bss->security = G_SUPPLICANT_SECURITY_PSK;
- else if (bss->privacy == TRUE)
- bss->security = G_SUPPLICANT_SECURITY_WEP;
- else
- bss->security = G_SUPPLICANT_SECURITY_NONE;
-
- add_bss_to_network(bss);
+ if (key == NULL)
return;
- }
if (g_strcmp0(key, "BSSID") == 0) {
DBusMessageIter array;
dbus_message_iter_get_basic(iter, &privacy);
bss->privacy = privacy;
- } else if ((g_strcmp0(key, "RSN") == 0) ||
- (g_strcmp0(key, "WPA") == 0)) {
- supplicant_dbus_property_foreach(iter, bss_wpa, bss);
+ } else if (g_strcmp0(key, "RSN") == 0) {
+ bss->rsn_selected = TRUE;
- if (bss->keymgmt &
- (G_SUPPLICANT_KEYMGMT_WPA_EAP |
- G_SUPPLICANT_KEYMGMT_WPA_FT_EAP |
- G_SUPPLICANT_KEYMGMT_WPA_EAP_256))
- bss->ieee8021x = TRUE;
+ supplicant_dbus_property_foreach(iter, bss_wpa, bss);
+ } else if (g_strcmp0(key, "WPA") == 0) {
+ bss->rsn_selected = FALSE;
- if (bss->keymgmt &
- (G_SUPPLICANT_KEYMGMT_WPA_PSK |
- G_SUPPLICANT_KEYMGMT_WPA_FT_PSK |
- G_SUPPLICANT_KEYMGMT_WPA_PSK_256))
- bss->psk = TRUE;
+ supplicant_dbus_property_foreach(iter, bss_wpa, bss);
} else if (g_strcmp0(key, "IEs") == 0)
bss_process_ies(iter, bss);
else
return;
supplicant_dbus_property_foreach(iter, bss_property, bss);
- bss_property(NULL, NULL, bss);
+
+ bss_compute_security(bss);
+ add_or_replace_bss_to_network(bss);
}
static void interface_bss_added_without_keys(DBusMessageIter *iter,
supplicant_dbus_property_get_all(bss->path,
SUPPLICANT_INTERFACE ".BSS",
bss_property, bss);
+
+ bss_compute_security(bss);
+ add_or_replace_bss_to_network(bss);
}
static void update_signal(gpointer key, gpointer value,
{
GSupplicantInterface *interface;
GSupplicantNetwork *network;
+ GSupplicantSecurity old_security;
struct g_supplicant_bss *bss;
SUPPLICANT_DBG("");
supplicant_dbus_property_foreach(iter, bss_property, bss);
+ old_security = network->security;
+ bss_compute_security(bss);
+
+ if (old_security != bss->security) {
+ struct g_supplicant_bss *new_bss;
+
+ SUPPLICANT_DBG("New network security for %s", bss->ssid);
+
+ /* 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. */
+
+ new_bss = g_try_new0(struct g_supplicant_bss, 1);
+ if (new_bss == NULL)
+ return;
+
+ 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);
+
+ add_or_replace_bss_to_network(new_bss);
+
+ return;
+ }
+
if (bss->signal == network->signal)
return;
struct supplicant_regdom {
GSupplicantCountryCallback callback;
+ const char *alpha2;
const void *user_data;
};
DBusMessageIter *iter, void *user_data)
{
struct supplicant_regdom *regdom = user_data;
- char *alpha2;
+ int result = 0;
SUPPLICANT_DBG("Country setting result");
if (user_data == NULL)
return;
- if (error == NULL) {
- alpha2 = (char *)regdom->user_data;
- } else {
+ if (error != NULL) {
SUPPLICANT_DBG("Country setting failure %s", error);
- alpha2 = NULL;
+ result = -EINVAL;
}
if (regdom->callback)
- regdom->callback(alpha2);
+ regdom->callback(result, regdom->alpha2,
+ (void *) regdom->user_data);
g_free(regdom);
}
static void country_params(DBusMessageIter *iter, void *user_data)
{
struct supplicant_regdom *regdom = user_data;
- const char *country;
- country = regdom->user_data;
-
- dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &country);
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
+ ®dom->alpha2);
}
int g_supplicant_set_country(const char *alpha2,
return -ENOMEM;
regdom->callback = callback;
+ regdom->alpha2 = alpha2;
regdom->user_data = user_data;
return supplicant_dbus_property_set(SUPPLICANT_PATH, SUPPLICANT_INTERFACE,
regdom);
}
+int g_supplicant_interface_set_country(GSupplicantInterface *interface,
+ GSupplicantCountryCallback callback,
+ const char *alpha2,
+ void *user_data)
+{
+ struct supplicant_regdom *regdom;
+
+ regdom = dbus_malloc0(sizeof(*regdom));
+ if (regdom == NULL)
+ return -ENOMEM;
+
+ regdom->callback = callback;
+ regdom->alpha2 = alpha2;
+ regdom->user_data = user_data;
+
+ return supplicant_dbus_property_set(interface->path,
+ SUPPLICANT_INTERFACE ".Interface",
+ "Country", DBUS_TYPE_STRING_AS_STRING,
+ country_params, country_result,
+ regdom);
+}
+
struct interface_data {
GSupplicantInterface *interface;
GSupplicantInterfaceCallback callback;
void *user_data;
};
+struct interface_autoscan_data {
+ GSupplicantInterface *interface;
+ GSupplicantInterfaceCallback callback;
+ const char *autoscan_params;
+ void *user_data;
+};
+
static void interface_create_property(const char *key, DBusMessageIter *iter,
void *user_data)
{
SUPPLICANT_DBG("");
if (error != NULL) {
- g_critical("error %s", error);
+ g_warning("error %s", error);
err = -EIO;
goto done;
}
if (error != NULL) {
SUPPLICANT_DBG("Interface not created yet");
- err = -EIO;
goto create;
}
}
if (data != NULL && data->scan_params != NULL)
- g_free(data->scan_params);
+ g_supplicant_free_scan_params(data->scan_params);
dbus_free(data);
}
unsigned int freq;
int i;
- for (i = 0; i < G_SUPPLICANT_MAX_FAST_SCAN; i++) {
+ for (i = 0; i < scan_data->num_ssids; i++) {
freq = scan_data->freqs[i];
if (!freq)
break;
static void append_ssids(DBusMessageIter *iter, void *user_data)
{
GSupplicantScanParams *scan_data = user_data;
- int i;
+ GSList *list;
+
+ for (list = scan_data->ssids; list; list = list->next) {
+ struct scan_ssid *scan_ssid = list->data;
- for (i = 0; i < scan_data->num_ssids; i++)
- append_ssid(iter, scan_data->ssids[i].ssid,
- scan_data->ssids[i].ssid_len);
+ append_ssid(iter, scan_ssid->ssid, scan_ssid->ssid_len);
+ }
}
static void supplicant_add_scan_frequency(DBusMessageIter *dict,
DBusMessageIter entry, value, array;
const char *key = "Channels";
- if (scan_params->freqs[0] != 0) {
+ if (scan_params->freqs && scan_params->freqs[0] != 0) {
dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
NULL, &entry);
return ret;
}
+static void interface_autoscan_result(const char *error,
+ DBusMessageIter *iter, void *user_data)
+{
+ struct interface_autoscan_data *data = user_data;
+ int err = 0;
+
+ if (error != NULL) {
+ SUPPLICANT_DBG("error %s", error);
+ err = -EIO;
+ }
+
+ if (data != NULL && data->callback != NULL)
+ data->callback(err, data->interface, data->user_data);
+
+ dbus_free(data);
+}
+
+static void interface_autoscan_params(DBusMessageIter *iter, void *user_data)
+{
+ struct interface_autoscan_data *data = user_data;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
+ &data->autoscan_params);
+}
+
+int g_supplicant_interface_autoscan(GSupplicantInterface *interface,
+ const char *autoscan_data,
+ GSupplicantInterfaceCallback callback,
+ void *user_data)
+{
+ struct interface_autoscan_data *data;
+ int ret;
+
+ data = dbus_malloc0(sizeof(*data));
+ if (data == NULL)
+ return -ENOMEM;
+
+ data->interface = interface;
+ data->callback = callback;
+ data->autoscan_params = autoscan_data;
+ data->user_data = user_data;
+
+ ret = supplicant_dbus_method_call(interface->path,
+ SUPPLICANT_INTERFACE ".Interface", "AutoScan",
+ interface_autoscan_params,
+ interface_autoscan_result, data);
+ if (ret < 0)
+ dbus_free(data);
+
+ return ret;
+}
+
static int parse_supplicant_error(DBusMessageIter *iter)
{
int err = -ECANCELED;
char *key;
+ /* If the given passphrase is malformed wpa_s returns
+ * "invalid message format" but this error should be interpreted as
+ * invalid-key.
+ */
while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) {
dbus_message_iter_get_basic(iter, &key);
- if (strncmp(key, "psk", 4) == 0 ||
- strncmp(key, "wep_key", 7) == 0) {
+ if (strncmp(key, "psk", 3) == 0 ||
+ strncmp(key, "wep_key", 7) == 0 ||
+ strcmp(key, "invalid message format") == 0) {
err = -ENOKEY;
break;
}
return TRUE;
}
+static unsigned char hexchar2bin(char c)
+{
+ if ((c >= '0') && (c <= '9'))
+ return c - '0';
+ else if ((c >= 'A') && (c <= 'F'))
+ return c - 'A' + 10;
+ else if ((c >= 'a') && (c <= 'f'))
+ return c - 'a' + 10;
+ else
+ return c;
+}
+
+static void hexstring2bin(const char *string, unsigned char *data, size_t data_len)
+{
+ size_t i;
+
+ for (i = 0; i < data_len; i++)
+ data[i] = (hexchar2bin(string[i * 2 + 0]) << 4 |
+ hexchar2bin(string[i * 2 + 1]) << 0);
+}
+
static void add_network_security_psk(DBusMessageIter *dict,
GSupplicantSSID *ssid)
{
if (ssid->passphrase && strlen(ssid->passphrase) > 0) {
+ const char *key = "psk";
- 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,
+ if (is_psk_raw_key(ssid->passphrase) == TRUE) {
+ unsigned char data[32];
+ unsigned char *datap = data;
+
+ /* The above pointer alias is required by D-Bus because
+ * with D-Bus and GCC, non-heap-allocated arrays cannot
+ * be passed directly by their base pointer. */
+
+ hexstring2bin(ssid->passphrase, datap, sizeof(data));
+
+ supplicant_dbus_dict_append_fixed_array(dict,
+ key, DBUS_TYPE_BYTE,
+ &datap, sizeof(data));
+ } else
+ supplicant_dbus_dict_append_basic(dict,
+ key, DBUS_TYPE_STRING,
&ssid->passphrase);
}
}
supplicant_dbus_dict_append_basic(&dict, "frequency",
DBUS_TYPE_UINT32, &ssid->freq);
+ if (ssid->bgscan != NULL)
+ supplicant_dbus_dict_append_basic(&dict, "bgscan",
+ DBUS_TYPE_STRING, &ssid->bgscan);
+
add_network_mode(&dict, ssid);
add_network_security(&dict, ssid);
/* If we are disconnecting from previous WPS successful
* association. i.e.: it did not went through AddNetwork,
* and interface->network_path was never set. */
- if (data->interface->network_path == NULL)
+ if (data->interface->network_path == NULL) {
+ dbus_free(data);
return;
+ }
network_remove(data);
}
callback_system_killed();
if (interface_table != NULL) {
- g_hash_table_foreach(interface_table,
+ g_hash_table_foreach(interface_table,
unregister_remove_interface, NULL);
g_hash_table_destroy(interface_table);
interface_table = NULL;