gsupplicant: Return max SSIDs to scan given by wpa_supplicant
[platform/upstream/connman.git] / gsupplicant / supplicant.c
index decf5fa..e298bb5 100644 (file)
@@ -287,6 +287,8 @@ static GSupplicantState string2state(const char *state)
 
        if (g_str_equal(state, "unknown") == TRUE)
                return G_SUPPLICANT_STATE_UNKNOWN;
+       else if (g_str_equal(state, "interface_disabled") == TRUE)
+               return G_SUPPLICANT_STATE_DISABLED;
        else if (g_str_equal(state, "disconnected") == TRUE)
                return G_SUPPLICANT_STATE_DISCONNECTED;
        else if (g_str_equal(state, "inactive") == TRUE)
@@ -437,6 +439,21 @@ static void remove_interface(gpointer data)
        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);
@@ -636,6 +653,8 @@ static void interface_capability(const char *key, DBusMessageIter *iter,
                dbus_int32_t max_scan_ssid;
 
                dbus_message_iter_get_basic(iter, &max_scan_ssid);
+               if (max_scan_ssid < 1)
+                       max_scan_ssid = 1;
                interface->max_scan_ssids = max_scan_ssid;
 
        } else
@@ -747,9 +766,6 @@ unsigned int g_supplicant_interface_get_max_scan_ssids(
        if (interface == NULL)
                return 0;
 
-       if (interface->max_scan_ssids == 0)
-               return WPAS_MAX_SCAN_SSIDS;
-
        return interface->max_scan_ssids;
 }
 
@@ -1666,7 +1682,6 @@ static void interface_property(const char *key, DBusMessageIter *iter,
                debug_strvalmap("Mode capability", mode_capa_map,
                                                interface->mode_capa);
 
-               interface->ready = TRUE;
                callback_interface_added(interface);
                return;
        }
@@ -1683,6 +1698,10 @@ static void interface_property(const char *key, DBusMessageIter *iter,
                                interface->state = string2state(str);
                                callback_interface_state(interface);
                        }
+               if (interface->state == G_SUPPLICANT_STATE_DISABLED)
+                       interface->ready = FALSE;
+               else
+                       interface->ready = TRUE;
 
                SUPPLICANT_DBG("state %s (%d)", str, interface->state);
        } else if (g_strcmp0(key, "Scanning") == 0) {
@@ -2159,20 +2178,21 @@ static void wps_credentials(const char *key, DBusMessageIter *iter,
 
        if (g_strcmp0(key, "Key") == 0) {
                DBusMessageIter array;
-               unsigned char *key;
+               unsigned char *key_val;
                int key_len;
 
                dbus_message_iter_recurse(iter, &array);
-               dbus_message_iter_get_fixed_array(&array, &key, &key_len);
+               dbus_message_iter_get_fixed_array(&array, &key_val, &key_len);
 
                g_free(interface->wps_cred.key);
                interface->wps_cred.key = g_try_malloc0(
-                                               sizeof(char) * key_len+1);
+                                               sizeof(char) * key_len + 1);
 
                if (interface->wps_cred.key == NULL)
                        return;
 
-               memcpy(interface->wps_cred.key, key, sizeof(char) * key_len);
+               memcpy(interface->wps_cred.key, key_val,
+                                               sizeof(char) * key_len);
 
                SUPPLICANT_DBG("WPS key present");
        } else if (g_strcmp0(key, "SSID") == 0) {
@@ -2306,6 +2326,7 @@ static DBusHandlerResult g_supplicant_filter(DBusConnection *conn,
 
 struct supplicant_regdom {
        GSupplicantCountryCallback callback;
+       const char *alpha2;
        const void *user_data;
 };
 
@@ -2313,22 +2334,21 @@ static void country_result(const char *error,
                                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);
 }
@@ -2336,11 +2356,9 @@ static void country_result(const char *error,
 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,
+                                                       &regdom->alpha2);
 }
 
 int g_supplicant_set_country(const char *alpha2,
@@ -2359,6 +2377,7 @@ 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,
@@ -2367,6 +2386,28 @@ int g_supplicant_set_country(const char *alpha2,
                                                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;
@@ -2396,6 +2437,13 @@ struct interface_scan_data {
        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)
 {
@@ -2651,12 +2699,20 @@ static void interface_scan_result(const char *error,
                                DBusMessageIter *iter, void *user_data)
 {
        struct interface_scan_data *data = user_data;
+       int err = 0;
 
        if (error != NULL) {
                SUPPLICANT_DBG("error %s", error);
+               err = -EIO;
+       }
+
+       /* A non ready interface cannot send/receive anything */
+       if (data->interface->ready == FALSE)
+               err = -ENOLINK;
 
+       if (err != 0) {
                if (data->callback != NULL)
-                       data->callback(-EIO, data->interface, data->user_data);
+                       data->callback(err, data->interface, data->user_data);
        } else {
                data->interface->scan_callback = data->callback;
                data->interface->scan_data = data->user_data;
@@ -2813,6 +2869,7 @@ int g_supplicant_interface_scan(GSupplicantInterface *interface,
        case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
                return -EBUSY;
        case G_SUPPLICANT_STATE_UNKNOWN:
+       case G_SUPPLICANT_STATE_DISABLED:
        case G_SUPPLICANT_STATE_DISCONNECTED:
        case G_SUPPLICANT_STATE_INACTIVE:
        case G_SUPPLICANT_STATE_SCANNING:
@@ -2839,6 +2896,58 @@ int g_supplicant_interface_scan(GSupplicantInterface *interface,
        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;
@@ -3476,8 +3585,12 @@ static void network_remove_result(const char *error,
 
        SUPPLICANT_DBG("");
 
-       if (error != NULL)
+       if (error != NULL) {
                result = -EIO;
+               if (g_strcmp0("org.freedesktop.DBus.Error.UnknownMethod",
+                                               error) == 0)
+                       result = -ECONNABORTED;
+       }
 
        if (data->callback != NULL)
                data->callback(result, data->interface, data->user_data);
@@ -3510,11 +3623,21 @@ static void interface_disconnect_result(const char *error,
                                DBusMessageIter *iter, void *user_data)
 {
        struct interface_data *data = user_data;
+       int result = 0;
 
        SUPPLICANT_DBG("");
 
-       if (error != NULL && data->callback != NULL)
-               data->callback(-EIO, data->interface, data->user_data);
+       if (error != NULL) {
+               result = -EIO;
+               if (g_strcmp0("org.freedesktop.DBus.Error.UnknownMethod",
+                                               error) == 0)
+                       result = -ECONNABORTED;
+       }
+
+       if (result < 0 && data->callback != NULL) {
+               data->callback(result, data->interface, data->user_data);
+               data->callback = NULL;
+       }
 
        /* If we are disconnecting from previous WPS successful
         * association. i.e.: it did not went through AddNetwork,
@@ -3524,7 +3647,10 @@ static void interface_disconnect_result(const char *error,
                return;
        }
 
-       network_remove(data);
+       if (result != -ECONNABORTED)
+               network_remove(data);
+       else
+               dbus_free(data);
 }
 
 int g_supplicant_interface_disconnect(GSupplicantInterface *interface,