Commit 52e96be3 authored by Dan Williams's avatar Dan Williams

core: split out config file handling

Make config file stuff somewhat clearer and easier to understand,
and possibly easier to extend later.
parent 1f835b0a
......@@ -142,6 +142,8 @@ NetworkManager_SOURCES = \
nm-ip6-config.h \
nm-active-connection.h \
nm-active-connection.c \
nm-config.h \
nm-config.c \
main.c \
nm-policy.c \
nm-policy.h \
......
......@@ -50,14 +50,13 @@
#include "nm-vpn-manager.h"
#include "nm-logging.h"
#include "nm-policy-hosts.h"
#include "nm-config.h"
#if !defined(NM_DIST_VERSION)
# define NM_DIST_VERSION VERSION
#endif
#define NM_DEFAULT_PID_FILE LOCALSTATEDIR"/run/NetworkManager.pid"
#define NM_DEFAULT_SYSTEM_CONF_FILE SYSCONFDIR"/NetworkManager/NetworkManager.conf"
#define NM_OLD_SYSTEM_CONF_FILE SYSCONFDIR"/NetworkManager/nm-system-settings.conf"
#define NM_DEFAULT_SYSTEM_STATE_FILE LOCALSTATEDIR"/lib/NetworkManager/NetworkManager.state"
/*
......@@ -309,46 +308,6 @@ done:
return nm_running;
}
static gboolean
parse_config_file (const char *filename,
char **plugins,
char **dhcp_client,
char ***dns_plugins,
char **log_level,
char **log_domains,
GError **error)
{
GKeyFile *config;
gboolean success = FALSE;
config = g_key_file_new ();
if (!config) {
g_set_error (error, 0, 0,
"Not enough memory to load config file.");
return FALSE;
}
g_key_file_set_list_separator (config, ',');
if (!g_key_file_load_from_file (config, filename, G_KEY_FILE_NONE, error))
goto out;
*plugins = g_key_file_get_value (config, "main", "plugins", error);
if (*error)
goto out;
*dhcp_client = g_key_file_get_value (config, "main", "dhcp", NULL);
*dns_plugins = g_key_file_get_string_list (config, "main", "dns", NULL, NULL);
*log_level = g_key_file_get_value (config, "logging", "level", NULL);
*log_domains = g_key_file_get_value (config, "logging", "domains", NULL);
success = TRUE;
out:
g_key_file_free (config);
return success;
}
static gboolean
parse_state_file (const char *filename,
gboolean *net_enabled,
......@@ -469,10 +428,9 @@ main (int argc, char *argv[])
GOptionContext *opt_ctx = NULL;
gboolean become_daemon = FALSE;
gboolean g_fatal_warnings = FALSE;
char *pidfile = NULL, *state_file = NULL, *dhcp = NULL;
char *config = NULL, *plugins = NULL, *conf_plugins = NULL;
char *pidfile = NULL, *state_file = NULL;
char *config_path = NULL, *plugins = NULL;
char *log_level = NULL, *log_domains = NULL;
char **dns = NULL;
gboolean wifi_enabled = TRUE, net_enabled = TRUE, wwan_enabled = TRUE, wimax_enabled = TRUE;
gboolean success, show_version = FALSE;
NMPolicy *policy = NULL;
......@@ -482,9 +440,9 @@ main (int argc, char *argv[])
NMSupplicantManager *sup_mgr = NULL;
NMDHCPManager *dhcp_mgr = NULL;
NMSettings *settings = NULL;
NMConfig *config;
GError *error = NULL;
gboolean wrote_pidfile = FALSE;
char *cfg_log_level = NULL, *cfg_log_domains = NULL;
GOptionEntry options[] = {
{ "version", 0, 0, G_OPTION_ARG_NONE, &show_version, "Print NetworkManager version and exit", NULL },
......@@ -492,7 +450,7 @@ main (int argc, char *argv[])
{ "g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &g_fatal_warnings, "Make all warnings fatal", NULL },
{ "pid-file", 0, 0, G_OPTION_ARG_FILENAME, &pidfile, "Specify the location of a PID file", "filename" },
{ "state-file", 0, 0, G_OPTION_ARG_FILENAME, &state_file, "State file location", "/path/to/state.file" },
{ "config", 0, 0, G_OPTION_ARG_FILENAME, &config, "Config file location", "/path/to/config.file" },
{ "config", 0, 0, G_OPTION_ARG_FILENAME, &config_path, "Config file location", "/path/to/config.file" },
{ "plugins", 0, 0, G_OPTION_ARG_STRING, &plugins, "List of plugins separated by ','", "plugin1,plugin2" },
{ "log-level", 0, 0, G_OPTION_ARG_STRING, &log_level, "Log level: one of [ERR, WARN, INFO, DEBUG]", "INFO" },
{ "log-domains", 0, 0, G_OPTION_ARG_STRING, &log_domains,
......@@ -554,58 +512,18 @@ main (int argc, char *argv[])
if (check_pidfile (pidfile))
exit (1);
/* Parse the config file */
if (config) {
if (!parse_config_file (config, &conf_plugins, &dhcp, &dns, &cfg_log_level, &cfg_log_domains, &error)) {
fprintf (stderr, "Config file %s invalid: (%d) %s\n",
config,
error ? error->code : -1,
(error && error->message) ? error->message : "unknown");
exit (1);
}
} else {
gboolean parsed = FALSE;
/* Even though we prefer NetworkManager.conf, we need to check the
* old nm-system-settings.conf first to preserve compat with older
* setups. In package managed systems dropping a NetworkManager.conf
* onto the system would make NM use it instead of nm-system-settings.conf,
* changing behavior during an upgrade. We don't want that.
*/
/* Try deprecated nm-system-settings.conf first */
if (g_file_test (NM_OLD_SYSTEM_CONF_FILE, G_FILE_TEST_EXISTS)) {
config = g_strdup (NM_OLD_SYSTEM_CONF_FILE);
parsed = parse_config_file (config, &conf_plugins, &dhcp, &dns, &cfg_log_level, &cfg_log_domains, &error);
if (!parsed) {
fprintf (stderr, "Default config file %s invalid: (%d) %s\n",
config,
error ? error->code : -1,
(error && error->message) ? error->message : "unknown");
g_free (config);
config = NULL;
g_clear_error (&error);
}
}
/* Try the preferred NetworkManager.conf last */
if (!parsed && g_file_test (NM_DEFAULT_SYSTEM_CONF_FILE, G_FILE_TEST_EXISTS)) {
config = g_strdup (NM_DEFAULT_SYSTEM_CONF_FILE);
parsed = parse_config_file (config, &conf_plugins, &dhcp, &dns, &cfg_log_level, &cfg_log_domains, &error);
if (!parsed) {
fprintf (stderr, "Default config file %s invalid: (%d) %s\n",
config,
error ? error->code : -1,
(error && error->message) ? error->message : "unknown");
g_free (config);
config = NULL;
g_clear_error (&error);
}
}
/* Read the config file and CLI overrides */
config = nm_config_new (config_path, plugins, log_level, log_domains, &error);
if (config == NULL) {
fprintf (stderr, "Failed to read configuration: (%d) %s\n",
error ? error->code : -1,
(error && error->message) ? error->message : "unknown");
exit (1);
}
/* Logging setup */
if (!nm_logging_setup (log_level ? log_level : cfg_log_level,
log_domains ? log_domains : cfg_log_domains,
if (!nm_logging_setup (nm_config_get_log_level (config),
nm_config_get_log_domains (config),
&error)) {
fprintf (stderr,
_("%s. Please use --help to see a list of valid options.\n"),
......@@ -613,10 +531,6 @@ main (int argc, char *argv[])
exit (1);
}
/* Plugins specified with '--plugins' override those of config file */
plugins = plugins ? plugins : g_strdup (conf_plugins);
g_free (conf_plugins);
/* Parse the state file */
if (!parse_state_file (state_file, &net_enabled, &wifi_enabled, &wwan_enabled, &wimax_enabled, &error)) {
fprintf (stderr, "State file %s parsing failed: (%d) %s\n",
......@@ -683,8 +597,7 @@ main (int argc, char *argv[])
nm_log_info (LOGD_CORE, "NetworkManager (version " NM_DIST_VERSION ") is starting...");
success = FALSE;
if (config)
nm_log_info (LOGD_CORE, "Read config file %s", config);
nm_log_info (LOGD_CORE, "Read config file %s", nm_config_get_path (config));
main_loop = g_main_loop_new (NULL, FALSE);
......@@ -704,13 +617,15 @@ main (int argc, char *argv[])
goto done;
}
dns_mgr = nm_dns_manager_get ((const char **) dns);
dns_mgr = nm_dns_manager_get (nm_config_get_dns_plugins (config));
if (!dns_mgr) {
nm_log_err (LOGD_CORE, "failed to start the DNS manager.");
goto done;
}
settings = nm_settings_new (config, plugins, &error);
settings = nm_settings_new (nm_config_get_path (config),
nm_config_get_plugins (config),
&error);
if (!settings) {
nm_log_err (LOGD_CORE, "failed to initialize settings storage: %s",
error && error->message ? error->message : "(unknown)");
......@@ -744,7 +659,7 @@ main (int argc, char *argv[])
}
/* Initialize DHCP manager */
dhcp_mgr = nm_dhcp_manager_new (dhcp, &error);
dhcp_mgr = nm_dhcp_manager_new (nm_config_get_dhcp_client (config), &error);
if (!dhcp_mgr) {
nm_log_err (LOGD_CORE, "failed to start the DHCP manager: %s.", error->message);
goto done;
......@@ -804,17 +719,15 @@ done:
if (pidfile && wrote_pidfile)
unlink (pidfile);
nm_config_free (config);
/* Free options */
g_free (pidfile);
g_free (state_file);
g_free (config);
g_free (config_path);
g_free (plugins);
g_free (dhcp);
g_strfreev (dns);
g_free (log_level);
g_free (log_domains);
g_free (cfg_log_level);
g_free (cfg_log_domains);
nm_log_info (LOGD_CORE, "exiting (%s)", success ? "success" : "error");
exit (success ? 0 : 1);
......
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager -- Network link manager
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2011 Red Hat, Inc.
*/
#include <config.h>
#include <string.h>
#include <stdio.h>
#include "nm-config.h"
#define NM_DEFAULT_SYSTEM_CONF_FILE SYSCONFDIR"/NetworkManager/NetworkManager.conf"
#define NM_OLD_SYSTEM_CONF_FILE SYSCONFDIR"/NetworkManager/nm-system-settings.conf"
struct NMConfig {
char *path;
char **plugins;
char *dhcp_client;
char **dns_plugins;
char *log_level;
char *log_domains;
};
/************************************************************************/
GQuark
nm_config_error_quark (void)
{
static GQuark quark = 0;
if (!quark)
quark = g_quark_from_static_string ("nm-config-error");
return quark;
}
/* This should really be standard. */
#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
GType
nm_config_error_get_type (void)
{
static GType etype = 0;
if (etype == 0) {
static const GEnumValue values[] = {
/* Not enough memory to parse the config file. */
ENUM_ENTRY (NM_CONFIG_ERROR_NO_MEMORY, "NoMemory"),
{ 0, 0, 0 }
};
etype = g_enum_register_static ("NMConfigError", values);
}
return etype;
}
/************************************************************************/
const char *
nm_config_get_path (NMConfig *config)
{
g_return_val_if_fail (config != NULL, NULL);
return config->path;
}
const char **
nm_config_get_plugins (NMConfig *config)
{
g_return_val_if_fail (config != NULL, NULL);
return (const char **) config->plugins;
}
const char *
nm_config_get_dhcp_client (NMConfig *config)
{
g_return_val_if_fail (config != NULL, NULL);
return config->dhcp_client;
}
const char **
nm_config_get_dns_plugins (NMConfig *config)
{
g_return_val_if_fail (config != NULL, NULL);
return (const char **) config->dns_plugins;
}
const char *
nm_config_get_log_level (NMConfig *config)
{
g_return_val_if_fail (config != NULL, NULL);
return config->log_level;
}
const char *
nm_config_get_log_domains (NMConfig *config)
{
g_return_val_if_fail (config != NULL, NULL);
return config->log_domains;
}
/************************************************************************/
static gboolean
fill_from_file (NMConfig *config,
const char *path,
const char *cli_plugins,
const char *cli_log_level,
const char *cli_log_domains,
GError **error)
{
GKeyFile *kf;
gboolean success = FALSE;
if (g_file_test (path, G_FILE_TEST_EXISTS) == FALSE) {
g_set_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND, "file not found");
return FALSE;
}
kf = g_key_file_new ();
if (!kf) {
g_set_error (error, NM_CONFIG_ERROR, NM_CONFIG_ERROR_NO_MEMORY,
"Not enough memory to load config file");
return FALSE;
}
g_key_file_set_list_separator (kf, ',');
if (g_key_file_load_from_file (kf, path, G_KEY_FILE_NONE, error)) {
config->path = g_strdup (path);
/* CLI provided options override config file options */
if (cli_plugins && strlen (cli_plugins))
config->plugins = g_strsplit_set (cli_plugins, ",", 0);
else
config->plugins = g_key_file_get_string_list (kf, "main", "plugins", NULL, NULL);
config->dhcp_client = g_key_file_get_value (kf, "main", "dhcp", NULL);
config->dns_plugins = g_key_file_get_string_list (kf, "main", "dns", NULL, NULL);
if (cli_log_level && strlen (cli_log_level))
config->log_level = g_strdup (cli_log_level);
else
config->log_level = g_key_file_get_value (kf, "logging", "level", NULL);
if (cli_log_domains && strlen (cli_log_domains))
config->log_domains = g_strdup (cli_log_domains);
else
config->log_domains = g_key_file_get_value (kf, "logging", "domains", NULL);
success = TRUE;
}
g_key_file_free (kf);
return success;
}
NMConfig *
nm_config_new (const char *cli_config_path,
const char *cli_plugins,
const char *cli_log_level,
const char *cli_log_domains,
GError **error)
{
NMConfig *config;
GError *local = NULL;
config = g_malloc0 (sizeof (*config));
if (cli_config_path) {
/* Bad user-specific config file path is a hard error */
if (!fill_from_file (config, cli_config_path, cli_plugins, cli_log_level, cli_log_domains, error)) {
nm_config_free (config);
return NULL;
}
return config;
}
/* Even though we prefer NetworkManager.conf, we need to check the
* old nm-system-settings.conf first to preserve compat with older
* setups. In package managed systems dropping a NetworkManager.conf
* onto the system would make NM use it instead of nm-system-settings.conf,
* changing behavior during an upgrade. We don't want that.
*/
/* Try deprecated nm-system-settings.conf first */
if (fill_from_file (config, NM_OLD_SYSTEM_CONF_FILE, cli_plugins, cli_log_level, cli_log_domains, &local))
return config;
if (g_error_matches (local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND) == FALSE) {
fprintf (stderr, "Default config file %s invalid: (%d) %s\n",
NM_OLD_SYSTEM_CONF_FILE,
local ? local->code : -1,
(local && local->message) ? local->message : "unknown");
}
g_clear_error (&local);
/* Try the standard config file location next */
if (fill_from_file (config, NM_DEFAULT_SYSTEM_CONF_FILE, cli_plugins, cli_log_level, cli_log_domains, &local))
return config;
if (g_error_matches (local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND) == FALSE) {
fprintf (stderr, "Default config file %s invalid: (%d) %s\n",
NM_DEFAULT_SYSTEM_CONF_FILE,
local ? local->code : -1,
(local && local->message) ? local->message : "unknown");
}
g_propagate_error (error, local);
return config;
}
void
nm_config_free (NMConfig *config)
{
g_return_if_fail (config != NULL);
g_free (config->path);
g_strfreev (config->plugins);
g_free (config->dhcp_client);
g_strfreev (config->dns_plugins);
g_free (config->log_level);
g_free (config->log_domains);
memset (config, 0, sizeof (*config));
g_free (config);
}
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager -- Network link manager
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2011 Red Hat, Inc.
*/
#ifndef NM_CONFIG_H
#define NM_CONFIG_H
#include <glib.h>
#include <glib-object.h>
typedef struct NMConfig NMConfig;
typedef enum {
NM_CONFIG_ERROR_NO_MEMORY = 0,
} NMConfigError;
#define NM_CONFIG_ERROR (nm_config_error_quark ())
GQuark nm_config_error_quark (void);
#define NM_TYPE_CONFIG_ERROR (nm_config_error_get_type ())
GType nm_config_error_get_type (void);
NMConfig *nm_config_new (const char *cli_config_path,
const char *cli_plugins,
const char *cli_log_level,
const char *cli_log_domains,
GError **error);
const char *nm_config_get_path (NMConfig *config);
const char **nm_config_get_plugins (NMConfig *config);
const char *nm_config_get_dhcp_client (NMConfig *config);
const char **nm_config_get_dns_plugins (NMConfig *config);
const char *nm_config_get_log_level (NMConfig *config);
const char *nm_config_get_log_domains (NMConfig *config);
void nm_config_free (NMConfig *config);
#endif /* NM_CONFIG_H */
......@@ -27,6 +27,7 @@
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <gmodule.h>
#include <net/ethernet.h>
#include <netinet/ether.h>
......@@ -546,24 +547,23 @@ find_plugin (GSList *list, const char *pname)
}
static gboolean
load_plugins (NMSettings *self, const char *plugins, GError **error)
load_plugins (NMSettings *self, const char **plugins, GError **error)
{
GSList *list = NULL;
char **plist;
char **iter;
const char **iter;
gboolean success = TRUE;
plist = g_strsplit (plugins, ",", 0);
if (!plist)
return FALSE;
for (iter = plist; *iter; iter++) {
for (iter = plugins; *iter; iter++) {
GModule *plugin;
char *full_name, *path;
const char *pname = g_strstrip (*iter);
const char *pname = *iter;
GObject *obj;
GObject * (*factory_func) (void);
/* strip leading spaces */
while (isblank (*pname))
pname++;
/* keyfile plugin built in now */
if (!strcmp (pname, "keyfile"))
continue;
......@@ -616,8 +616,6 @@ load_plugins (NMSettings *self, const char *plugins, GError **error)
list = g_slist_append (list, obj);
}
g_strfreev (plist);
g_slist_foreach (list, (GFunc) g_object_unref, NULL);
g_slist_free (list);
......@@ -1494,7 +1492,7 @@ nm_settings_device_removed (NMSettings *self, NMDevice *device)
NMSettings *
nm_settings_new (const char *config_file,
const char *plugins,
const char **plugins,
GError **error)
{
NMSettings *self;
......
......@@ -77,7 +77,7 @@ typedef struct {
GType nm_settings_get_type (void);
NMSettings *nm_settings_new (const char *config_file,
const char *plugins,
const char **plugins,
GError **error);
typedef void (*NMSettingsForEachFunc) (NMSettings *settings,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment