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;
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);
network->frequency = bss->frequency;
network->best_bss = bss;
- network->wps = FALSE;
- 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,
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,
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) {
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)
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
/* Security change policy:
* - we first copy the current bss into a new one with
* its own pointer (path)
- * - we remove the current bss related nework which will
+ * - 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.
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;
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;
}
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);
}
}
/* 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);
}