vpn-provider: Introduce immutable flag to provider data
[platform/upstream/connman.git] / plugins / wifi.c
index 409c060..dd79cd3 100644 (file)
@@ -142,9 +142,6 @@ static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
 
        DBG("index %d flags %d change %d", wifi->index, flags, change);
 
-       if (!change)
-               return;
-
        if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
                if (flags & IFF_UP)
                        DBG("interface up");
@@ -387,6 +384,8 @@ static int get_hidden_connections(int max_ssids,
                        continue;
 
                keyfile = connman_storage_load_service(services[i]);
+               if (keyfile == NULL)
+                       continue;
 
                value = g_key_file_get_boolean(keyfile,
                                        services[i], "Hidden", NULL);
@@ -425,7 +424,7 @@ static int get_hidden_connections(int max_ssids,
        /*
         * Check if there are any hidden AP that needs to be provisioned.
         */
-       entries = connman_config_get_entries();
+       entries = connman_config_get_entries("wifi");
        for (i = 0; entries && entries[i]; i++) {
                int len;
 
@@ -519,7 +518,10 @@ static void scan_callback(int result, GSupplicantInterface *interface,
                connman_device_reset_scanning(device);
 
        connman_device_set_scanning(device, FALSE);
-       start_autoscan(device);
+
+       if (result != -ENOLINK)
+               start_autoscan(device);
+
        connman_device_unref(device);
 }
 
@@ -528,7 +530,8 @@ static void scan_callback_hidden(int result,
 {
        struct connman_device *device = user_data;
        struct wifi_data *wifi = connman_device_get_data(device);
-       int driver_max_ssids;
+       GSupplicantScanParams *scan_params;
+       int driver_max_ssids, ret;
 
        DBG("result %d wifi %p", result, wifi);
 
@@ -537,32 +540,30 @@ static void scan_callback_hidden(int result,
 
        /*
         * Scan hidden networks so that we can autoconnect to them.
+        * We will assume 1 as a default number of ssid to scan.
         */
        driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
                                                        wifi->interface);
-       DBG("max ssids %d", driver_max_ssids);
+       if (driver_max_ssids == 0)
+               driver_max_ssids = 1;
 
-       if (driver_max_ssids > 0) {
-               GSupplicantScanParams *scan_params;
-               int ret;
+       DBG("max ssids %d", driver_max_ssids);
 
-               scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
-               if (scan_params == NULL)
-                       goto out;
+       scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
+       if (scan_params == NULL)
+               goto out;
 
-               if (get_hidden_connections(driver_max_ssids,
-                                               scan_params) > 0) {
-                       ret = g_supplicant_interface_scan(wifi->interface,
+       if (get_hidden_connections(driver_max_ssids, scan_params) > 0) {
+               ret = g_supplicant_interface_scan(wifi->interface,
                                                        scan_params,
                                                        scan_callback,
                                                        device);
-                       if (ret == 0)
-                               return;
-               }
-
-               g_supplicant_free_scan_params(scan_params);
+               if (ret == 0)
+                       return;
        }
 
+       g_supplicant_free_scan_params(scan_params);
+
 out:
        scan_callback(result, interface, user_data);
 }
@@ -825,6 +826,8 @@ static int get_latest_connections(int max_ssids,
                        continue;
 
                keyfile = connman_storage_load_service(services[i]);
+               if (keyfile == NULL)
+                       continue;
 
                str = g_key_file_get_string(keyfile,
                                        services[i], "Favorite", NULL);
@@ -902,24 +905,34 @@ static int get_latest_connections(int max_ssids,
        return num_ssids;
 }
 
-static int wifi_scan(struct connman_device *device)
+static int wifi_scan_simple(struct connman_device *device)
 {
        reset_autoscan(device);
 
        return throw_wifi_scan(device, scan_callback_hidden);
 }
 
-static int wifi_scan_fast(struct connman_device *device)
+/*
+ * Note that the hidden scan is only used when connecting to this specific
+ * hidden AP first time. It is not used when system autoconnects to hidden AP.
+ */
+static int wifi_scan(struct connman_device *device,
+               const char *ssid, unsigned int ssid_len,
+               const char *identity, const char* passphrase,
+               gpointer user_data)
 {
        struct wifi_data *wifi = connman_device_get_data(device);
        GSupplicantScanParams *scan_params = NULL;
+       struct scan_ssid *scan_ssid;
+       struct hidden_params *hidden;
        int ret;
        int driver_max_ssids = 0;
+       connman_bool_t do_hidden;
 
        if (wifi == NULL)
                return -ENODEV;
 
-       DBG("device %p %p", device, wifi->interface);
+       DBG("device %p wifi %p hidden ssid %s", device, wifi->interface, ssid);
 
        if (wifi->tethering == TRUE)
                return 0;
@@ -927,107 +940,77 @@ static int wifi_scan_fast(struct connman_device *device)
        if (connman_device_get_scanning(device) == TRUE)
                return -EALREADY;
 
-       driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
-                                                       wifi->interface);
-       DBG("max ssids %d", driver_max_ssids);
-       if (driver_max_ssids == 0)
-               return wifi_scan(device);
-
-       scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
-       if (scan_params == NULL)
-               return -ENOMEM;
+       if (ssid == NULL || ssid_len == 0 || ssid_len > 32) {
+               do_hidden = FALSE;
+       } else {
+               if (wifi->hidden != NULL)
+                       return -EBUSY;
 
-       ret = get_latest_connections(driver_max_ssids, scan_params);
-       if (ret <= 0) {
-               g_supplicant_free_scan_params(scan_params);
-               return wifi_scan(device);
+               do_hidden = TRUE;
        }
 
-       connman_device_ref(device);
-       reset_autoscan(device);
-
-       ret = g_supplicant_interface_scan(wifi->interface, scan_params,
-                                               scan_callback, device);
-       if (ret == 0)
-               connman_device_set_scanning(device, TRUE);
-       else {
-               g_supplicant_free_scan_params(scan_params);
-               connman_device_unref(device);
+       if (do_hidden == FALSE) {
+               driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
+                                                       wifi->interface);
+               DBG("max ssids %d", driver_max_ssids);
+               if (driver_max_ssids == 0)
+                       return wifi_scan_simple(device);
        }
 
-       return ret;
-}
-
-/*
- * This func is only used when connecting to this specific AP first time.
- * It is not used when system autoconnects to hidden AP.
- */
-static int wifi_scan_hidden(struct connman_device *device,
-               const char *ssid, unsigned int ssid_len,
-               const char *identity, const char* passphrase,
-               gpointer user_data)
-{
-       struct wifi_data *wifi = connman_device_get_data(device);
-       GSupplicantScanParams *scan_params = NULL;
-       struct scan_ssid *scan_ssid;
-       struct hidden_params *hidden;
-       int ret;
-
-       if (wifi == NULL)
-               return -ENODEV;
-
-       DBG("hidden SSID %s", ssid);
-
-       if (wifi->tethering == TRUE || wifi->hidden != NULL)
-               return -EBUSY;
-
-       if (ssid == NULL || ssid_len == 0 || ssid_len > 32)
-               return -EINVAL;
-
-       if (connman_device_get_scanning(device) == TRUE)
-               return -EALREADY;
-
        scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
        if (scan_params == NULL)
                return -ENOMEM;
 
-       scan_ssid = g_try_new(struct scan_ssid, 1);
-       if (scan_ssid == NULL) {
-               g_free(scan_params);
-               return -ENOMEM;
-       }
+       if (do_hidden == TRUE) {
+               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;
 
-       memcpy(scan_ssid->ssid, ssid, ssid_len);
-       scan_ssid->ssid_len = ssid_len;
-       scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
+               hidden = g_try_new0(struct hidden_params, 1);
+               if (hidden == NULL) {
+                       g_free(scan_params);
+                       return -ENOMEM;
+               }
 
-       scan_params->num_ssids = 1;
+               memcpy(hidden->ssid, ssid, ssid_len);
+               hidden->ssid_len = ssid_len;
+               hidden->identity = g_strdup(identity);
+               hidden->passphrase = g_strdup(passphrase);
+               hidden->user_data = user_data;
+               wifi->hidden = hidden;
 
-       hidden = g_try_new0(struct hidden_params, 1);
-       if (hidden == NULL) {
-               g_free(scan_params);
-               return -ENOMEM;
+       } else {
+               ret = get_latest_connections(driver_max_ssids, scan_params);
+               if (ret <= 0) {
+                       g_supplicant_free_scan_params(scan_params);
+                       return wifi_scan_simple(device);
+               }
        }
-       memcpy(hidden->ssid, ssid, ssid_len);
-       hidden->ssid_len = ssid_len;
-       hidden->identity = g_strdup(identity);
-       hidden->passphrase = g_strdup(passphrase);
-       hidden->user_data = user_data;
-       wifi->hidden = hidden;
 
        connman_device_ref(device);
 
        reset_autoscan(device);
 
        ret = g_supplicant_interface_scan(wifi->interface, scan_params,
-                       scan_callback, device);
+                                               scan_callback, device);
        if (ret == 0)
                connman_device_set_scanning(device, TRUE);
        else {
-               connman_device_unref(device);
                g_supplicant_free_scan_params(scan_params);
-               hidden_free(wifi->hidden);
-               wifi->hidden = NULL;
+               connman_device_unref(device);
+
+               if (do_hidden == TRUE) {
+                       hidden_free(wifi->hidden);
+                       wifi->hidden = NULL;
+               }
        }
 
        return ret;
@@ -1072,8 +1055,6 @@ static struct connman_device_driver wifi_ng_driver = {
        .enable         = wifi_enable,
        .disable        = wifi_disable,
        .scan           = wifi_scan,
-       .scan_fast      = wifi_scan_fast,
-       .scan_hidden    = wifi_scan_hidden,
        .set_regdom     = wifi_set_regdom,
 };
 
@@ -1256,6 +1237,14 @@ static void disconnect_callback(int result, GSupplicantInterface *interface,
 {
        struct wifi_data *wifi = user_data;
 
+       DBG("result %d supplicant interface %p wifi %p",
+                       result, interface, wifi);
+
+       if (result == -ECONNABORTED) {
+               DBG("wifi interface no longer available");
+               return;
+       }
+
        if (wifi->network != NULL) {
                /*
                 * if result < 0 supplican return an error because
@@ -1353,6 +1342,7 @@ static connman_bool_t is_idle(struct wifi_data *wifi)
 
        switch (wifi->state) {
        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:
@@ -1382,6 +1372,7 @@ static connman_bool_t is_idle_wps(GSupplicantInterface *interface,
         * actually means that we are idling. */
        switch (wifi->state) {
        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:
@@ -1552,6 +1543,7 @@ static void interface_state(GSupplicantInterface *interface)
                break;
 
        case G_SUPPLICANT_STATE_UNKNOWN:
+       case G_SUPPLICANT_STATE_DISABLED:
        case G_SUPPLICANT_STATE_ASSOCIATED:
        case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
        case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
@@ -1681,7 +1673,7 @@ static void network_added(GSupplicantNetwork *supplicant_network)
                        return;
                }
 
-               wifi->networks = g_slist_append(wifi->networks, network);
+               wifi->networks = g_slist_prepend(wifi->networks, network);
        }
 
        if (name != NULL && name[0] != '\0')