summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomasz Bursztyka <tomasz.bursztyka@linux.intel.com>2013-02-25 17:49:50 +0200
committerPatrik Flykt <patrik.flykt@linux.intel.com>2013-02-26 12:48:06 +0200
commite8a408eb0014771357cba2ce7399da906784c1e7 (patch)
treefc9bde00e8fc351bc886eb478d089f0bfd4ca2bc
parent143ef96a6fcd70d7e461882f9dcdf97b18694940 (diff)
downloadconnman-e8a408eb0014771357cba2ce7399da906784c1e7.tar.gz
connman-e8a408eb0014771357cba2ce7399da906784c1e7.tar.bz2
connman-e8a408eb0014771357cba2ce7399da906784c1e7.zip
config: Add a function to provision mutable service
The point here is to create a virtual configuration, which does not come from a real file. This is a handy way for plugins to be able to provision services without creating any file on the FS. In case of a wifi configuration type and if connect is requested, it will trigger a scan, thus leading to a possible service being provisioned by such virtual configuration. If so and if connect was requested: the service will be asked to connect.
-rw-r--r--include/provision.h1
-rw-r--r--src/config.c105
2 files changed, 104 insertions, 2 deletions
diff --git a/include/provision.h b/include/provision.h
index d6d7c72c..b5f736e8 100644
--- a/include/provision.h
+++ b/include/provision.h
@@ -42,6 +42,7 @@ struct connman_config_entry {
connman_bool_t hidden;
};
+int connman_config_provision_mutable_service(GKeyFile *keyfile);
struct connman_config_entry **connman_config_get_entries(const char *type);
void connman_config_free_entries(struct connman_config_entry **entries);
diff --git a/src/config.c b/src/config.c
index 098ef610..63c15ea7 100644
--- a/src/config.c
+++ b/src/config.c
@@ -56,6 +56,8 @@ struct connman_config_service {
char *config_ident; /* file prefix */
char *config_entry; /* entry name */
connman_bool_t hidden;
+ connman_bool_t virtual;
+ char *virtual_file;
char *ipv4_address;
char *ipv4_netmask;
char *ipv4_gateway;
@@ -173,6 +175,9 @@ static void unregister_service(gpointer data)
protected_services = g_slist_remove(protected_services,
config_service);
+ if (config_service->virtual == TRUE)
+ goto free_only;
+
for (list = config_service->service_identifiers; list != NULL;
list = list->next) {
service_id = list->data;
@@ -238,6 +243,7 @@ free_only:
g_slist_free_full(config_service->service_identifiers, g_free);
g_free(config_service->config_ident);
g_free(config_service->config_entry);
+ g_free(config_service->virtual_file);
g_free(config_service);
}
@@ -1021,6 +1027,23 @@ static void provision_service_wifi(gpointer key,
__connman_service_set_hidden(service);
}
+struct connect_virtual {
+ struct connman_service *service;
+ const char *vfile;
+};
+
+static gboolean remove_virtual_config(gpointer user_data)
+{
+ struct connect_virtual *virtual = user_data;
+
+ __connman_service_connect(virtual->service);
+ g_hash_table_remove(config_table, virtual->vfile);
+
+ g_free(virtual);
+
+ return FALSE;
+}
+
static void provision_service(gpointer key, gpointer value,
gpointer user_data)
{
@@ -1157,7 +1180,8 @@ static void provision_service(gpointer key, gpointer value,
g_slist_prepend(config->service_identifiers,
g_strdup(service_id));
- __connman_service_set_immutable(service, TRUE);
+ if (config->virtual == FALSE)
+ __connman_service_set_immutable(service, TRUE);
__connman_service_set_favorite_delayed(service, TRUE, TRUE);
@@ -1197,7 +1221,16 @@ static void provision_service(gpointer key, gpointer value,
__connman_service_save(service);
- __connman_service_auto_connect();
+ if (config->virtual == TRUE) {
+ struct connect_virtual *virtual;
+
+ virtual = g_malloc0(sizeof(struct connect_virtual));
+ virtual->service = service;
+ virtual->vfile = config->virtual_file;
+
+ g_timeout_add(0, remove_virtual_config, virtual);
+ } else
+ __connman_service_auto_connect();
}
int __connman_config_provision_service(struct connman_service *service)
@@ -1294,6 +1327,74 @@ int __connman_config_provision_service_ident(struct connman_service *service,
return ret;
}
+static void generate_random_string(char *str, int length)
+{
+ uint8_t val;
+ int i;
+
+ memset(str, '\0', length);
+
+ for (i = 0; i < length-1; i++) {
+ do {
+ val = (uint8_t)(random() % 122);
+ if (val < 48)
+ val += 48;
+ } while((val > 57 && val < 65) || (val > 90 && val < 97));
+
+ str[i] = val;
+ }
+}
+
+int connman_config_provision_mutable_service(GKeyFile *keyfile)
+{
+ struct connman_config_service *service_config;
+ struct connman_config *config;
+ char *vfile, *group;
+ char rstr[11];
+
+ DBG("");
+
+ generate_random_string(rstr, 11);
+
+ vfile = g_strdup_printf("service_mutable_%s.config", rstr);
+
+ config = create_config(vfile);
+ if (config == NULL)
+ return -ENOMEM;
+
+ if (load_service_from_keyfile(keyfile, config) == FALSE)
+ goto error;
+
+ group = g_key_file_get_start_group(keyfile);
+
+ service_config = g_hash_table_lookup(config->service_table, group+8);
+ if (service_config == NULL)
+ goto error;
+
+ /* Specific to non file based config: */
+ g_free(service_config->config_ident);
+ service_config->config_ident = NULL;
+ g_free(service_config->config_entry);
+ service_config->config_entry = NULL;
+
+ service_config->virtual = TRUE;
+ service_config->virtual_file = vfile;
+
+ __connman_service_provision_changed(vfile);
+
+ if (g_strcmp0(service_config->type, "wifi") == 0)
+ __connman_device_request_scan(CONNMAN_SERVICE_TYPE_WIFI);
+
+ return 0;
+
+error:
+ DBG("Could not proceed");
+ g_hash_table_remove(config_table, vfile);
+ g_free(vfile);
+
+ return -EINVAL;
+}
+
struct connman_config_entry **connman_config_get_entries(const char *type)
{
GHashTableIter iter_file, iter_config;