| Index: src/service.c
|
| diff --git a/src/service.c b/src/service.c
|
| index aa5c2c63b807dea7fd65953ef48b686163c41088..fd64966b02d5c735430042ee356fe6ead7d1a3b2 100644
|
| --- a/src/service.c
|
| +++ b/src/service.c
|
| @@ -96,7 +96,7 @@ struct connman_service {
|
| char *key_mgmt;
|
| } eap;
|
|
|
| - char *profile;
|
| + const struct connman_storage_ident *profile;
|
| char *proxy_config;
|
|
|
| /* TODO(sleffler) overlay storage */
|
| @@ -216,8 +216,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)
|
| {
|
| @@ -392,6 +396,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.
|
| + */
|
| + connman_service_ref(service);
|
| + /* TODO(sleffler) skip wired ethernet, open auth? */
|
| + __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>";
|
| @@ -761,68 +799,6 @@ static void hidden_ssid_changed(struct connman_service *service)
|
| DBUS_TYPE_BOOLEAN, &service->wifi.hidden_ssid);
|
| }
|
|
|
| -/**
|
| - * connman_service_append_hidden_ssids:
|
| - * @hidden_ssids: pointer to a list of hidden SSIDs
|
| - *
|
| - * Append the list of SSIDs whose services whose WiFi.HiddenSSID property is
|
| - * TRUE. These SSIDs should be directly probed whenever performing a WiFi
|
| - * network scan.
|
| - *
|
| - * Return -EINVAL if profile could not be parsed cleanly
|
| - */
|
| -int connman_service_append_hidden_ssids(GSList **hidden_ssids)
|
| -{
|
| - const char *ident = __connman_profile_active_ident();
|
| - GKeyFile *keyfile;
|
| - gchar **keys;
|
| - int ret = 0;
|
| -
|
| - _DBG_SERVICE("ident %s", ident);
|
| -
|
| - keyfile = __connman_storage_open(ident);
|
| - if (keyfile == NULL)
|
| - return -EINVAL;
|
| -
|
| - keys = g_key_file_get_groups(keyfile, NULL);
|
| - if (keys == NULL) {
|
| - ret = -EINVAL;
|
| - goto done;
|
| - }
|
| -
|
| - for (; *keys != NULL; keys++) {
|
| - gchar *key = *keys;
|
| - gchar *hex_ssid;
|
| - struct blob *ssid;
|
| -
|
| - if (g_ascii_strncasecmp(key, "wifi_", 5) != 0)
|
| - continue;
|
| -
|
| - if (!g_key_file_get_boolean(keyfile, key, "WiFi.HiddenSSID",
|
| - NULL))
|
| - continue;
|
| -
|
| - hex_ssid = g_key_file_get_string(keyfile, key, "SSID", NULL);
|
| - if (hex_ssid == NULL)
|
| - continue;
|
| -
|
| - _DBG_SERVICE("service %s", key);
|
| -
|
| - ret = blob_new_from_hex(&ssid, hex_ssid);
|
| - g_free(hex_ssid);
|
| - if (ret < 0)
|
| - goto done;
|
| -
|
| - _DBG_SERVICE("ssid %.*s", ssid->len, ssid->data);
|
| - *hidden_ssids = g_slist_prepend(*hidden_ssids, ssid);
|
| - }
|
| -
|
| -done:
|
| - g_key_file_free(keyfile);
|
| -
|
| - return ret;
|
| -}
|
| -
|
| static connman_bool_t is_connectable(const struct connman_service *service)
|
| {
|
|
|
| @@ -1455,7 +1431,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;
|
| }
|
| @@ -1502,8 +1478,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;
|
|
|
| @@ -1545,7 +1520,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,
|
| @@ -1632,7 +1607,7 @@ static DBusMessage *set_property(DBusConnection *conn,
|
| CONNMAN_SERVICE_INTERFACE, kEAPUseSystemCAs,
|
| DBUS_TYPE_BOOLEAN, &service->eap.use_system_cas);
|
|
|
| - __connman_storage_save_service(service);
|
| + __connman_profile_save_service(service);
|
| } else if (g_str_equal(name, kEAPPIN) == TRUE) {
|
| returnmsg = set_eap_string(service, msg, type, value,
|
| &service->eap.pin,
|
| @@ -1669,7 +1644,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;
|
|
|
| @@ -1683,7 +1658,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;
|
|
|
| @@ -1704,7 +1679,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);
|
| @@ -1729,12 +1704,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);
|
| }
|
| @@ -1742,14 +1722,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;
|
|
|
| @@ -1790,6 +1769,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);
|
| }
|
| @@ -2152,6 +2138,23 @@ void connman_service_auto_connect(struct connman_service *service)
|
| __connman_service_device_auto_connect(device);
|
| }
|
|
|
| +static gboolean auto_connect_any(gpointer data)
|
| +{
|
| + _DBG_SERVICE("");
|
| +
|
| + if (__connman_connection_is_online() == FALSE)
|
| + __auto_connect(NULL, NULL);
|
| + return FALSE;
|
| +}
|
| +
|
| +/*
|
| + * Attempt autoconnect on any device, but only if offline.
|
| + */
|
| +void __connman_service_auto_connect_any(void)
|
| +{
|
| + g_idle_add(auto_connect_any, NULL);
|
| +}
|
| +
|
| /**
|
| * __connman_service_set_activation_state:
|
| * @service: service structure
|
| @@ -2706,7 +2709,7 @@ static DBusMessage *set_apn(DBusConnection *conn, DBusMessage *msg,
|
| __connman_service_save_last_good_apn(service, NULL);
|
| }
|
|
|
| - __connman_storage_save_service(service);
|
| + service_modified(service);
|
| return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
|
| }
|
|
|
| @@ -2760,7 +2763,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);
|
| @@ -3850,7 +3852,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
|
| @@ -3897,9 +3899,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);
|
| @@ -3927,7 +3929,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);
|
|
|
| @@ -3996,7 +3998,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);
|
|
|
| @@ -4398,7 +4400,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);
|
|
|
| @@ -4607,7 +4609,7 @@ void __connman_service_save_last_good_apn(struct connman_service *service,
|
| service->cellular.last_good_apn.password = NULL;
|
| }
|
|
|
| - __connman_storage_save_service(service);
|
| + __connman_profile_save_service(service);
|
| }
|
|
|
| static void populate_service_from_keyfile(GKeyFile *keyfile,
|
| @@ -4635,9 +4637,17 @@ 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;
|
| }
|
| @@ -4678,14 +4688,10 @@ static void load_apn(struct connman_service *service,
|
| g_free(network_id_key);
|
| }
|
|
|
| -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, use_system_cas;
|
| unsigned int ssid_len;
|
| @@ -4694,40 +4700,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) {
|
| @@ -4813,8 +4801,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);
|
| @@ -4892,8 +4880,6 @@ static int service_load(struct connman_service *service)
|
| load_apn(service, keyfile, group, &service->cellular.last_good_apn,
|
| "LastGoodAPN");
|
| done:
|
| - g_key_file_free(keyfile);
|
| -
|
| if (group != service->identifier)
|
| g_free((char *)group);
|
|
|
| @@ -4941,38 +4927,12 @@ static void save_apn(struct connman_service *service,
|
| g_free(network_id_key);
|
| }
|
|
|
| -static int service_save(struct connman_service *service)
|
| +static int service_save(struct connman_service *service, GKeyFile *keyfile)
|
| {
|
| - const char *ident = service->profile;
|
| - 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);
|
| @@ -5042,7 +5002,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,
|
| @@ -5088,19 +5048,7 @@ update:
|
| save_apn(service, keyfile, &service->cellular.last_good_apn,
|
| "LastGoodAPN");
|
|
|
| - 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 = {
|
|
|