| Index: src/service.c
|
| diff --git a/src/service.c b/src/service.c
|
| index f56c40559a818176faef070d50c4644b20d282ba..f1234eaed30a2c99f090481891efc28b1e1ed291 100644
|
| --- a/src/service.c
|
| +++ b/src/service.c
|
| @@ -95,7 +95,7 @@ struct connman_service {
|
| char *key_mgmt;
|
| } eap;
|
|
|
| - char *profile;
|
| + const struct connman_storage_ident *profile;
|
| char *proxy_config;
|
|
|
| /* TODO(sleffler) overlay storage */
|
| @@ -213,8 +213,12 @@ static const char* kEAPPIN = "EAP.PIN";
|
| static const char* kEAPPassword = "EAP.Password";
|
| static const char* kEAPKeyMgmt = "EAP.KeyMgmt";
|
|
|
| +static void service_clear_passphrase(struct connman_service *service);
|
| static void service_modified(struct connman_service *service);
|
| +static void service_clear_eap(struct connman_service *service);
|
| static void __service_resort(struct connman_service *service);
|
| +static void set_reconnect_state(struct connman_service *service,
|
| + connman_bool_t onoff);
|
|
|
| static connman_bool_t is_timeset(const GTimeVal *tv)
|
| {
|
| @@ -389,6 +393,40 @@ static struct connman_service *find_service(const char *path)
|
| return data.service;
|
| }
|
|
|
| +static void invalidate_profile(gpointer value, gpointer user_data)
|
| +{
|
| + struct connman_service *service = value;
|
| + const struct connman_storage_ident *profile = user_data;
|
| +
|
| + if (service->profile == profile) {
|
| + /*
|
| + * Invalidate profile-related data and force a re-load
|
| + * the next time the service is to be used (so it can
|
| + * come from the active profile).
|
| + */
|
| + service->profile = NULL;
|
| +
|
| + /*
|
| + * network_disconnect may drop the last reference to the
|
| + * service and cause it to be freed, so take a reference
|
| + * temporarily until we are done with it.
|
| + */
|
| + set_reconnect_state(service, FALSE);
|
| + connman_service_ref(service);
|
| + __connman_service_disconnect(service);
|
| + service_clear_passphrase(service);
|
| + service_clear_eap(service);
|
| + connman_service_unref(service);
|
| + }
|
| +}
|
| +
|
| +void __connman_service_invalidate_profile(const struct connman_storage_ident *ident)
|
| +{
|
| + _DBG_SERVICE("ident %s/%s", ident->user, ident->ident);
|
| +
|
| + g_sequence_foreach(service_list, invalidate_profile, (gpointer) ident);
|
| +}
|
| +
|
| static const char *identifier(struct connman_service *service)
|
| {
|
| return service ? service->identifier : "<nil>";
|
| @@ -770,12 +808,13 @@ static void hidden_ssid_changed(struct connman_service *service)
|
| */
|
| int connman_service_append_hidden_ssids(GSList **hidden_ssids)
|
| {
|
| - const char *ident = __connman_profile_active_ident();
|
| + const struct connman_storage_ident *ident =
|
| + __connman_profile_active_ident();
|
| GKeyFile *keyfile;
|
| gchar **keys;
|
| int ret = 0;
|
|
|
| - _DBG_SERVICE("ident %s", ident);
|
| + _DBG_SERVICE("ident %s:%s", ident->user, ident->ident);
|
|
|
| keyfile = __connman_storage_open(ident);
|
| if (keyfile == NULL)
|
| @@ -815,7 +854,7 @@ int connman_service_append_hidden_ssids(GSList **hidden_ssids)
|
| }
|
|
|
| done:
|
| - g_key_file_free(keyfile);
|
| + __connman_storage_close(ident, keyfile, FALSE);
|
|
|
| return ret;
|
| }
|
| @@ -1434,7 +1473,7 @@ static DBusMessage *set_eap_string(struct connman_service *service,
|
| CONNMAN_SERVICE_INTERFACE, servicename,
|
| DBUS_TYPE_STRING, storage);
|
|
|
| - __connman_storage_save_service(service);
|
| + service_modified(service);
|
|
|
| return NULL;
|
| }
|
| @@ -1481,8 +1520,7 @@ static DBusMessage *set_property(DBusConnection *conn,
|
|
|
| hidden_ssid_changed(service);
|
|
|
| - __connman_storage_save_service(service);
|
| -
|
| + service_modified(service);
|
| } else if (g_str_equal(name, "Passphrase") == TRUE) {
|
| const char *passphrase;
|
|
|
| @@ -1524,7 +1562,7 @@ static DBusMessage *set_property(DBusConnection *conn,
|
| if (service->network != NULL)
|
| prepare_network_passphrase(service);
|
|
|
| - __connman_storage_save_service(service);
|
| + service_modified(service);
|
| } else if (g_str_equal(name, kEAPIdentity) == TRUE) {
|
| returnmsg = set_eap_string(service, msg, type, value,
|
| &service->eap.identity,
|
| @@ -1629,7 +1667,7 @@ static DBusMessage *set_property(DBusConnection *conn,
|
|
|
| autoconnect_changed(service);
|
|
|
| - __connman_storage_save_service(service);
|
| + service_modified(service);
|
| } else if (g_str_equal(name, "ProxyConfig") == TRUE) {
|
| const char *proxy_config;
|
|
|
| @@ -1643,7 +1681,7 @@ static DBusMessage *set_property(DBusConnection *conn,
|
|
|
| proxy_configuration_changed(service);
|
|
|
| - __connman_storage_save_service(service);
|
| + service_modified(service);
|
| } else if (g_str_has_prefix(name, "Priority") == TRUE) {
|
| int pri;
|
|
|
| @@ -1664,7 +1702,7 @@ static DBusMessage *set_property(DBusConnection *conn,
|
|
|
| service_priority_changed(service);
|
|
|
| - __connman_storage_save_service(service);
|
| + service_modified(service);
|
| }
|
| } else
|
| return __connman_error_invalid_property(msg);
|
| @@ -1689,12 +1727,17 @@ static void set_idle(struct connman_service *service)
|
| state_change(service, CONNMAN_SERVICE_STATE_IDLE, TRUE);
|
| }
|
|
|
| -static void __connman_service_clear_passphrase(struct connman_service *service)
|
| +static void service_clear_passphrase(struct connman_service *service)
|
| {
|
| g_free(service->passphrase);
|
| service->passphrase = NULL;
|
|
|
| memset(&service->wifi, 0, sizeof(service->wifi));
|
| +}
|
| +
|
| +static void __connman_service_clear_passphrase(struct connman_service *service)
|
| +{
|
| + service_clear_passphrase(service);
|
|
|
| passphrase_required_changed(service);
|
| }
|
| @@ -1702,14 +1745,13 @@ static void __connman_service_clear_passphrase(struct connman_service *service)
|
| static void service_modified(struct connman_service *service)
|
| {
|
| g_get_current_time(&service->modified);
|
| - __connman_storage_save_service(service);
|
| +
|
| + service->profile = __connman_profile_active_ident();
|
| + __connman_profile_save_service(service);
|
| }
|
|
|
| -void __connman_service_reset(struct connman_service *service)
|
| +static void service_clear_eap(struct connman_service *service)
|
| {
|
| - connman_service_set_favorite(service, FALSE);
|
| - __connman_service_clear_passphrase(service);
|
| -
|
| g_free(service->eap.identity);
|
| service->eap.identity = NULL;
|
|
|
| @@ -1748,6 +1790,13 @@ void __connman_service_reset(struct connman_service *service)
|
|
|
| g_free(service->eap.password);
|
| service->eap.password = NULL;
|
| +}
|
| +
|
| +void __connman_service_reset(struct connman_service *service)
|
| +{
|
| + connman_service_set_favorite(service, FALSE);
|
| + __connman_service_clear_passphrase(service);
|
| + service_clear_eap(service);
|
|
|
| service_modified(service);
|
| }
|
| @@ -2655,7 +2704,7 @@ static DBusMessage *set_apn(DBusConnection *conn, DBusMessage *msg,
|
| apn_info->password = g_strdup(password);
|
| }
|
|
|
| - __connman_storage_save_service(service);
|
| + service_modified(service);
|
| return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
|
| }
|
|
|
| @@ -2709,7 +2758,6 @@ static void service_free(gpointer user_data)
|
| if (service->provider != NULL)
|
| connman_provider_unref(service->provider);
|
|
|
| - g_free(service->profile);
|
| g_free(service->name);
|
| g_free(service->passphrase);
|
| g_free(service->eap.identity);
|
| @@ -3777,7 +3825,7 @@ DBusMessage *__connman_configure_wifi_service(DBusMessage *msg)
|
|
|
| _DBG_SERVICE("service %p created %d", service, created);
|
|
|
| - __connman_storage_save_service(service);
|
| + service_modified(service);
|
|
|
| /*
|
| * If __connman_get_wifi_service_int created the network object
|
| @@ -3824,9 +3872,9 @@ static struct connman_service *__connman_service_get(const char *identifier)
|
|
|
| service->identifier = g_strdup(identifier);
|
|
|
| - service->profile = g_strdup(__connman_profile_active_ident());
|
| + service->profile = __connman_profile_active_ident();
|
|
|
| - __connman_storage_load_service(service);
|
| + __connman_profile_load_service(service);
|
|
|
| iter = g_sequence_insert_sorted(service_list, service,
|
| service_compare, NULL);
|
| @@ -3854,7 +3902,7 @@ static int service_register(struct connman_service *service)
|
| service_methods, service_signals,
|
| NULL, service, NULL);
|
|
|
| - __connman_storage_load_service(service);
|
| + __connman_profile_load_service(service);
|
|
|
| __service_resort(service);
|
|
|
| @@ -3923,7 +3971,7 @@ __connman_service_create_from_device(struct connman_device *device)
|
|
|
| service->device = device;
|
|
|
| - __connman_storage_load_service(service);
|
| + __connman_profile_load_service(service);
|
|
|
| service_register(service);
|
|
|
| @@ -4325,7 +4373,7 @@ __connman_service_create_from_network(struct connman_network *network)
|
|
|
| update_from_network(service, network, FALSE);
|
|
|
| - __connman_storage_load_service(service);
|
| + __connman_profile_load_service(service);
|
|
|
| service_register(service);
|
|
|
| @@ -4527,21 +4575,25 @@ static char *__old_security(GKeyFile *keyfile,
|
| if (service->security == CONNMAN_SERVICE_SECURITY_WPA) {
|
| group = g_strdup(service->identifier);
|
| g_strlcpy(group + strlen(group) - 3, "wpa", 4);
|
| + if (g_key_file_has_group(keyfile, group) == FALSE) {
|
| + g_free(group);
|
| + group = NULL;
|
| + }
|
| } else if (service->security == CONNMAN_SERVICE_SECURITY_RSN) {
|
| group = g_strdup(service->identifier);
|
| g_strlcpy(group + strlen(group) - 3, "rsn", 4);
|
| + if (g_key_file_has_group(keyfile, group) == FALSE) {
|
| + g_free(group);
|
| + group = NULL;
|
| + }
|
| }
|
| return group;
|
| }
|
|
|
| -static int service_load(struct connman_service *service)
|
| +static int service_load(struct connman_service *service, GKeyFile *keyfile)
|
| {
|
| - const char *ident = service->profile;
|
| const char *group = service->identifier;
|
| - GKeyFile *keyfile;
|
| GError *error = NULL;
|
| - gchar *pathname, *data = NULL;
|
| - gsize length;
|
| gchar *str;
|
| connman_bool_t autoconnect;
|
| unsigned int ssid_len;
|
| @@ -4550,40 +4602,22 @@ static int service_load(struct connman_service *service)
|
|
|
| _DBG_SERVICE("service %p", service);
|
|
|
| - if (ident == NULL)
|
| - return -EINVAL;
|
| -
|
| - pathname = g_strdup_printf("%s/%s.profile", STORAGEDIR, ident);
|
| - if (pathname == NULL)
|
| - return -ENOMEM;
|
| -
|
| - keyfile = g_key_file_new();
|
| -
|
| - if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE) {
|
| - g_free(pathname);
|
| - return -ENOENT;
|
| - }
|
| -
|
| - g_free(pathname);
|
| -
|
| - if (g_key_file_load_from_data(keyfile, data, length,
|
| - 0, NULL) == FALSE) {
|
| - g_free(data);
|
| - return -EILSEQ;
|
| - }
|
| -
|
| - g_free(data);
|
| -
|
| - /*
|
| - * Handle upgrade of old-style entries for wpa/rsn services.
|
| - */
|
| - if (g_key_file_has_group(keyfile, group) == FALSE &&
|
| - g_str_has_suffix(group, "_psk") == TRUE) {
|
| - char *old_group = __old_security(keyfile, service);
|
| - if (old_group != NULL) {
|
| - _DBG_SERVICE("check old entry %s", old_group);
|
| - group = old_group;
|
| + if (g_key_file_has_group(keyfile, group) == FALSE) {
|
| + char *old_group;
|
| + /*
|
| + * Handle upgrade of old-style entries for wpa/rsn services.
|
| + */
|
| + if (g_str_has_suffix(group, "_psk") == FALSE) {
|
| + err = -ESRCH;
|
| + goto done;
|
| + }
|
| + old_group = __old_security(keyfile, service);
|
| + if (old_group == NULL) {
|
| + err = -ESRCH;
|
| + goto done;
|
| }
|
| + _DBG_SERVICE("check old entry %s", old_group);
|
| + group = old_group;
|
| }
|
|
|
| switch (service->type) {
|
| @@ -4669,8 +4703,8 @@ static int service_load(struct connman_service *service)
|
| g_free(str);
|
| }
|
|
|
| - str = __connman_storage_get_encrypted_value(keyfile, service->profile,
|
| - group, "Passphrase");
|
| + str = __connman_storage_get_encrypted_value(keyfile, group,
|
| + "Passphrase");
|
| if (str != NULL) {
|
| connman_bool_t valid_pass = TRUE;
|
| g_free(service->passphrase);
|
| @@ -4761,8 +4795,6 @@ static int service_load(struct connman_service *service)
|
| apn->network_id = NULL;
|
| }
|
| done:
|
| - g_key_file_free(keyfile);
|
| -
|
| if (group != service->identifier)
|
| g_free((char *)group);
|
|
|
| @@ -4778,39 +4810,13 @@ static void save_property(GKeyFile *keyfile, struct connman_service *service,
|
| g_key_file_remove_key(keyfile, service->identifier, key, NULL);
|
| }
|
|
|
| -static int service_save(struct connman_service *service)
|
| +static int service_save(struct connman_service *service, GKeyFile *keyfile)
|
| {
|
| - const char *ident = service->profile;
|
| struct connman_network_apn *apn = &service->cellular.apn;
|
| - GKeyFile *keyfile;
|
| - gchar *pathname, *data = NULL;
|
| - gsize length;
|
| gchar *str;
|
| - int err = 0;
|
|
|
| _DBG_SERVICE("service %p", service);
|
|
|
| - if (ident == NULL)
|
| - return -EINVAL;
|
| -
|
| - pathname = g_strdup_printf("%s/%s.profile", STORAGEDIR, ident);
|
| - if (pathname == NULL)
|
| - return -ENOMEM;
|
| -
|
| - keyfile = g_key_file_new();
|
| -
|
| - if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE)
|
| - goto update;
|
| -
|
| - if (length > 0) {
|
| - if (g_key_file_load_from_data(keyfile, data, length,
|
| - 0, NULL) == FALSE)
|
| - goto done;
|
| - }
|
| -
|
| - g_free(data);
|
| -
|
| -update:
|
| if (service->name != NULL)
|
| g_key_file_set_string(keyfile, service->identifier,
|
| "Name", service->name);
|
| @@ -4880,7 +4886,7 @@ update:
|
| }
|
|
|
| if (service->passphrase != NULL && strlen(service->passphrase) > 0) {
|
| - __connman_storage_set_encrypted_value(keyfile, service->profile,
|
| + __connman_storage_set_encrypted_value(keyfile,
|
| service->identifier, "Passphrase", service->passphrase);
|
| } else {
|
| g_key_file_remove_key(keyfile, service->identifier,
|
| @@ -4940,19 +4946,7 @@ update:
|
| "Cellular.APN.network_id", NULL);
|
| }
|
|
|
| - data = g_key_file_to_data(keyfile, &length, NULL);
|
| -
|
| - if (g_file_set_contents(pathname, data, length, NULL) == FALSE)
|
| - connman_error("Failed to store service information");
|
| -
|
| -done:
|
| - g_free(data);
|
| -
|
| - g_key_file_free(keyfile);
|
| -
|
| - g_free(pathname);
|
| -
|
| - return err;
|
| + return 0;
|
| }
|
|
|
| static struct connman_storage service_storage = {
|
|
|