[PATCH 3/9] vpn-settings: Add callback for processing configs, support conf.d

Jussi Laakkonen <[email protected]> Wed, 20 May 2026 16:47:07 +0300
Newsgroups dev.linux.lists.connman
Message-ID <[email protected]>
Reformat init to allow processing of separate config files with a
separate callback for the conf.d support.

Cleanup conf loading.

Support conf.d style setting override by freeing the old ones first.
---
 vpn/main.c         |  5 +--
 vpn/vpn-settings.c | 83 ++++++++++++++++++++++++++++++++--------------
 vpn/vpn.h          |  4 ++-
 3 files changed, 64 insertions(+), 28 deletions(-)

diff --git a/vpn/main.c b/vpn/main.c
index 92c63e20..1965c34b 100644
--- a/vpn/main.c
+++ b/vpn/main.c
@@ -3,6 +3,7 @@
  *  ConnMan VPN daemon
  *
  *  Copyright (C) 2012-2013  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2025  Jolla Mobile Ltd. All right reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2 as
@@ -250,9 +251,9 @@ int main(int argc, char *argv[])
 	__connman_dbus_init(conn);
 
 	if (!option_config)
-		__vpn_settings_init(CONFIGMAINFILE);
+		__vpn_settings_init(CONFIGMAINFILE, CONFIGDIR);
 	else
-		__vpn_settings_init(option_config);
+		__vpn_settings_init(option_config, CONFIGDIR);
 
 	__connman_inotify_init();
 	__connman_agent_init();
diff --git a/vpn/vpn-settings.c b/vpn/vpn-settings.c
index e78e5019..78a1bfb2 100644
--- a/vpn/vpn-settings.c
+++ b/vpn/vpn-settings.c
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 2012-2013  Intel Corporation. All rights reserved.
  *  Copyright (C) 2018-2020 Jolla Ltd. All rights reserved.
+ *  Copyright (C) 2025  Jolla Mobile Ltd. All right reserved.
  *  Contact: [email protected]
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -41,13 +42,7 @@ static struct {
 	char *binary_group;
 	char **binary_supplementary_groups;
 	char **system_binary_users;
-} connman_vpn_settings  = {
-	.timeout_inputreq		= DEFAULT_INPUT_REQUEST_TIMEOUT,
-	.binary_user			= NULL,
-	.binary_group			= NULL,
-	.binary_supplementary_groups	= NULL,
-	.system_binary_users		= NULL,
-};
+} connman_vpn_settings = { 0 };
 
 struct vpn_plugin_data {
 	char *binary_user;
@@ -56,6 +51,7 @@ struct vpn_plugin_data {
 };
 
 GHashTable *plugin_hash = NULL;
+static char *configdir = NULL;
 
 bool vpn_settings_is_system_user(const char *user)
 {
@@ -164,6 +160,8 @@ static char **get_string_list(GKeyFile *config, const char *group,
 static void parse_config(GKeyFile *config, const char *file)
 {
 	const char *group = "General";
+	char **str_list = NULL;
+	char *str = NULL;
 	GError *error = NULL;
 	int timeout;
 
@@ -179,16 +177,29 @@ static void parse_config(GKeyFile *config, const char *file)
 
 	g_clear_error(&error);
 
-	connman_vpn_settings.binary_user = get_string(config, VPN_GROUP,
-						"User");
-	connman_vpn_settings.binary_group = get_string(config, VPN_GROUP,
-						"Group");
-	connman_vpn_settings.binary_supplementary_groups = get_string_list(
-						config, VPN_GROUP,
-						"SupplementaryGroups");
-	connman_vpn_settings.system_binary_users = get_string_list(
-						config, VPN_GROUP,
-						"SystemBinaryUsers");
+	str = get_string(config, VPN_GROUP, "User");
+	if (str) {
+		g_free(connman_vpn_settings.binary_user);
+		connman_vpn_settings.binary_user = str;
+	}
+
+	str = get_string(config, VPN_GROUP, "Group");
+	if (str) {
+		g_free(connman_vpn_settings.binary_group);
+		connman_vpn_settings.binary_group = str;
+	}
+
+	str_list = get_string_list(config, VPN_GROUP, "SupplementaryGroups");
+	if (str_list) {
+		g_strfreev(connman_vpn_settings.binary_supplementary_groups);
+		connman_vpn_settings.binary_supplementary_groups = str_list;
+	}
+
+	str_list = get_string_list(config, VPN_GROUP, "SystemBinaryUsers");
+	if (str_list) {
+		g_strfreev(connman_vpn_settings.system_binary_users);
+		connman_vpn_settings.system_binary_users = str_list;
+	}
 }
 
 struct vpn_plugin_data *vpn_settings_get_vpn_plugin_config(const char *name)
@@ -275,31 +286,50 @@ GKeyFile *__vpn_settings_load_config(const char *file)
 	g_key_file_set_list_separator(keyfile, ',');
 
 	if (!g_key_file_load_from_file(keyfile, file, 0, &err)) {
-		if (err->code != G_FILE_ERROR_NOENT) {
+		if (err->code != G_FILE_ERROR_NOENT)
 			connman_error("Parsing %s failed: %s", file,
 								err->message);
-		}
 
-		g_error_free(err);
 		g_key_file_unref(keyfile);
-		return NULL;
+		keyfile = NULL;
 	}
 
+	g_clear_error(&err);
+
 	return keyfile;
 }
 
-int __vpn_settings_init(const char *file)
+int __vpn_settings_process_config(const char *configfile)
 {
 	GKeyFile *config;
 
-	config = __vpn_settings_load_config(file);
-	parse_config(config, file);
-	if (config)
+	if (!configfile)
+		return -EINVAL;
+
+	DBG("%s", configfile);
+
+	config = __vpn_settings_load_config(configfile);
+	if (config) {
+		parse_config(config, configfile);
 		g_key_file_unref(config);
+	}
 
 	return 0;
 }
 
+int __vpn_settings_init(const char *file, const char *dir)
+{
+	if (!file || !dir)
+		return -EINVAL;
+
+	memset(&connman_vpn_settings, 0, sizeof(connman_vpn_settings));
+	connman_vpn_settings.timeout_inputreq = DEFAULT_INPUT_REQUEST_TIMEOUT;
+
+	configdir = g_build_filename(dir, PLUGIN_CONFIGDIR, NULL);
+
+	return __vpn_settings_process_config(file);
+}
+
 void __vpn_settings_cleanup()
 {
 	g_free(connman_vpn_settings.binary_user);
@@ -307,6 +337,9 @@ void __vpn_settings_cleanup()
 	g_strfreev(connman_vpn_settings.binary_supplementary_groups);
 	g_strfreev(connman_vpn_settings.system_binary_users);
 
+	g_free(configdir);
+	configdir = NULL;
+
 	if (plugin_hash) {
 		g_hash_table_destroy(plugin_hash);
 		plugin_hash = NULL;
diff --git a/vpn/vpn.h b/vpn/vpn.h
index 1f8c8fcd..5e30ea36 100644
--- a/vpn/vpn.h
+++ b/vpn/vpn.h
@@ -3,6 +3,7 @@
  *  ConnMan VPN daemon
  *
  *  Copyright (C) 2012-2013  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2025  Jolla Mobile Ltd. All right reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2 as
@@ -114,7 +115,8 @@ char **__vpn_config_get_string_list(GKeyFile *key_file, const char *group_name,
 bool __vpn_config_get_boolean(GKeyFile *key_file, const char *group_name,
 			const char *key, bool default_value);
 
-int __vpn_settings_init(const char *file);
+int __vpn_settings_init(const char *file, const char *dir);
+int __vpn_settings_process_config(const char *configfile);
 void __vpn_settings_cleanup(void);
 GKeyFile *__vpn_settings_load_config(const char *file);
 unsigned int __vpn_settings_get_timeout_inputreq(void);
-- 
2.47.3