Add support for handling wifi authentication failure
[platform/upstream/connman.git] / src / service.c
index e4dbc32..5e7eb8d 100755 (executable)
@@ -75,6 +75,12 @@ struct saved_profiles {
        gchar *profile_name;
 };
 
+static unsigned char invalid_bssid[WIFI_BSSID_LEN_MAX] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+#endif
+
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
 enum connman_ins_preferred_freq {
        CONNMAN_INS_PREFERRED_FREQ_UNKNOWN,
        CONNMAN_INS_PREFERRED_FREQ_24GHZ,
@@ -100,11 +106,7 @@ struct connman_ins_settings {
 };
 
 static struct connman_ins_settings ins_settings;
-
-static unsigned char invalid_bssid[WIFI_BSSID_LEN_MAX] = {
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-#endif
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
 
 struct connman_stats {
        bool valid;
@@ -514,6 +516,10 @@ static const char *error2string(enum connman_service_error error)
                return "login-failed";
        case CONNMAN_SERVICE_ERROR_AUTH_FAILED:
                return "auth-failed";
+#ifdef TIZEN_EXT
+       case CONNMAN_SERVICE_ERROR_ASSOC_FAILED:
+               return "assoc-failed";
+#endif
        case CONNMAN_SERVICE_ERROR_INVALID_KEY:
                return "invalid-key";
        case CONNMAN_SERVICE_ERROR_BLOCKED:
@@ -813,7 +819,8 @@ static void count_assoc_reject(gpointer key, gpointer value, gpointer user_data)
        struct assoc_reject_data *assoc_data = value;
        int *assoc_reject_count = user_data;
 
-       *assoc_reject_count += g_slist_length(assoc_data->reject_time_list);
+       if (assoc_data)
+               *assoc_reject_count += g_slist_length(assoc_data->reject_time_list);
 }
 
 static bool update_assoc_reject(struct connman_service *service)
@@ -857,10 +864,8 @@ static int service_ext_load(struct connman_service *service)
        int i;
        int err = 0;
 
-#if defined TIZEN_EXT
        if (!simplified_log)
-#endif
-       DBG("service %p", service);
+               DBG("service %p", service);
 
        if (!service->network)
                return -EINVAL;
@@ -1834,6 +1839,7 @@ static void __connman_manage_saved_profiles()
                if (!entry) {
                        g_sequence_free(profile_list);
                        g_key_file_free(keyfile);
+                       g_strfreev(services);
                        return;
                }
 
@@ -1857,6 +1863,7 @@ static void __connman_manage_saved_profiles()
        }
 
        g_sequence_free(profile_list);
+       g_strfreev(services);
 }
 #endif
 
@@ -3081,14 +3088,16 @@ static void state_changed(struct connman_service *service)
 #if defined TIZEN_EXT
 static void connect_reason_changed(struct connman_service *service)
 {
+#if defined TIZEN_EXT_INS
        struct connman_device *device;
-
+#endif
        if (!service->path)
                return;
 
        if (!allow_property_changed(service))
                return;
 
+#if defined TIZEN_EXT_INS
        if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER) {
                device = connman_network_get_device(service->network);
                if (device) {
@@ -3105,14 +3114,17 @@ static void connect_reason_changed(struct connman_service *service)
                                connman_device_save_last_user_selection(device);
                }
        }
+#endif
 
        connman_dbus_property_changed_basic(service->path,
-                                           CONNMAN_SERVICE_INTERFACE,
-                                           "ConnectReason",
-                                           DBUS_TYPE_INT32,
-                                           &service->connect_reason);
+                                       CONNMAN_SERVICE_INTERFACE,
+                                       "ConnectReason",
+                                       DBUS_TYPE_INT32,
+                                       &service->connect_reason);
 }
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
 
+#if defined TIZEN_EXT
 static void disconnection_requested_changed(struct connman_service *service)
 {
        dbus_bool_t disconnection_requested;
@@ -4245,6 +4257,22 @@ int connman_service_iterate_services(connman_service_iterate_cb cb,
 }
 
 #if defined TIZEN_EXT
+static void append_security_list(DBusMessageIter *iter, void *user_data)
+{
+       GSList *sec_list = (GSList *)user_data;
+       const char *sec_str;
+
+       if (sec_list) {
+               GSList *list;
+               for (list = sec_list; list; list = list->next) {
+                       sec_str = (const char *)list->data;
+
+                       dbus_message_iter_append_basic(iter,
+                                       DBUS_TYPE_STRING, &sec_str);
+               }
+       }
+}
+
 static void append_wifi_ext_info(DBusMessageIter *dict,
                                        struct connman_network *network)
 {
@@ -4264,6 +4292,7 @@ static void append_wifi_ext_info(DBusMessageIter *dict,
        char *country_code_str = country_code_buff;
        unsigned char *country_code;
        uint16_t connection_mode;
+       GSList *sec_list = NULL;
 
        ssid = connman_network_get_blob(network, "WiFi.SSID", &ssid_len);
        bssid = connman_network_get_bssid(network);
@@ -4275,12 +4304,16 @@ static void append_wifi_ext_info(DBusMessageIter *dict,
        keymgmt = connman_network_get_keymgmt(network);
        country_code = connman_network_get_countrycode(network);
        connection_mode = connman_network_get_connection_mode(network);
+       sec_list = (GSList *)connman_network_get_sec_list(network);
 
        snprintf(bssid_str, WIFI_BSSID_STR_LEN, MACSTR, MAC2STR(bssid));
 
        snprintf(country_code_str, (WIFI_COUNTRY_CODE_LEN + 1), "%c%c",
                 country_code[0], country_code[1]);
 
+       connman_dbus_dict_append_array(dict, "SecurityList",
+                                       DBUS_TYPE_STRING,
+                                       append_security_list, sec_list);
 
        connman_dbus_dict_append_fixed_array(dict, "SSID",
                                        DBUS_TYPE_BYTE, &ssid, ssid_len);
@@ -4559,7 +4592,7 @@ static void append_properties(DBusMessageIter *dict, dbus_bool_t limited,
                connman_network_append_acddbus(dict, service->network);
 }
 
-#if defined TIZEN_EXT_INS
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
 static void append_ins_bssid_info(DBusMessageIter *iter, void *user_data)
 {
        GSList *bssid_list = NULL;
@@ -4650,7 +4683,7 @@ static void append_ins_properties(DBusMessageIter *dict,
                                append_ins_bssid_info, service->network);
        }
 }
-#endif
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
 
 static void append_struct_service(DBusMessageIter *iter,
                connman_dbus_append_cb_t function,
@@ -4689,12 +4722,7 @@ static void append_struct(gpointer value, gpointer user_data)
        append_struct_service(iter, append_dict_properties, service);
 }
 
-void __connman_service_list_struct(DBusMessageIter *iter)
-{
-       g_list_foreach(service_list, append_struct, iter);
-}
-
-#if defined TIZEN_EXT_INS
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
 static void append_dict_ins_properties(DBusMessageIter *dict, void *user_data)
 {
        struct connman_service *service = user_data;
@@ -4720,7 +4748,12 @@ void __connman_ins_list_struct(DBusMessageIter *iter)
 {
        g_list_foreach(service_list, append_ins_struct, iter);
 }
-#endif
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
+
+void __connman_service_list_struct(DBusMessageIter *iter)
+{
+       g_list_foreach(service_list, append_struct, iter);
+}
 
 bool __connman_service_is_hidden(struct connman_service *service)
 {
@@ -7508,7 +7541,7 @@ static DBusMessage *is_eapol_enabled(DBusConnection *conn,
 }
 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 
-#if defined TIZEN_MAINTAIN_ONLINE
+#if defined TIZEN_EXT
 static DBusMessage *downgrade_service(DBusConnection *conn,
                                        DBusMessage *msg, void *user_data)
 {
@@ -7516,6 +7549,7 @@ static DBusMessage *downgrade_service(DBusConnection *conn,
 
        downgrade_state(service);
        __connman_connection_update_gateway();
+       start_online_check(service, CONNMAN_IPCONFIG_TYPE_IPV4);
 
        return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
@@ -7588,7 +7622,7 @@ static const GDBusMethodTable service_methods[] = {
 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
        { GDBUS_METHOD("IsEapolEnabled", NULL, GDBUS_ARGS({ "eapol", "b" }), is_eapol_enabled) },
 #endif
-#if defined TIZEN_MAINTAIN_ONLINE
+#if defined TIZEN_EXT
        { GDBUS_METHOD("Downgrade", NULL, NULL, downgrade_service) },
 #endif
        { },
@@ -7863,7 +7897,7 @@ void connman_service_unref_debug(struct connman_service *service,
        g_hash_table_remove(service_hash, service->identifier);
 }
 
-#if defined TIZEN_EXT
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
 static int calculate_score_last_user_selection(struct connman_service *service)
 {
        int score = 0;
@@ -7928,14 +7962,16 @@ static int calculate_score_last_connected(struct connman_service *service)
        last_connected_ident = connman_device_get_last_connected_ident(device);
        frequency = connman_network_get_frequency(service->network);
 
-       if (g_strcmp0(last_connected_ident, service->identifier) == 0 &&
-               (((frequency >= FREQ_RANGE_24GHZ_CHANNEL_1 &&
-               frequency <= FREQ_RANGE_24GHZ_CHANNEL_14) &&
-               service->strength >= ins_settings.signal_level3_24ghz) ||
-               ((frequency >= FREQ_RANGE_5GHZ_CHANNEL_32 &&
-               frequency <= FREQ_RANGE_5GHZ_CHANNEL_165) &&
-               service->strength >= ins_settings.signal_level3_5ghz))) {
-               score += ins_settings.last_connected_score;
+       if (ins_settings.last_connected) {
+               if (g_strcmp0(last_connected_ident, service->identifier) == 0 &&
+                               (((frequency >= FREQ_RANGE_24GHZ_CHANNEL_1 &&
+                               frequency <= FREQ_RANGE_24GHZ_CHANNEL_14) &&
+                               service->strength >= ins_settings.signal_level3_24ghz) ||
+                               ((frequency >= FREQ_RANGE_5GHZ_CHANNEL_32 &&
+                               frequency <= FREQ_RANGE_5GHZ_CHANNEL_165) &&
+                               service->strength >= ins_settings.signal_level3_5ghz))) {
+                       score += ins_settings.last_connected_score;
+               }
        }
 
        return score;
@@ -7950,7 +7986,7 @@ static int calculate_score_frequency(struct connman_service *service)
 
        switch (ins_settings.preferred_freq) {
        case CONNMAN_INS_PREFERRED_FREQ_24GHZ:
-               if ((frequency >= FREQ_RANGE_24GHZ_CHANNEL_14 &&
+               if ((frequency >= FREQ_RANGE_24GHZ_CHANNEL_1 &&
                        frequency <= FREQ_RANGE_24GHZ_CHANNEL_14) &&
                        (service->strength >= ins_settings.signal_level3_24ghz))
                        score += ins_settings.preferred_freq_score;
@@ -8029,19 +8065,17 @@ static int calculate_score(struct connman_service *service)
                score_frequency + score_security_priority +
                score_internet_connection + score_strength;
 
-#if defined TIZEN_EXT_INS
        service->score_last_user_selection = score_last_user_selection;
        service->score_last_connected = score_last_connected;
        service->score_frequency = score_frequency;
        service->score_security_priority = score_security_priority;
        service->score_internet_connection = score_internet_connection;
        service->score_strength = score_strength;
-#endif
 
        service->ins_score = score;
        return score;
 }
-#endif
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
 
 static gint service_compare(gconstpointer a, gconstpointer b)
 {
@@ -8049,12 +8083,12 @@ static gint service_compare(gconstpointer a, gconstpointer b)
        struct connman_service *service_b = (void *) b;
        enum connman_service_state state_a, state_b;
        bool a_connected, b_connected;
-#if defined TIZEN_EXT
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
        int score_a;
        int score_b;
-#else
+#else /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
        gint strength;
-#endif
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
 
        state_a = service_a->state;
        state_b = service_b->state;
@@ -8162,21 +8196,21 @@ static gint service_compare(gconstpointer a, gconstpointer b)
                        return 1;
        }
 
-#if defined TIZEN_EXT
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
        score_a = calculate_score(service_a);
        score_b = calculate_score(service_b);
        if (score_b != score_a)
                return score_b - score_a;
-#else
+#else /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
        strength = (gint) service_b->strength - (gint) service_a->strength;
        if (strength)
                return strength;
-#endif
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
 
        return g_strcmp0(service_a->name, service_b->name);
 }
 
-#if defined TIZEN_EXT_INS
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
 static void print_service_sort(gpointer data, gpointer user_data)
 {
        struct connman_service *service = data;
@@ -8191,15 +8225,15 @@ static void print_service_sort(gpointer data, gpointer user_data)
                service->score_security_priority, service->score_internet_connection,
                service->score_strength);
 }
-#endif
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
 
 static void service_list_sort(void)
 {
        if (service_list && service_list->next) {
                service_list = g_list_sort(service_list, service_compare);
-#if defined TIZEN_EXT_INS
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
                g_list_foreach(service_list, print_service_sort, NULL);
-#endif
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
                service_schedule_changed();
        }
 }
@@ -8576,7 +8610,8 @@ static void report_error_cb(void *user_context, bool retry,
                service->state_ipv4 = service->state_ipv6 =
                                CONNMAN_SERVICE_STATE_IDLE;
 
-               if (service->error != CONNMAN_SERVICE_ERROR_AUTH_FAILED)
+               if (service->error != CONNMAN_SERVICE_ERROR_AUTH_FAILED &&
+                               service->error != CONNMAN_SERVICE_ERROR_ASSOC_FAILED)
                        set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
 #endif
                service_complete(service);
@@ -9209,6 +9244,55 @@ static int service_indicate_state(struct connman_service *service)
 #else
        __connman_service_connect_default(service);
 #endif
+       /* Update Wi-Fi Roaming result */
+       if (connman_setting_get_bool("WifiRoaming") &&
+                       connman_network_get_bool(service->network, "WiFi.Roaming")) {
+               const char *cur_bssid;
+               const char *dst_bssid;
+               const char *ifname;
+               struct connman_device *device;
+
+               device = connman_network_get_device(service->network);
+               if (device) {
+                       ifname = connman_device_get_string(device, "Interface");
+                       cur_bssid = connman_network_get_string(service->network,
+                                               "WiFi.RoamingCurBSSID");
+                       dst_bssid = connman_network_get_string(service->network,
+                                               "WiFi.RoamingDstBSSID");
+               }
+
+               if (device && ifname && cur_bssid && dst_bssid) {
+                       switch(new_state) {
+                       case CONNMAN_SERVICE_STATE_UNKNOWN:
+                       case CONNMAN_SERVICE_STATE_ASSOCIATION:
+                       case CONNMAN_SERVICE_STATE_CONFIGURATION:
+                               break;
+                       case CONNMAN_SERVICE_STATE_READY:
+                       case CONNMAN_SERVICE_STATE_ONLINE:
+                               __connman_technology_notify_roaming_state(ifname,
+                                               "success", cur_bssid, dst_bssid);
+                               connman_network_set_bool(service->network,
+                                               "WiFi.Roaming", false);
+                               connman_network_set_string(service->network,
+                                               "WiFi.RoamingCurBSSID", NULL);
+                               connman_network_set_string(service->network,
+                                               "WiFi.RoamingDstBSSID", NULL);
+                               break;
+                       case CONNMAN_SERVICE_STATE_DISCONNECT:
+                       case CONNMAN_SERVICE_STATE_FAILURE:
+                       case CONNMAN_SERVICE_STATE_IDLE:
+                               __connman_technology_notify_roaming_state(ifname,
+                                               "failure", cur_bssid, dst_bssid);
+                               connman_network_set_bool(service->network,
+                                               "WiFi.Roaming", false);
+                               connman_network_set_string(service->network,
+                                               "WiFi.RoamingCurBSSID", NULL);
+                               connman_network_set_string(service->network,
+                                               "WiFi.RoamingDstBSSID", NULL);
+                               break;
+                       }
+               }
+       }
 #endif
 
        __connman_connection_update_gateway();
@@ -9411,7 +9495,13 @@ static gboolean redo_wispr_ipv4(gpointer user_data)
 {
        struct connman_service *service = user_data;
 
+#if defined TIZEN_MAINTAIN_ONLINE
+       DBG("");
+
+       __connman_wispr_start(service, CONNMAN_IPCONFIG_TYPE_IPV4);
+#else
        redo_wispr(service, CONNMAN_IPCONFIG_TYPE_IPV4);
+#endif
 
        return FALSE;
 }
@@ -9425,19 +9515,6 @@ static gboolean redo_wispr_ipv6(gpointer user_data)
        return FALSE;
 }
 
-#if defined TIZEN_MAINTAIN_ONLINE
-static gboolean redo_wispr_ipv4(gpointer user_data)
-{
-       struct connman_service *service = user_data;
-
-       DBG("");
-
-       __connman_wispr_start(service, CONNMAN_IPCONFIG_TYPE_IPV4);
-
-       return FALSE;
-}
-#endif
-
 int __connman_service_online_check_failed(struct connman_service *service,
                                        enum connman_ipconfig_type type)
 {
@@ -11129,7 +11206,7 @@ static struct connman_agent_driver agent_driver = {
        .context_unref  = agent_context_unref,
 };
 
-#if defined TIZEN_EXT
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
 static void ins_setting_init(void)
 {
        int i;
@@ -11186,8 +11263,13 @@ static void ins_setting_init(void)
        ins_settings.preferred_freq_score = connman_setting_get_uint("INSPreferredFreqScore");
        ins_settings.internet_score = connman_setting_get_uint("INSInternetScore");
 
-       ins_settings.signal_level3_5ghz = connman_setting_get_int("INSSignalLevel3_5GHz");
-       ins_settings.signal_level3_24ghz = connman_setting_get_int("INSSignalLevel3_24GHz");
+       /*
+        * In ConnMan, signal strength is used after being converted
+        * to positive value(signal strength + 120).
+        * So the value for comparison should also be converted to the same.
+        */
+       ins_settings.signal_level3_5ghz = connman_setting_get_int("INSSignalLevel3_5GHz") + 120;
+       ins_settings.signal_level3_24ghz = connman_setting_get_int("INSSignalLevel3_24GHz") + 120;
 
        DBG("last_user_selection [%s]", ins_settings.last_user_selection ? "true" : "false");
        DBG("last_user_selection_time [%d]", ins_settings.last_user_selection_time);
@@ -11215,7 +11297,7 @@ static void ins_setting_init(void)
        DBG("signal_level3_5ghz [%d]", ins_settings.signal_level3_5ghz);
        DBG("signal_level3_24ghz [%d]", ins_settings.signal_level3_24ghz);
 }
-#endif
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
 
 int __connman_service_init(void)
 {
@@ -11244,9 +11326,9 @@ int __connman_service_init(void)
 
        remove_unprovisioned_services();
 
-#if defined TIZEN_EXT
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
        ins_setting_init();
-#endif
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
 
        return 0;
 }