#define G_SUPPLICANT_PAIRWISE_TKIP (1 << 1)
#define G_SUPPLICANT_PAIRWISE_CCMP (1 << 2)
-#define G_SUPPLICANT_MAX_FAST_SCAN 4
-
#define G_SUPPLICANT_WPS_CONFIGURED (1 << 0)
#define G_SUPPLICANT_WPS_PBC (1 << 1)
#define G_SUPPLICANT_WPS_PIN (1 << 2)
typedef struct _GSupplicantSSID GSupplicantSSID;
+/*
+ * Max number of SSIDs that can be scanned.
+ * In wpa_s 0.7x the limit is 4.
+ * In wps_s 0.8 or later it is 16.
+ * The value is only used if wpa_supplicant does not return any max limit
+ * for number of scannable SSIDs.
+ */
+#define WPAS_MAX_SCAN_SSIDS 4
+
+struct scan_ssid {
+ unsigned char ssid[32];
+ uint8_t ssid_len;
+};
+
struct _GSupplicantScanParams {
- struct scan_ssid {
- unsigned char ssid[32];
- uint8_t ssid_len;
- } ssids[G_SUPPLICANT_MAX_FAST_SCAN];
+ GSList *ssids;
uint8_t num_ssids;
- uint16_t freqs[G_SUPPLICANT_MAX_FAST_SCAN];
+ uint16_t *freqs;
};
typedef struct _GSupplicantScanParams GSupplicantScanParams;
int g_supplicant_register(const GSupplicantCallbacks *callbacks);
void g_supplicant_unregister(const GSupplicantCallbacks *callbacks);
+static inline
+void g_supplicant_free_scan_params(GSupplicantScanParams *scan_params)
+{
+ g_slist_free_full(scan_params->ssids, g_free);
+ g_free(scan_params->freqs);
+ g_free(scan_params);
+}
+
#ifdef __cplusplus
}
#endif
if (interface == NULL)
return 0;
+ if (interface->max_scan_ssids == 0)
+ return WPAS_MAX_SCAN_SSIDS;
+
return interface->max_scan_ssids;
}
}
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 (i = 0; i < scan_data->num_ssids; i++)
- append_ssid(iter, scan_data->ssids[i].ssid,
- scan_data->ssids[i].ssid_len);
+ for (list = scan_data->ssids; list; list = list->next) {
+ struct scan_ssid *scan_ssid = list->data;
+
+ 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);
int driver_max_scan_ssids)
{
unsigned int i;
+ struct scan_ssid *scan_ssid;
if (driver_max_scan_ssids > scan_data->num_ssids && hex_ssid != NULL) {
gchar *ssid;
ssid[j++] = hex;
}
- memcpy(scan_data->ssids[scan_data->num_ssids].ssid, ssid, j);
- scan_data->ssids[scan_data->num_ssids].ssid_len = j;
+ scan_ssid = g_try_new(struct scan_ssid, 1);
+ if (scan_ssid == NULL) {
+ g_free(ssid);
+ return -ENOMEM;
+ }
+
+ memcpy(scan_ssid->ssid, ssid, j);
+ scan_ssid->ssid_len = j;
+ scan_data->ssids = g_slist_prepend(scan_data->ssids,
+ scan_ssid);
+
scan_data->num_ssids++;
g_free(ssid);
+ } else
+ return -EINVAL;
+
+ scan_data->ssids = g_slist_reverse(scan_data->ssids);
+
+ if (scan_data->freqs == NULL) {
+ scan_data->freqs = g_try_malloc0(sizeof(uint16_t) *
+ scan_data->num_ssids);
+ if (scan_data->freqs == NULL) {
+ g_slist_free_full(scan_data->ssids, g_free);
+ return -ENOMEM;
+ }
+ } else {
+ scan_data->freqs = g_try_realloc(scan_data->freqs,
+ sizeof(uint16_t) * scan_data->num_ssids);
+ if (scan_data->freqs == NULL) {
+ g_slist_free_full(scan_data->ssids, g_free);
+ return -ENOMEM;
+ }
+ scan_data->freqs[scan_data->num_ssids - 1] = 0;
}
/* Don't add duplicate entries */
- for (i = 0; i < G_SUPPLICANT_MAX_FAST_SCAN; i++) {
+ for (i = 0; i < scan_data->num_ssids; i++) {
if (scan_data->freqs[i] == 0) {
scan_data->freqs[i] = freq;
break;
g_strfreev(services);
- num_ssids = num_ssids > G_SUPPLICANT_MAX_FAST_SCAN ?
- G_SUPPLICANT_MAX_FAST_SCAN : num_ssids;
+ num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
iter = g_sequence_get_begin_iter(latest_list);
ret = get_latest_connections(driver_max_ssids, scan_params);
if (ret <= 0) {
- g_free(scan_params);
+ g_supplicant_free_scan_params(scan_params);
return wifi_scan(device);
}
if (ret == 0)
connman_device_set_scanning(device, TRUE);
else {
- g_free(scan_params);
+ g_supplicant_free_scan_params(scan_params);
connman_device_unref(device);
}
{
struct wifi_data *wifi = connman_device_get_data(device);
GSupplicantScanParams *scan_params = NULL;
+ struct scan_ssid *scan_ssid;
struct hidden_params *hidden;
int ret;
scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
if (scan_params == NULL)
return -ENOMEM;
- memcpy(scan_params->ssids[0].ssid, ssid, ssid_len);
- scan_params->ssids[0].ssid_len = ssid_len;
+
+ scan_ssid = g_try_new(struct scan_ssid, 1);
+ if (scan_ssid == NULL) {
+ g_free(scan_params);
+ return -ENOMEM;
+ }
+
+ memcpy(scan_ssid->ssid, ssid, ssid_len);
+ scan_ssid->ssid_len = ssid_len;
+ scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
+
scan_params->num_ssids = 1;
hidden = g_try_new0(struct hidden_params, 1);
connman_device_set_scanning(device, TRUE);
else {
connman_device_unref(device);
- g_free(scan_params);
+ g_supplicant_free_scan_params(scan_params);
hidden_free(wifi->hidden);
wifi->hidden = NULL;
}