Merge "Remove TIZEN_EXT for patch accepted by upstream community." into tizen
[platform/upstream/connman.git] / src / service.c
index 0c6e623..cbedb34 100644 (file)
@@ -41,6 +41,7 @@
 
 #if defined TIZEN_EXT
 #define WIFI_BSSID_STR_LEN     18
+#define MAX_WIFI_PROFILES      200
 #endif
 
 static DBusConnection *connection = NULL;
@@ -55,6 +56,12 @@ static bool services_dirty = false;
 
 #if defined TIZEN_EXT
 static bool auto_connect_mode = TRUE;
+
+struct saved_profiles {
+       GTimeVal modified;
+       gchar *profile_name;
+};
+
 #endif
 
 struct connman_stats {
@@ -172,6 +179,11 @@ struct connman_service {
        enum connman_dnsconfig_method dns_config_method_ipv4;
        enum connman_dnsconfig_method dns_config_method_ipv6;
 #endif
+#if defined TIZEN_EXT
+       char *connector;
+       char *c_sign_key;
+       char *net_access_key;
+#endif
 };
 
 static bool allow_property_changed(struct connman_service *service);
@@ -350,6 +362,8 @@ enum connman_service_security __connman_service_string2security(const char *str)
                return CONNMAN_SERVICE_SECURITY_SAE;
        if (!strcmp(str, "owe"))
                return CONNMAN_SERVICE_SECURITY_OWE;
+       if (!strcmp(str, "dpp"))
+               return CONNMAN_SERVICE_SECURITY_DPP;
 #endif
 
        return CONNMAN_SERVICE_SECURITY_UNKNOWN;
@@ -374,6 +388,8 @@ static const char *security2string(enum connman_service_security security)
                return "sae";
        case CONNMAN_SERVICE_SECURITY_OWE:
                return "owe";
+       case CONNMAN_SERVICE_SECURITY_DPP:
+               return "dpp";
 #else
        case CONNMAN_SERVICE_SECURITY_RSN:
                return "psk";
@@ -812,6 +828,29 @@ static int service_load(struct connman_service *service)
                }
        }
 #endif
+#if defined TIZEN_EXT
+       if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
+                       service->security == CONNMAN_SERVICE_SECURITY_DPP) {
+               str = g_key_file_get_string(keyfile,
+                               service->identifier, "Connector", NULL);
+               if (str != NULL) {
+                       g_free(service->connector);
+                       service->connector = str;
+               }
+               str = g_key_file_get_string(keyfile,
+                               service->identifier, "CSignKey", NULL);
+               if (str != NULL) {
+                       g_free(service->c_sign_key);
+                       service->c_sign_key = str;
+               }
+               str = g_key_file_get_string(keyfile,
+                               service->identifier, "NetAccessKey", NULL);
+               if (str != NULL) {
+                       g_free(service->net_access_key);
+                       service->net_access_key = str;
+               }
+       }
+#endif
 
 done:
        g_key_file_free(keyfile);
@@ -1087,6 +1126,29 @@ static int service_save(struct connman_service *service)
                        g_key_file_remove_key(keyfile, service->identifier,
                                        "PrivateKeyPassphrase", NULL);
        }
+       if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
+                       service->security == CONNMAN_SERVICE_SECURITY_DPP) {
+               if (service->connector != NULL && strlen(service->connector) > 0)
+                       g_key_file_set_string(keyfile, service->identifier,
+                                       "Connector", service->connector);
+               else
+                       g_key_file_remove_key(keyfile, service->identifier,
+                                       "Connector", NULL);
+
+               if (service->c_sign_key != NULL && strlen(service->c_sign_key) > 0)
+                       g_key_file_set_string(keyfile, service->identifier,
+                                       "CSignKey", service->c_sign_key);
+               else
+                       g_key_file_remove_key(keyfile, service->identifier,
+                                       "CSignKey", NULL);
+
+               if (service->net_access_key != NULL && strlen(service->net_access_key) > 0)
+                       g_key_file_set_string(keyfile, service->identifier,
+                                       "NetAccessKey", service->net_access_key);
+               else
+                       g_key_file_remove_key(keyfile, service->identifier,
+                                       "NetAccessKey", NULL);
+       }
 #endif
 
 done:
@@ -1097,12 +1159,108 @@ done:
        return err;
 }
 
+#if defined TIZEN_EXT
+static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
+{
+       GTimeVal *aval = (GTimeVal *)a;
+       GTimeVal *bval = (GTimeVal *)b;
+
+       /* Note that the sort order is ascending */
+       if (aval->tv_sec > bval->tv_sec)
+               return 1;
+
+       if (aval->tv_sec < bval->tv_sec)
+               return -1;
+
+       return 0;
+}
+
+static void free_entry(gpointer data)
+{
+       struct saved_profiles *entry = data;
+       g_free(entry->profile_name);
+       g_free(entry);
+}
+
+static void __connman_manage_saved_profiles()
+{
+       GKeyFile *keyfile;
+       gchar **services = NULL;
+       GTimeVal modified;
+       int i, num_profiles = 0;
+       GSequenceIter *iter;
+       GSequence *profile_list;
+       struct saved_profiles *entry;
+
+       profile_list = g_sequence_new(free_entry);
+       if (!profile_list)
+               return;
+
+       services = connman_storage_get_services();
+
+       /* Check the count of saved profiles */
+       for (i = 0; services && services[i]; i++) {
+               if (strncmp(services[i], "wifi_", 5) != 0)
+                       continue;
+
+               keyfile = connman_storage_load_service(services[i]);
+               if (!keyfile)
+                       continue;
+
+               gchar *str = g_key_file_get_string(keyfile,
+                               services[i], "Modified", NULL);
+               if (!str) {
+                       g_key_file_free(keyfile);
+                       continue;
+               }
+
+               g_time_val_from_iso8601(str, &modified);
+               g_free(str);
+
+               entry = g_try_new(struct saved_profiles, 1);
+               if (!entry) {
+                       g_sequence_free(profile_list);
+                       g_key_file_free(keyfile);
+                       return;
+               }
+
+               entry->modified = modified;
+               entry->profile_name = g_strdup(services[i]);
+
+               g_sequence_insert_sorted(profile_list, entry,
+                               sort_entry, NULL);
+
+               num_profiles++;
+       }
+       DBG("number of profiles: %d", num_profiles);
+
+       if (num_profiles > MAX_WIFI_PROFILES) {
+               iter = g_sequence_get_begin_iter(profile_list);
+
+               entry = g_sequence_get(iter);
+
+               if (__connman_storage_remove_service(entry->profile_name) == false)
+                       DBG("Failed to remove service profile: %s", entry->profile_name);
+       }
+
+       g_sequence_free(profile_list);
+}
+#endif
+
 void __connman_service_save(struct connman_service *service)
 {
        if (!service)
                return;
 
        service_save(service);
+#if defined TIZEN_EXT
+       /*
+        * Description: Manage the wireless profiles saved in connman.
+        * If the number of saved profiles is more than 200, remove the
+        * profile that is not updated for longer duration.
+        */
+       __connman_manage_saved_profiles();
+#endif
 }
 
 static enum connman_service_state combine_state(
@@ -1488,6 +1646,12 @@ static int nameserver_add_all(struct connman_service *service,
        if (!i)
                __connman_resolver_append_fallback_nameservers();
 
+#if defined TIZEN_EXT
+       const char *global_dns = connman_option_get_string("GlobalNameserver");
+       if (global_dns)
+               nameserver_add(service, type, global_dns);
+#endif
+
        searchdomain_add_all(service);
 
        return 0;
@@ -1657,6 +1821,11 @@ static int nameserver_remove_all(struct connman_service *service,
                i++;
        }
 
+#if defined TIZEN_EXT
+       const char *global_dns = connman_option_get_string("GlobalNameserver");
+       if (global_dns)
+               nameserver_remove(service, type, global_dns);
+#endif
        searchdomain_remove_all(service);
 
        return 0;
@@ -3380,18 +3549,16 @@ static void append_properties(DBusMessageIter *dict, dbus_bool_t limited,
 
 #if defined TIZEN_EXT
        unsigned int frequency = 0U;
-       if (service && service->network) {
-               frequency = connman_network_get_frequency(service->network);
-               connman_dbus_dict_append_basic(dict, "Frequency",
-                               DBUS_TYPE_UINT16, &frequency);
-       }
-
        unsigned char *wifi_vsie;
        unsigned int wifi_vsie_len;
        GSList *vsie_list = NULL;
 
-       if (service->network)
+       if (service->network) {
+               frequency = connman_network_get_frequency(service->network);
+               connman_dbus_dict_append_basic(dict, "Frequency",
+                               DBUS_TYPE_UINT16, &frequency);
                vsie_list = (GSList *)connman_network_get_vsie_list(service->network);
+       }
 
        if (vsie_list) {
                GSList *list;
@@ -4204,6 +4371,7 @@ int __connman_service_check_passphrase(enum connman_service_security security,
        case CONNMAN_SERVICE_SECURITY_8021X:
 #if defined TIZEN_EXT
        case CONNMAN_SERVICE_SECURITY_OWE:
+       case CONNMAN_SERVICE_SECURITY_DPP:
 #endif
                break;
        }
@@ -4224,6 +4392,9 @@ int __connman_service_set_passphrase(struct connman_service *service,
                return -EINVAL;
 
 #if defined TIZEN_EXT
+       if (service->immutable &&
+                       service->security != CONNMAN_SERVICE_SECURITY_DPP)
+               return -EINVAL;
        /* The encrypted passphrase is used here
         * and validation is done by net-config before being encrypted.
         */
@@ -5711,6 +5882,17 @@ static void __connman_service_cleanup_network_8021x(struct connman_service *serv
        connman_network_set_string(service->network, "WiFi.Phase2", NULL);
        connman_network_set_string(service->network, "WiFi.AnonymousIdentity", NULL);
 }
+static void __connman_service_cleanup_network_dpp(struct connman_service *service)
+{
+       if (service == NULL)
+               return;
+
+       DBG("service %p ", service);
+
+       connman_network_set_string(service->network, "WiFi.Connector", NULL);
+       connman_network_set_string(service->network, "WiFi.CSignKey", NULL);
+       connman_network_set_string(service->network, "WiFi.NetAccessKey", NULL);
+}
 #endif
 
 bool __connman_service_remove(struct connman_service *service)
@@ -5784,6 +5966,16 @@ bool __connman_service_remove(struct connman_service *service)
        g_strfreev(service->nameservers_config);
        service->nameservers_config = NULL;
 
+       g_free(service->connector);
+       service->connector = NULL;
+
+       g_free(service->c_sign_key);
+       service->c_sign_key = NULL;
+
+       g_free(service->net_access_key);
+       service->net_access_key = NULL;
+
+       __connman_service_cleanup_network_dpp(service);
 #endif
 
        service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
@@ -6282,6 +6474,11 @@ static void service_free(gpointer user_data)
        g_free(service->phase2);
        g_free(service->config_file);
        g_free(service->config_entry);
+#if defined TIZEN_EXT
+       g_free(service->connector);
+       g_free(service->c_sign_key);
+       g_free(service->net_access_key);
+#endif
 
        if (service->stats.timer)
                g_timer_destroy(service->stats.timer);
@@ -6855,6 +7052,19 @@ void __connman_service_set_string(struct connman_service *service,
                service->phase2 = g_strdup(value);
        } else if (g_str_equal(key, "Passphrase"))
                __connman_service_set_passphrase(service, value);
+#if defined TIZEN_EXT
+        else if (g_str_equal(key, "Connector")) {
+               g_free(service->connector);
+               service->connector = g_strdup(value);
+        }      else if (g_str_equal(key, "CSignKey")) {
+               g_free(service->c_sign_key);
+               service->c_sign_key = g_strdup(value);
+        }      else if (g_str_equal(key, "NetAccessKey")) {
+               g_free(service->net_access_key);
+               service->net_access_key = g_strdup(value);
+       } else
+               DBG("Unknown key: %s", key);
+#endif
 }
 
 void __connman_service_set_search_domains(struct connman_service *service,
@@ -8064,6 +8274,29 @@ static void prepare_8021x(struct connman_service *service)
                                                        service->phase1);
 #endif
 }
+#if defined TIZEN_EXT
+
+static bool has_valid_configuration_object(struct connman_service *service)
+{
+       return service->connector && service->c_sign_key && service->net_access_key;
+}
+
+static void prepare_dpp(struct connman_service *service)
+{
+       DBG("prepare dpp");
+       if (service->connector)
+               connman_network_set_string(service->network, "WiFi.Connector",
+                                                               service->connector);
+
+       if (service->c_sign_key)
+               connman_network_set_string(service->network, "WiFi.CSignKey",
+                                                       service->c_sign_key);
+
+       if (service->net_access_key)
+               connman_network_set_string(service->network, "WiFi.NetAccessKey",
+                                                       service->net_access_key);
+}
+#endif
 
 static int service_connect(struct connman_service *service)
 {
@@ -8142,6 +8375,13 @@ static int service_connect(struct connman_service *service)
                        }
                        break;
 
+#if defined TIZEN_EXT
+               case CONNMAN_SERVICE_SECURITY_DPP:
+                       if (has_valid_configuration_object(service) &&
+                                       !service->network)
+                               return -EINVAL;
+                       break;
+#endif
                case CONNMAN_SERVICE_SECURITY_8021X:
                        if (!service->eap) {
                                connman_warn("EAP type has not been found. "
@@ -8206,6 +8446,9 @@ static int service_connect(struct connman_service *service)
 #if defined TIZEN_EXT
                case CONNMAN_SERVICE_SECURITY_SAE:
                case CONNMAN_SERVICE_SECURITY_OWE:
+                       break;
+               case CONNMAN_SERVICE_SECURITY_DPP:
+                       prepare_dpp(service);
 #endif
                        break;
                case CONNMAN_SERVICE_SECURITY_8021X:
@@ -8902,6 +9145,8 @@ static enum connman_service_security convert_wifi_security(const char *security)
                return CONNMAN_SERVICE_SECURITY_SAE;
        else if (g_str_equal(security, "owe"))
                return CONNMAN_SERVICE_SECURITY_OWE;
+       else if (g_str_equal(security, "dpp"))
+               return CONNMAN_SERVICE_SECURITY_DPP;
        else if (g_str_equal(security, "ft_psk") == TRUE)
                return CONNMAN_SERVICE_SECURITY_PSK;
        else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
@@ -9122,6 +9367,15 @@ struct connman_service * __connman_service_create_from_network(struct connman_ne
                if (service->phase2 != NULL)
                        connman_network_set_string(service->network, "WiFi.Phase2",
                                                                service->phase2);
+               if (service->eap != NULL)
+                       connman_network_set_string(service->network, "WiFi.Connector",
+                                                               service->connector);
+               if (service->identity != NULL)
+                       connman_network_set_string(service->network, "WiFi.CSignKey",
+                                                               service->c_sign_key);
+               if (service->phase2 != NULL)
+                       connman_network_set_string(service->network, "WiFi.NetAccessKey",
+                                                               service->net_access_key);
 #endif
        }