User is able to change autoconnect value for a provisioned service.
This user modification must be preserved across ConnMan restarts.
This is done by loading the necessary minimal service settings
when provisioning a service via .config file. We also do not load
the service settings if we could provision the service so that
the options in .config file are not overwritten.
---
 src/config.c  | 59 ++++++++++++++++++++++++++++++++++++-----------------------
 src/service.c | 10 +++++++---
 2 files changed, 43 insertions(+), 26 deletions(-)

diff --git a/src/config.c b/src/config.c
index d7f98f0..a74409d 100644
--- a/src/config.c
+++ b/src/config.c
@@ -1055,11 +1055,10 @@ static gboolean remove_virtual_config(gpointer 
user_data)
        return FALSE;
 }
 
-static void provision_service(gpointer key, gpointer value,
-                                                       gpointer user_data)
+static int try_provision_service(gpointer key,
+                               struct connman_config_service *config,
+                               struct connman_service *service)
 {
-       struct connman_service *service = user_data;
-       struct connman_config_service *config = value;
        struct connman_network *network;
        const void *service_id;
        enum connman_service_type type;
@@ -1069,15 +1068,15 @@ static void provision_service(gpointer key, gpointer 
value,
        type = connman_service_get_type(service);
        if (type == CONNMAN_SERVICE_TYPE_WIFI &&
                                g_strcmp0(config->type, "wifi") != 0)
-               return;
+               return -ENOENT;
 
        if (type == CONNMAN_SERVICE_TYPE_ETHERNET &&
                                g_strcmp0(config->type, "ethernet") != 0)
-               return;
+               return -ENOENT;
 
        if (type == CONNMAN_SERVICE_TYPE_GADGET &&
                                g_strcmp0(config->type, "gadget") != 0)
-               return;
+               return -ENOENT;
 
        DBG("service %p ident %s", service,
                                        __connman_service_get_ident(service));
@@ -1085,7 +1084,7 @@ static void provision_service(gpointer key, gpointer 
value,
        network = __connman_service_get_network(service);
        if (!network) {
                connman_error("Service has no network set");
-               return;
+               return -EINVAL;
        }
 
        DBG("network %p ident %s", network,
@@ -1098,7 +1097,7 @@ static void provision_service(gpointer key, gpointer 
value,
                device = connman_network_get_device(network);
                if (!device) {
                        connman_error("Network device is missing");
-                       return;
+                       return -ENODEV;
                }
 
                device_addr = connman_device_get_string(device, "Address");
@@ -1106,7 +1105,7 @@ static void provision_service(gpointer key, gpointer 
value,
                DBG("wants %s has %s", config->mac, device_addr);
 
                if (g_ascii_strcasecmp(device_addr, config->mac) != 0)
-                       return;
+                       return -ENOENT;
        }
 
        if (g_strcmp0(config->type, "wifi") == 0 &&
@@ -1115,14 +1114,14 @@ static void provision_service(gpointer key, gpointer 
value,
                                                &ssid_len);
                if (!ssid) {
                        connman_error("Network SSID not set");
-                       return;
+                       return -EINVAL;
                }
 
                if (!config->ssid || ssid_len != config->ssid_len)
-                       return;
+                       return -ENOENT;
 
                if (memcmp(config->ssid, ssid, ssid_len) != 0)
-                       return;
+                       return -ENOENT;
        }
 
        if (!config->ipv6_address) {
@@ -1140,12 +1139,12 @@ static void provision_service(gpointer key, gpointer 
value,
 
                if (config->ipv6_prefix_length == 0) {
                        DBG("IPv6 prefix missing");
-                       return;
+                       return -EINVAL;
                }
 
                address = connman_ipaddress_alloc(AF_INET6);
                if (!address)
-                       return;
+                       return -ENOENT;
 
                connman_ipaddress_set_ipv6(address, config->ipv6_address,
                                        config->ipv6_prefix_length,
@@ -1185,12 +1184,12 @@ static void provision_service(gpointer key, gpointer 
value,
 
                if (!config->ipv4_netmask) {
                        DBG("IPv4 netmask missing");
-                       return;
+                       return -EINVAL;
                }
 
                address = connman_ipaddress_alloc(AF_INET);
                if (!address)
-                       return;
+                       return -ENOENT;
 
                connman_ipaddress_set_ipv4(address, config->ipv4_address,
                                        config->ipv4_netmask,
@@ -1253,7 +1252,7 @@ static void provision_service(gpointer key, gpointer 
value,
 
        __connman_service_mark_dirty();
 
-       __connman_service_save(service);
+       __connman_service_load_minimal(service);
 
        if (config->virtual) {
                struct connect_virtual *virtual;
@@ -1265,13 +1264,21 @@ static void provision_service(gpointer key, gpointer 
value,
                g_timeout_add(0, remove_virtual_config, virtual);
        } else
                
__connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
+
+       return 0;
+}
+
+static void provision_service(gpointer key, gpointer value, gpointer user_data)
+{
+       try_provision_service(key, value, user_data);
 }
 
 int __connman_config_provision_service(struct connman_service *service)
 {
        enum connman_service_type type;
-       GHashTableIter iter;
-       gpointer value, key;
+       GHashTableIter iter, iter_service;
+       gpointer value, key, value_service, key_service;
+       int ret = -ENOENT;
 
        /* For now only WiFi, Gadget and Ethernet services are supported */
        type = connman_service_get_type(service);
@@ -1288,11 +1295,17 @@ int __connman_config_provision_service(struct 
connman_service *service)
        while (g_hash_table_iter_next(&iter, &key, &value)) {
                struct connman_config *config = value;
 
-               g_hash_table_foreach(config->service_table,
-                                               provision_service, service);
+               g_hash_table_iter_init(&iter_service, config->service_table);
+               while (g_hash_table_iter_next(&iter_service, &key_service,
+                                               &value_service)) {
+                       if (!(ret = try_provision_service(key_service,
+                                               value_service, service)))
+                               goto out;
+               }
        }
 
-       return 0;
+out:
+       return ret;
 }
 
 int __connman_config_provision_service_ident(struct connman_service *service,
diff --git a/src/service.c b/src/service.c
index 48b0609..c871234 100644
--- a/src/service.c
+++ b/src/service.c
@@ -6241,9 +6241,13 @@ static int service_register(struct connman_service 
*service)
 
        DBG("path %s", service->path);
 
-       __connman_config_provision_service(service);
-
-       service_load(service);
+       /*
+        * We only load the service data if we could not provision
+        * the service. This way the provisioned service is not overwritten
+        * when loading the service from the settings file.
+        */
+       if (__connman_config_provision_service(service) < 0)
+               service_load(service);
 
        g_dbus_register_interface(connection, service->path,
                                        CONNMAN_SERVICE_INTERFACE,
-- 
1.8.3.1

_______________________________________________
connman mailing list
connman@connman.net
https://lists.connman.net/mailman/listinfo/connman

Reply via email to