config,connectivity: merge branch 'th/rh1066697_reload_config'

Refactor NMConfig to support reloading.

Implement reloading of NMConnectivity parameters

https://bugzilla.redhat.com/show_bug.cgi?id=1066697
This commit is contained in:
Thomas Haller
2015-02-03 15:49:11 +01:00
20 changed files with 1383 additions and 444 deletions

View File

@@ -287,6 +287,8 @@ nm_sources = \
nm-active-connection.h \
nm-config.c \
nm-config.h \
nm-config-data.c \
nm-config-data.h \
nm-connection-provider.c \
nm-connection-provider.h \
nm-connectivity.c \

View File

@@ -1463,7 +1463,7 @@ new_default_connection (NMDevice *self)
const char *hw_address;
char *defname, *uuid;
if (!nm_config_get_ethernet_can_auto_default (nm_config_get (), self))
if (nm_config_get_no_auto_default_for_device (nm_config_get (), self))
return NULL;
hw_address = nm_device_get_hw_address (self);

View File

@@ -40,9 +40,7 @@
static gboolean
sighup_handler (gpointer user_data)
{
/* Reread config stuff like system config files, VPN service files, etc */
nm_log_info (LOGD_CORE, "caught SIGHUP, not supported yet.");
nm_main_config_reload ();
return G_SOURCE_CONTINUE;
}
@@ -177,7 +175,8 @@ nm_main_utils_early_setup (const char *progname,
char **argv[],
int *argc,
GOptionEntry *options,
GOptionEntry *more_options,
void (*option_context_hook) (gpointer user_data, GOptionContext *opt_ctx),
gpointer option_context_hook_data,
const char *summary)
{
GOptionContext *opt_ctx = NULL;
@@ -220,9 +219,9 @@ nm_main_utils_early_setup (const char *progname,
g_option_context_set_ignore_unknown_options (opt_ctx, FALSE);
g_option_context_set_help_enabled (opt_ctx, TRUE);
g_option_context_add_main_entries (opt_ctx, options, NULL);
if (more_options)
g_option_context_add_main_entries (opt_ctx, more_options, NULL);
g_option_context_set_summary (opt_ctx, summary);
if (option_context_hook)
option_context_hook (option_context_hook_data, opt_ctx);
success = g_option_context_parse (opt_ctx, argc, argv, &error);
if (!success) {

View File

@@ -33,7 +33,13 @@ gboolean nm_main_utils_early_setup (const char *progname,
char **argv[],
int *argc,
GOptionEntry *options,
GOptionEntry *more_options,
void (*option_context_hook) (gpointer user_data, GOptionContext *opt_ctx),
gpointer option_context_hook_data,
const char *summary);
/* The following functions are not implemented inside nm-main-utils.c, instead
* main.c and nm-iface-helper.c */
void nm_main_config_reload (void);
#endif /* __MAIN_UTILS_H__ */

View File

@@ -175,6 +175,19 @@ _init_nm_debug (const char *debug)
}
}
void
nm_main_config_reload ()
{
nm_log_info (LOGD_CORE, "reload configuration...");
/* The signal handler thread is only installed after
* creating NMConfig instance, and on shut down we
* no longer run the mainloop (to reach this point).
*
* Hence, a NMConfig singleton instance must always be
* available. */
nm_config_reload (nm_config_get ());
}
static void
manager_configure_quit (NMManager *manager, gpointer user_data)
{
@@ -204,6 +217,7 @@ main (int argc, char *argv[])
GError *error = NULL;
gboolean wrote_pidfile = FALSE;
char *bad_domains = NULL;
NMConfigCmdLineOptions *config_cli;
GOptionEntry options[] = {
{ "version", 'V', 0, G_OPTION_ARG_NONE, &show_version, N_("Print NetworkManager version and exit"), NULL },
@@ -224,11 +238,13 @@ main (int argc, char *argv[])
main_loop = g_main_loop_new (NULL, FALSE);
config_cli = nm_config_cmd_line_options_new ();
if (!nm_main_utils_early_setup ("NetworkManager",
&argv,
&argc,
options,
nm_config_get_options (),
(void (*)(gpointer, GOptionContext *)) nm_config_cmd_line_options_add_to_entries,
config_cli,
_("NetworkManager monitors all network connections and automatically\nchooses the best connection to use. It also allows the user to\nspecify wireless access points which wireless cards in the computer\nshould associate with.")))
exit (1);
@@ -290,7 +306,9 @@ main (int argc, char *argv[])
exit (1);
/* Read the config file and CLI overrides */
config = nm_config_new (&error);
config = nm_config_setup (config_cli, &error);
nm_config_cmd_line_options_free (config_cli);
config_cli = NULL;
if (config == NULL) {
fprintf (stderr, _("Failed to read configuration: (%d) %s\n"),
error ? error->code : -1,
@@ -369,7 +387,7 @@ main (int argc, char *argv[])
nm_log_info (LOGD_CORE, "NetworkManager (version " NM_DIST_VERSION ") is starting...");
success = FALSE;
nm_log_info (LOGD_CORE, "Read config: %s", nm_config_get_description (config));
nm_log_info (LOGD_CORE, "Read config: %s", nm_config_data_get_config_description (nm_config_get_data (config)));
nm_log_info (LOGD_CORE, "WEXT support is %s",
#if HAVE_WEXT
"enabled"

408
src/nm-config-data.c Normal file
View File

@@ -0,0 +1,408 @@
/* -*- 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.
* Copyright (C) 2013 Thomas Bechtold <thomasbechtold@jpberlin.de>
*/
#include "nm-config-data.h"
#include <string.h>
#include "nm-config.h"
#include "gsystem-local-alloc.h"
typedef struct {
char *config_main_file;
char *config_description;
GKeyFile *keyfile;
struct {
char *uri;
char *response;
guint interval;
} connectivity;
struct {
char **arr;
GSList *specs;
} no_auto_default;
} NMConfigDataPrivate;
enum {
PROP_0,
PROP_CONFIG_MAIN_FILE,
PROP_CONFIG_DESCRIPTION,
PROP_KEYFILE,
PROP_CONNECTIVITY_URI,
PROP_CONNECTIVITY_INTERVAL,
PROP_CONNECTIVITY_RESPONSE,
PROP_NO_AUTO_DEFAULT,
LAST_PROP
};
G_DEFINE_TYPE (NMConfigData, nm_config_data, G_TYPE_OBJECT)
#define NM_CONFIG_DATA_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_CONFIG_DATA, NMConfigDataPrivate))
/************************************************************************/
const char *
nm_config_data_get_config_main_file (const NMConfigData *self)
{
g_return_val_if_fail (self, NULL);
return NM_CONFIG_DATA_GET_PRIVATE (self)->config_main_file;
}
const char *
nm_config_data_get_config_description (const NMConfigData *self)
{
g_return_val_if_fail (self, NULL);
return NM_CONFIG_DATA_GET_PRIVATE (self)->config_description;
}
char *
nm_config_data_get_value (const NMConfigData *self, const char *group, const char *key, GError **error)
{
g_return_val_if_fail (self, NULL);
return g_key_file_get_string (NM_CONFIG_DATA_GET_PRIVATE (self)->keyfile, group, key, error);
}
const char *
nm_config_data_get_connectivity_uri (const NMConfigData *self)
{
g_return_val_if_fail (self, NULL);
return NM_CONFIG_DATA_GET_PRIVATE (self)->connectivity.uri;
}
const guint
nm_config_data_get_connectivity_interval (const NMConfigData *self)
{
g_return_val_if_fail (self, 0);
return MAX (NM_CONFIG_DATA_GET_PRIVATE (self)->connectivity.interval, 0);
}
const char *
nm_config_data_get_connectivity_response (const NMConfigData *self)
{
g_return_val_if_fail (self != NULL, NULL);
return NM_CONFIG_DATA_GET_PRIVATE (self)->connectivity.response;
}
const char *const*
nm_config_data_get_no_auto_default (const NMConfigData *self)
{
g_return_val_if_fail (self, FALSE);
return (const char *const*) NM_CONFIG_DATA_GET_PRIVATE (self)->no_auto_default.arr;
}
const GSList *
nm_config_data_get_no_auto_default_list (const NMConfigData *self)
{
g_return_val_if_fail (self, NULL);
return NM_CONFIG_DATA_GET_PRIVATE (self)->no_auto_default.specs;
}
/************************************************************************/
static gboolean
_keyfile_a_contains_all_in_b (GKeyFile *kf_a, GKeyFile *kf_b)
{
gs_strfreev char **groups = NULL;
guint i, j;
if (kf_a == kf_b)
return TRUE;
groups = g_key_file_get_groups (kf_a, NULL);
for (i = 0; groups && groups[i]; i++) {
gs_strfreev char **keys = NULL;
keys = g_key_file_get_keys (kf_a, groups[i], NULL, NULL);
if (keys) {
for (j = 0; keys[j]; j++) {
gs_free char *key_a = g_key_file_get_value (kf_a, groups[i], keys[j], NULL);
gs_free char *key_b = g_key_file_get_value (kf_b, groups[i], keys[j], NULL);
if (g_strcmp0 (key_a, key_b) != 0)
return FALSE;
}
}
}
return TRUE;
}
NMConfigChangeFlags
nm_config_data_diff (NMConfigData *old_data, NMConfigData *new_data)
{
NMConfigChangeFlags changes = NM_CONFIG_CHANGE_NONE;
NMConfigDataPrivate *priv_old, *priv_new;
GSList *spec_old, *spec_new;
g_return_val_if_fail (NM_IS_CONFIG_DATA (old_data), NM_CONFIG_CHANGE_NONE);
g_return_val_if_fail (NM_IS_CONFIG_DATA (new_data), NM_CONFIG_CHANGE_NONE);
priv_old = NM_CONFIG_DATA_GET_PRIVATE (old_data);
priv_new = NM_CONFIG_DATA_GET_PRIVATE (new_data);
if ( !_keyfile_a_contains_all_in_b (priv_old->keyfile, priv_new->keyfile)
|| !_keyfile_a_contains_all_in_b (priv_new->keyfile, priv_old->keyfile))
changes |= NM_CONFIG_CHANGE_VALUES;
if ( g_strcmp0 (nm_config_data_get_config_main_file (old_data), nm_config_data_get_config_main_file (new_data)) != 0
|| g_strcmp0 (nm_config_data_get_config_description (old_data), nm_config_data_get_config_description (new_data)) != 0)
changes |= NM_CONFIG_CHANGE_CONFIG_FILES;
if ( nm_config_data_get_connectivity_interval (old_data) != nm_config_data_get_connectivity_interval (new_data)
|| g_strcmp0 (nm_config_data_get_connectivity_uri (old_data), nm_config_data_get_connectivity_uri (new_data))
|| g_strcmp0 (nm_config_data_get_connectivity_response (old_data), nm_config_data_get_connectivity_response (new_data)))
changes |= NM_CONFIG_CHANGE_CONNECTIVITY;
spec_old = priv_old->no_auto_default.specs;
spec_new = priv_new->no_auto_default.specs;
while (spec_old && spec_new && strcmp (spec_old->data, spec_new->data) == 0) {
spec_old = spec_old->next;
spec_new = spec_new->next;
}
if (spec_old || spec_new)
changes |= NM_CONFIG_CHANGE_NO_AUTO_DEFAULT;
return changes;
}
/************************************************************************/
static void
get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
NMConfigData *self = NM_CONFIG_DATA (object);
switch (prop_id) {
case PROP_CONFIG_MAIN_FILE:
g_value_set_string (value, nm_config_data_get_config_main_file (self));
break;
case PROP_CONFIG_DESCRIPTION:
g_value_set_string (value, nm_config_data_get_config_description (self));
break;
case PROP_NO_AUTO_DEFAULT:
g_value_take_boxed (value, g_strdupv ((char **) nm_config_data_get_no_auto_default (self)));
break;
case PROP_CONNECTIVITY_URI:
g_value_set_string (value, nm_config_data_get_connectivity_uri (self));
break;
case PROP_CONNECTIVITY_INTERVAL:
g_value_set_uint (value, nm_config_data_get_connectivity_interval (self));
break;
case PROP_CONNECTIVITY_RESPONSE:
g_value_set_string (value, nm_config_data_get_connectivity_response (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
NMConfigData *self = NM_CONFIG_DATA (object);
NMConfigDataPrivate *priv = NM_CONFIG_DATA_GET_PRIVATE (self);
guint i;
/* This type is immutable. All properties are construct only. */
switch (prop_id) {
case PROP_CONFIG_MAIN_FILE:
priv->config_main_file = g_value_dup_string (value);
break;
case PROP_CONFIG_DESCRIPTION:
priv->config_description = g_value_dup_string (value);
break;
case PROP_KEYFILE:
priv->keyfile = g_value_dup_boxed (value);
if (!priv->keyfile)
priv->keyfile = nm_config_create_keyfile ();
break;
case PROP_NO_AUTO_DEFAULT:
priv->no_auto_default.arr = g_strdupv (g_value_get_boxed (value));
if (!priv->no_auto_default.arr)
priv->no_auto_default.arr = g_new0 (char *, 1);
for (i = 0; priv->no_auto_default.arr[i]; i++)
priv->no_auto_default.specs = g_slist_prepend (priv->no_auto_default.specs, priv->no_auto_default.arr[i]);
priv->no_auto_default.specs = g_slist_reverse (priv->no_auto_default.specs);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
dispose (GObject *object)
{
}
static void
finalize (GObject *gobject)
{
NMConfigDataPrivate *priv = NM_CONFIG_DATA_GET_PRIVATE (gobject);
g_free (priv->config_main_file);
g_free (priv->config_description);
g_free (priv->connectivity.uri);
g_free (priv->connectivity.response);
g_slist_free (priv->no_auto_default.specs);
g_strfreev (priv->no_auto_default.arr);
G_OBJECT_CLASS (nm_config_data_parent_class)->finalize (gobject);
}
static void
nm_config_data_init (NMConfigData *self)
{
}
static void
constructed (GObject *object)
{
NMConfigData *self = NM_CONFIG_DATA (object);
NMConfigDataPrivate *priv = NM_CONFIG_DATA_GET_PRIVATE (self);
int interval;
priv->connectivity.uri = g_key_file_get_value (priv->keyfile, "connectivity", "uri", NULL);
priv->connectivity.response = g_key_file_get_value (priv->keyfile, "connectivity", "response", NULL);
interval = g_key_file_get_integer (priv->keyfile, "connectivity", "interval", NULL);
priv->connectivity.interval = MAX (0, interval);
G_OBJECT_CLASS (nm_config_data_parent_class)->constructed (object);
}
NMConfigData *
nm_config_data_new (const char *config_main_file,
const char *config_description,
const char *const*no_auto_default,
GKeyFile *keyfile)
{
return g_object_new (NM_TYPE_CONFIG_DATA,
NM_CONFIG_DATA_CONFIG_MAIN_FILE, config_main_file,
NM_CONFIG_DATA_CONFIG_DESCRIPTION, config_description,
NM_CONFIG_DATA_KEYFILE, keyfile,
NM_CONFIG_DATA_NO_AUTO_DEFAULT, no_auto_default,
NULL);
}
NMConfigData *
nm_config_data_new_update_no_auto_default (const NMConfigData *base,
const char *const*no_auto_default)
{
NMConfigDataPrivate *priv = NM_CONFIG_DATA_GET_PRIVATE (base);
return g_object_new (NM_TYPE_CONFIG_DATA,
NM_CONFIG_DATA_CONFIG_MAIN_FILE, priv->config_main_file,
NM_CONFIG_DATA_CONFIG_DESCRIPTION, priv->config_description,
NM_CONFIG_DATA_KEYFILE, priv->keyfile, /* the keyfile is unchanged. It's safe to share it. */
NM_CONFIG_DATA_NO_AUTO_DEFAULT, no_auto_default,
NULL);
}
static void
nm_config_data_class_init (NMConfigDataClass *config_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (config_class);
g_type_class_add_private (config_class, sizeof (NMConfigDataPrivate));
object_class->constructed = constructed;
object_class->dispose = dispose;
object_class->finalize = finalize;
object_class->get_property = get_property;
object_class->set_property = set_property;
g_object_class_install_property
(object_class, PROP_CONFIG_MAIN_FILE,
g_param_spec_string (NM_CONFIG_DATA_CONFIG_MAIN_FILE, "", "",
NULL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property
(object_class, PROP_CONFIG_DESCRIPTION,
g_param_spec_string (NM_CONFIG_DATA_CONFIG_DESCRIPTION, "", "",
NULL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property
(object_class, PROP_KEYFILE,
g_param_spec_boxed (NM_CONFIG_DATA_KEYFILE, "", "",
G_TYPE_KEY_FILE,
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property
(object_class, PROP_CONNECTIVITY_URI,
g_param_spec_string (NM_CONFIG_DATA_CONNECTIVITY_URI, "", "",
NULL,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property
(object_class, PROP_CONNECTIVITY_INTERVAL,
g_param_spec_uint (NM_CONFIG_DATA_CONNECTIVITY_INTERVAL, "", "",
0, G_MAXUINT, 0,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property
(object_class, PROP_CONNECTIVITY_RESPONSE,
g_param_spec_string (NM_CONFIG_DATA_CONNECTIVITY_RESPONSE, "", "",
NULL,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property
(object_class, PROP_NO_AUTO_DEFAULT,
g_param_spec_boxed (NM_CONFIG_DATA_NO_AUTO_DEFAULT, "", "",
G_TYPE_STRV,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
}

91
src/nm-config-data.h Normal file
View File

@@ -0,0 +1,91 @@
/* -*- 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) 2014 Red Hat, Inc.
*/
#ifndef NM_CONFIG_DATA_H
#define NM_CONFIG_DATA_H
#include <glib.h>
#include <glib-object.h>
#include "nm-types.h"
G_BEGIN_DECLS
#define NM_TYPE_CONFIG_DATA (nm_config_data_get_type ())
#define NM_CONFIG_DATA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_CONFIG_DATA, NMConfigData))
#define NM_CONFIG_DATA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_CONFIG_DATA, NMConfigDataClass))
#define NM_IS_CONFIG_DATA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_CONFIG_DATA))
#define NM_IS_CONFIG_DATA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_CONFIG_DATA))
#define NM_CONFIG_DATA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_CONFIG_DATA, NMConfigDataClass))
#define NM_CONFIG_DATA_CONFIG_MAIN_FILE "config-main-file"
#define NM_CONFIG_DATA_CONFIG_DESCRIPTION "config-description"
#define NM_CONFIG_DATA_KEYFILE "keyfile"
#define NM_CONFIG_DATA_CONNECTIVITY_URI "connectivity-uri"
#define NM_CONFIG_DATA_CONNECTIVITY_INTERVAL "connectivity-interval"
#define NM_CONFIG_DATA_CONNECTIVITY_RESPONSE "connectivity-response"
#define NM_CONFIG_DATA_NO_AUTO_DEFAULT "no-auto-default"
typedef enum { /*< flags >*/
NM_CONFIG_CHANGE_NONE = 0,
NM_CONFIG_CHANGE_CONFIG_FILES = (1L << 0),
NM_CONFIG_CHANGE_VALUES = (1L << 1),
NM_CONFIG_CHANGE_CONNECTIVITY = (1L << 2),
NM_CONFIG_CHANGE_NO_AUTO_DEFAULT = (1L << 3),
_NM_CONFIG_CHANGE_LAST,
NM_CONFIG_CHANGE_ALL = ((_NM_CONFIG_CHANGE_LAST - 1) << 1) - 1,
} NMConfigChangeFlags;
struct _NMConfigData {
GObject parent;
};
typedef struct {
GObjectClass parent;
} NMConfigDataClass;
GType nm_config_data_get_type (void);
NMConfigData *nm_config_data_new (const char *config_main_file,
const char *config_description,
const char *const*no_auto_default,
GKeyFile *keyfile);
NMConfigData *nm_config_data_new_update_no_auto_default (const NMConfigData *base, const char *const*no_auto_default);
NMConfigChangeFlags nm_config_data_diff (NMConfigData *old_data, NMConfigData *new_data);
const char *nm_config_data_get_config_main_file (const NMConfigData *config_data);
const char *nm_config_data_get_config_description (const NMConfigData *config_data);
char *nm_config_data_get_value (const NMConfigData *config_data, const char *group, const char *key, GError **error);
const char *nm_config_data_get_connectivity_uri (const NMConfigData *config_data);
const guint nm_config_data_get_connectivity_interval (const NMConfigData *config_data);
const char *nm_config_data_get_connectivity_response (const NMConfigData *config_data);
const char *const*nm_config_data_get_no_auto_default (const NMConfigData *config_data);
const GSList * nm_config_data_get_no_auto_default_list (const NMConfigData *config_data);
G_END_DECLS
#endif /* NM_CONFIG_DATA_H */

View File

@@ -29,6 +29,9 @@
#include "nm-utils.h"
#include "nm-glib-compat.h"
#include "nm-device.h"
#include "NetworkManagerUtils.h"
#include "gsystem-local-alloc.h"
#include "nm-enum-types.h"
#include <gio/gio.h>
#include <glib/gi18n.h>
@@ -38,12 +41,28 @@
#define NM_OLD_SYSTEM_CONF_FILE NMCONFDIR "/nm-system-settings.conf"
#define NM_NO_AUTO_DEFAULT_STATE_FILE NMSTATEDIR "/no-auto-default.state"
typedef struct {
char *nm_conf_path;
struct NMConfigCmdLineOptions {
char *config_main_file;
char *config_dir;
char *no_auto_default_file;
char *plugins;
char *connectivity_uri;
/* We store interval as signed internally to track whether it's
* set or not via GOptionEntry
*/
int connectivity_interval;
char *connectivity_response;
};
typedef struct {
NMConfigCmdLineOptions cli;
NMConfigData *config_data;
NMConfigData *config_data_orig;
char *config_dir;
char *config_description;
char *no_auto_default_file;
GKeyFile *keyfile;
char **plugins;
gboolean monitor_connection_files;
@@ -56,24 +75,40 @@ typedef struct {
char *debug;
char *connectivity_uri;
gint connectivity_interval;
char *connectivity_response;
char **no_auto_default;
char **ignore_carrier;
gboolean configure_and_quit;
} NMConfigPrivate;
static NMConfig *singleton = NULL;
enum {
PROP_0,
PROP_CMD_LINE_OPTIONS,
LAST_PROP,
};
enum {
SIGNAL_CONFIG_CHANGED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
static void nm_config_initable_iface_init (GInitableIface *iface);
G_DEFINE_TYPE_WITH_CODE (NMConfig, nm_config, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_config_initable_iface_init);
)
G_DEFINE_TYPE (NMConfig, nm_config, G_TYPE_OBJECT)
#define NM_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_CONFIG, NMConfigPrivate))
/************************************************************************/
static void _set_config_data (NMConfig *self, NMConfigData *new_data);
/************************************************************************/
static gboolean
_get_bool_value (GKeyFile *keyfile,
const char *section,
@@ -109,20 +144,23 @@ _get_bool_value (GKeyFile *keyfile,
/************************************************************************/
const char *
nm_config_get_path (NMConfig *config)
NMConfigData *
nm_config_get_data (NMConfig *config)
{
g_return_val_if_fail (config != NULL, NULL);
return NM_CONFIG_GET_PRIVATE (config)->nm_conf_path;
return NM_CONFIG_GET_PRIVATE (config)->config_data;
}
const char *
nm_config_get_description (NMConfig *config)
/* The NMConfigData instance is reloadable and will be swapped on reload.
* nm_config_get_data_orig() returns the original configuration, when the NMConfig
* instance was created. */
NMConfigData *
nm_config_get_data_orig (NMConfig *config)
{
g_return_val_if_fail (config != NULL, NULL);
return NM_CONFIG_GET_PRIVATE (config)->config_description;
return NM_CONFIG_GET_PRIVATE (config)->config_data_orig;
}
const char **
@@ -189,47 +227,12 @@ nm_config_get_debug (NMConfig *config)
return NM_CONFIG_GET_PRIVATE (config)->debug;
}
const char *
nm_config_get_connectivity_uri (NMConfig *config)
{
g_return_val_if_fail (config != NULL, NULL);
return NM_CONFIG_GET_PRIVATE (config)->connectivity_uri;
}
guint
nm_config_get_connectivity_interval (NMConfig *config)
{
g_return_val_if_fail (config != NULL, 0);
/* We store interval as signed internally to track whether it's
* set or not, but report as unsigned to callers.
*/
return MAX (NM_CONFIG_GET_PRIVATE (config)->connectivity_interval, 0);
}
const char *
nm_config_get_connectivity_response (NMConfig *config)
{
g_return_val_if_fail (config != NULL, NULL);
return NM_CONFIG_GET_PRIVATE (config)->connectivity_response;
}
gboolean
nm_config_get_configure_and_quit (NMConfig *config)
{
return NM_CONFIG_GET_PRIVATE (config)->configure_and_quit;
}
char *
nm_config_get_value (NMConfig *config, const char *group, const char *key, GError **error)
{
NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (config);
return g_key_file_get_string (priv->keyfile, group, key, error);
}
gboolean
nm_config_get_ignore_carrier (NMConfig *config, NMDevice *device)
{
@@ -252,72 +255,71 @@ nm_config_get_ignore_carrier (NMConfig *config, NMDevice *device)
/************************************************************************/
static void
merge_no_auto_default_state (NMConfig *config)
static char **
no_auto_default_merge_from_file (const char *no_auto_default_file, const char *const* no_auto_default)
{
NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (config);
GPtrArray *updated;
char **list;
int i, j;
char *data;
/* If the config already matches everything, we don't need to do anything else. */
if (priv->no_auto_default && !g_strcmp0 (priv->no_auto_default[0], "*"))
return;
updated = g_ptr_array_new ();
if (priv->no_auto_default) {
for (i = 0; priv->no_auto_default[i]; i++)
g_ptr_array_add (updated, priv->no_auto_default[i]);
g_free (priv->no_auto_default);
if (no_auto_default) {
for (i = 0; no_auto_default[i]; i++)
g_ptr_array_add (updated, g_strdup (no_auto_default[i]));
}
if (g_file_get_contents (priv->no_auto_default_file, &data, NULL, NULL)) {
if ( no_auto_default_file
&& g_file_get_contents (no_auto_default_file, &data, NULL, NULL)) {
list = g_strsplit (data, "\n", -1);
for (i = 0; list[i]; i++) {
if (!*list[i])
continue;
for (j = 0; j < updated->len; j++) {
if (!strcmp (list[i], updated->pdata[j]))
break;
g_free (list[i]);
else {
for (j = 0; j < updated->len; j++) {
if (!strcmp (list[i], updated->pdata[j]))
break;
}
if (j == updated->len)
g_ptr_array_add (updated, list[i]);
else
g_free (list[i]);
}
if (j == updated->len)
g_ptr_array_add (updated, list[i]);
}
g_free (list);
g_free (data);
}
g_ptr_array_add (updated, NULL);
priv->no_auto_default = (char **) g_ptr_array_free (updated, FALSE);
return (char **) g_ptr_array_free (updated, FALSE);
}
gboolean
nm_config_get_ethernet_can_auto_default (NMConfig *config, NMDevice *device)
nm_config_get_no_auto_default_for_device (NMConfig *self, NMDevice *device)
{
NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (config);
GSList *specs = NULL;
int i;
gboolean match;
NMConfigData *config_data;
for (i = 0; priv->no_auto_default[i]; i++)
specs = g_slist_prepend (specs, priv->no_auto_default[i]);
g_return_val_if_fail (NM_IS_CONFIG (self), FALSE);
g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
match = nm_device_spec_match_list (device, specs);
g_slist_free (specs);
return !match;
config_data = NM_CONFIG_GET_PRIVATE (self)->config_data;
return nm_device_spec_match_list (device, nm_config_data_get_no_auto_default_list (config_data));
}
void
nm_config_set_ethernet_no_auto_default (NMConfig *config, NMDevice *device)
nm_config_set_no_auto_default_for_device (NMConfig *self, NMDevice *device)
{
NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (config);
NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (self);
char *current;
GString *updated;
GError *error = NULL;
char **no_auto_default;
NMConfigData *new_data = NULL;
if (!nm_config_get_ethernet_can_auto_default (config, device))
g_return_if_fail (NM_IS_CONFIG (self));
g_return_if_fail (NM_IS_DEVICE (device));
if (nm_config_get_no_auto_default_for_device (self, device))
return;
updated = g_string_new (NULL);
@@ -339,48 +341,111 @@ nm_config_set_ethernet_no_auto_default (NMConfig *config, NMDevice *device)
g_string_free (updated, TRUE);
merge_no_auto_default_state (config);
no_auto_default = no_auto_default_merge_from_file (priv->no_auto_default_file, nm_config_data_get_no_auto_default (priv->config_data));
new_data = nm_config_data_new_update_no_auto_default (priv->config_data, (const char *const*) no_auto_default);
g_strfreev (no_auto_default);
_set_config_data (self, new_data);
}
/************************************************************************/
static char *cli_config_path;
static char *cli_config_dir;
static char *cli_no_auto_default_file;
static char *cli_plugins;
static char *cli_connectivity_uri;
static int cli_connectivity_interval = -1;
static char *cli_connectivity_response;
static GOptionEntry config_options[] = {
{ "config", 0, 0, G_OPTION_ARG_FILENAME, &cli_config_path, N_("Config file location"), N_("/path/to/config.file") },
{ "config-dir", 0, 0, G_OPTION_ARG_FILENAME, &cli_config_dir, N_("Config directory location"), N_("/path/to/config/dir") },
{ "no-auto-default", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_FILENAME, &cli_no_auto_default_file, "no-auto-default.state location", NULL },
{ "plugins", 0, 0, G_OPTION_ARG_STRING, &cli_plugins, N_("List of plugins separated by ','"), N_("plugin1,plugin2") },
/* These three are hidden for now, and should eventually just go away. */
{ "connectivity-uri", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &cli_connectivity_uri, N_("An http(s) address for checking internet connectivity"), "http://example.com" },
{ "connectivity-interval", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_INT, &cli_connectivity_interval, N_("The interval between connectivity checks (in seconds)"), "60" },
{ "connectivity-response", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &cli_connectivity_response, N_("The expected start of the response"), N_("Bingo!") },
{NULL}
};
GOptionEntry *
nm_config_get_options (void)
static void
_nm_config_cmd_line_options_clear (NMConfigCmdLineOptions *cli)
{
return config_options;
g_clear_pointer (&cli->config_main_file, g_free);
g_clear_pointer (&cli->config_dir, g_free);
g_clear_pointer (&cli->no_auto_default_file, g_free);
g_clear_pointer (&cli->plugins, g_free);
g_clear_pointer (&cli->connectivity_uri, g_free);
g_clear_pointer (&cli->connectivity_response, g_free);
cli->connectivity_interval = -1;
}
static void
_nm_config_cmd_line_options_copy (const NMConfigCmdLineOptions *cli, NMConfigCmdLineOptions *dst)
{
g_return_if_fail (cli);
g_return_if_fail (dst);
g_return_if_fail (cli != dst);
_nm_config_cmd_line_options_clear (dst);
dst->config_dir = g_strdup (cli->config_dir);
dst->config_main_file = g_strdup (cli->config_main_file);
dst->no_auto_default_file = g_strdup (cli->no_auto_default_file);
dst->plugins = g_strdup (cli->plugins);
dst->connectivity_uri = g_strdup (cli->connectivity_uri);
dst->connectivity_response = g_strdup (cli->connectivity_response);
dst->connectivity_interval = cli->connectivity_interval;
}
NMConfigCmdLineOptions *
nm_config_cmd_line_options_new ()
{
NMConfigCmdLineOptions *cli = g_new0 (NMConfigCmdLineOptions, 1);
_nm_config_cmd_line_options_clear (cli);
return cli;
}
void
nm_config_cmd_line_options_free (NMConfigCmdLineOptions *cli)
{
g_return_if_fail (cli);
_nm_config_cmd_line_options_clear (cli);
g_free (cli);
}
void
nm_config_cmd_line_options_add_to_entries (NMConfigCmdLineOptions *cli,
GOptionContext *opt_ctx)
{
g_return_if_fail (opt_ctx);
g_return_if_fail (cli);
{
GOptionEntry config_options[] = {
{ "config", 0, 0, G_OPTION_ARG_FILENAME, &cli->config_main_file, N_("Config file location"), N_("/path/to/config.file") },
{ "config-dir", 0, 0, G_OPTION_ARG_FILENAME, &cli->config_dir, N_("Config directory location"), N_("/path/to/config/dir") },
{ "no-auto-default", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_FILENAME, &cli->no_auto_default_file, "no-auto-default.state location", NULL },
{ "plugins", 0, 0, G_OPTION_ARG_STRING, &cli->plugins, N_("List of plugins separated by ','"), N_("plugin1,plugin2") },
/* These three are hidden for now, and should eventually just go away. */
{ "connectivity-uri", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &cli->connectivity_uri, N_("An http(s) address for checking internet connectivity"), "http://example.com" },
{ "connectivity-interval", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_INT, &cli->connectivity_interval, N_("The interval between connectivity checks (in seconds)"), "60" },
{ "connectivity-response", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &cli->connectivity_response, N_("The expected start of the response"), N_("Bingo!") },
{ 0 },
};
g_option_context_add_main_entries (opt_ctx, config_options, NULL);
}
}
/************************************************************************/
GKeyFile *
nm_config_create_keyfile ()
{
GKeyFile *keyfile;
keyfile = g_key_file_new ();
g_key_file_set_list_separator (keyfile, ',');
return keyfile;
}
static gboolean
read_config (NMConfig *config, const char *path, GError **error)
read_config (GKeyFile *keyfile, const char *path, GError **error)
{
NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (config);
GKeyFile *kf;
char **groups, **keys;
gsize ngroups, nkeys;
int g, k;
g_return_val_if_fail (keyfile, FALSE);
g_return_val_if_fail (path, FALSE);
g_return_val_if_fail (!error || !*error, 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 %s not found", path);
return FALSE;
@@ -388,8 +453,7 @@ read_config (NMConfig *config, const char *path, GError **error)
nm_log_dbg (LOGD_SETTINGS, "Reading config file '%s'", path);
kf = g_key_file_new ();
g_key_file_set_list_separator (kf, ',');
kf = nm_config_create_keyfile ();
if (!g_key_file_load_from_file (kf, path, G_KEY_FILE_NONE, error)) {
g_key_file_free (kf);
return FALSE;
@@ -407,22 +471,22 @@ read_config (NMConfig *config, const char *path, GError **error)
if (keys[k][len - 1] == '+') {
char *base_key = g_strndup (keys[k], len - 1);
const char *old_val = g_key_file_get_value (priv->keyfile, groups[g], base_key, NULL);
const char *old_val = g_key_file_get_value (keyfile, groups[g], base_key, NULL);
const char *new_val = g_key_file_get_value (kf, groups[g], keys[k], NULL);
if (old_val && *old_val) {
char *combined = g_strconcat (old_val, ",", new_val, NULL);
g_key_file_set_value (priv->keyfile, groups[g], base_key, combined);
g_key_file_set_value (keyfile, groups[g], base_key, combined);
g_free (combined);
} else
g_key_file_set_value (priv->keyfile, groups[g], base_key, new_val);
g_key_file_set_value (keyfile, groups[g], base_key, new_val);
g_free (base_key);
continue;
}
g_key_file_set_value (priv->keyfile, groups[g], keys[k],
g_key_file_set_value (keyfile, groups[g], keys[k],
v = g_key_file_get_value (kf, groups[g], keys[k], NULL));
g_free (v);
}
@@ -435,16 +499,22 @@ read_config (NMConfig *config, const char *path, GError **error)
}
static gboolean
find_base_config (NMConfig *config, GError **error)
read_base_config (GKeyFile *keyfile,
const char *cli_config_main_file,
char **out_config_main_file,
GError **error)
{
NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (config);
GError *my_error = NULL;
g_return_val_if_fail (keyfile, FALSE);
g_return_val_if_fail (out_config_main_file && !*out_config_main_file, FALSE);
g_return_val_if_fail (!error || !*error, FALSE);
/* Try a user-specified config file first */
if (cli_config_path) {
if (cli_config_main_file) {
/* Bad user-specific config file path is a hard error */
if (read_config (config, cli_config_path, error)) {
priv->nm_conf_path = g_strdup (cli_config_path);
if (read_config (keyfile, cli_config_main_file, error)) {
*out_config_main_file = g_strdup (cli_config_main_file);
return TRUE;
} else
return FALSE;
@@ -458,8 +528,8 @@ find_base_config (NMConfig *config, GError **error)
*/
/* Try deprecated nm-system-settings.conf first */
if (read_config (config, NM_OLD_SYSTEM_CONF_FILE, &my_error)) {
priv->nm_conf_path = g_strdup (NM_OLD_SYSTEM_CONF_FILE);
if (read_config (keyfile, NM_OLD_SYSTEM_CONF_FILE, &my_error)) {
*out_config_main_file = g_strdup (NM_OLD_SYSTEM_CONF_FILE);
return TRUE;
}
@@ -471,8 +541,8 @@ find_base_config (NMConfig *config, GError **error)
g_clear_error (&my_error);
/* Try the standard config file location next */
if (read_config (config, NM_DEFAULT_SYSTEM_CONF_FILE, &my_error)) {
priv->nm_conf_path = g_strdup (NM_DEFAULT_SYSTEM_CONF_FILE);
if (read_config (keyfile, NM_DEFAULT_SYSTEM_CONF_FILE, &my_error)) {
*out_config_main_file = g_strdup (NM_DEFAULT_SYSTEM_CONF_FILE);
return TRUE;
}
@@ -488,21 +558,12 @@ find_base_config (NMConfig *config, GError **error)
/* If for some reason no config file exists, use the default
* config file path.
*/
priv->nm_conf_path = g_strdup (NM_DEFAULT_SYSTEM_CONF_FILE);
*out_config_main_file = g_strdup (NM_DEFAULT_SYSTEM_CONF_FILE);
nm_log_info (LOGD_CORE, "No config file found or given; using %s\n",
NM_DEFAULT_SYSTEM_CONF_FILE);
return TRUE;
}
/************************************************************************/
NMConfig *
nm_config_get (void)
{
g_assert (singleton);
return singleton;
}
static int
sort_asciibetically (gconstpointer a, gconstpointer b)
{
@@ -512,45 +573,31 @@ sort_asciibetically (gconstpointer a, gconstpointer b)
return strcmp (s1, s2);
}
/* call this function only once! */
NMConfig *
nm_config_new (GError **error)
static GPtrArray *
_get_config_dir_files (const char *config_main_file,
const char *config_dir,
char **out_config_description)
{
NMConfigPrivate *priv = NULL;
GFile *dir;
GFileEnumerator *direnum;
GFileInfo *info;
GPtrArray *confs;
const char *name;
int i;
GString *config_description;
const char *name;
g_assert (!singleton);
singleton = NM_CONFIG (g_object_new (NM_TYPE_CONFIG, NULL));
priv = NM_CONFIG_GET_PRIVATE (singleton);
/* First read the base config file */
if (!find_base_config (singleton, error)) {
g_object_unref (singleton);
singleton = NULL;
return NULL;
}
/* Now read the overrides in the config dir */
if (cli_config_dir)
priv->config_dir = g_strdup (cli_config_dir);
else
priv->config_dir = g_strdup (NM_DEFAULT_SYSTEM_CONF_DIR);
g_return_val_if_fail (config_main_file, NULL);
g_return_val_if_fail (config_dir, NULL);
g_return_val_if_fail (out_config_description && !*out_config_description, NULL);
confs = g_ptr_array_new_with_free_func (g_free);
config_description = g_string_new (priv->nm_conf_path);
dir = g_file_new_for_path (priv->config_dir);
config_description = g_string_new (config_main_file);
dir = g_file_new_for_path (config_dir);
direnum = g_file_enumerate_children (dir, G_FILE_ATTRIBUTE_STANDARD_NAME, 0, NULL, NULL);
if (direnum) {
while ((info = g_file_enumerator_next_file (direnum, NULL, NULL))) {
name = g_file_info_get_name (info);
if (g_str_has_suffix (name, ".conf")) {
g_ptr_array_add (confs, g_build_filename (priv->config_dir, name, NULL));
g_ptr_array_add (confs, g_build_filename (config_dir, name, NULL));
if (confs->len == 1)
g_string_append (config_description, " and conf.d: ");
else
@@ -564,62 +611,273 @@ nm_config_new (GError **error)
g_object_unref (dir);
g_ptr_array_sort (confs, sort_asciibetically);
priv->config_description = g_string_free (config_description, FALSE);
*out_config_description = g_string_free (config_description, FALSE);
return confs;
}
static GKeyFile *
read_entire_config (const NMConfigCmdLineOptions *cli,
const char *config_dir,
char **out_config_main_file,
char **out_config_description,
GError **error)
{
GKeyFile *keyfile = nm_config_create_keyfile ();
GPtrArray *confs;
guint i;
char *o_config_main_file = NULL;
char *o_config_description = NULL;
char **plugins_tmp;
g_return_val_if_fail (config_dir, NULL);
g_return_val_if_fail (out_config_main_file && !*out_config_main_file, FALSE);
g_return_val_if_fail (out_config_description && !*out_config_description, NULL);
g_return_val_if_fail (!error || !*error, FALSE);
/* First read the base config file */
if ( cli
&& !read_base_config (keyfile, cli->config_main_file, &o_config_main_file, error)) {
g_key_file_free (keyfile);
return NULL;
}
g_assert (o_config_main_file);
confs = _get_config_dir_files (o_config_main_file, config_dir, &o_config_description);
for (i = 0; i < confs->len; i++) {
if (!read_config (singleton, confs->pdata[i], error)) {
g_object_unref (singleton);
singleton = NULL;
break;
if (!read_config (keyfile, confs->pdata[i], error)) {
g_key_file_free (keyfile);
g_free (o_config_main_file);
g_free (o_config_description);
g_ptr_array_unref (confs);
return NULL;
}
}
g_ptr_array_unref (confs);
if (!singleton)
/* Merge settings from command line. They overwrite everything read from
* config files. */
if (cli && cli->plugins && cli->plugins[0])
g_key_file_set_value (keyfile, "main", "plugins", cli->plugins);
plugins_tmp = g_key_file_get_string_list (keyfile, "main", "plugins", NULL, NULL);
if (!plugins_tmp) {
if (STRLEN (CONFIG_PLUGINS_DEFAULT) > 0)
g_key_file_set_value (keyfile, "main", "plugins", CONFIG_PLUGINS_DEFAULT);
} else
g_strfreev (plugins_tmp);
if (cli && cli->connectivity_uri && cli->connectivity_uri[0])
g_key_file_set_value (keyfile, "connectivity", "uri", cli->connectivity_uri);
if (cli && cli->connectivity_interval >= 0)
g_key_file_set_integer (keyfile, "connectivity", "interval", cli->connectivity_interval);
if (cli && cli->connectivity_response && cli->connectivity_response[0])
g_key_file_set_value (keyfile, "connectivity", "response", cli->connectivity_response);
*out_config_main_file = o_config_main_file;
*out_config_description = o_config_description;
return keyfile;
}
/************************************************************************/
void
nm_config_reload (NMConfig *self)
{
NMConfigPrivate *priv;
GError *error = NULL;
GKeyFile *keyfile;
NMConfigData *new_data = NULL;
char *config_main_file = NULL;
char *config_description = NULL;
g_return_if_fail (NM_IS_CONFIG (self));
priv = NM_CONFIG_GET_PRIVATE (self);
/* pass on the original command line options. This means, that
* options specified at command line cannot ever be reloaded from
* file. That seems desirable.
*/
keyfile = read_entire_config (&priv->cli,
priv->config_dir,
&config_main_file,
&config_description,
&error);
if (!keyfile) {
nm_log_err (LOGD_CORE, "Failed to reload the configuration: %s", error->message);
g_clear_error (&error);
return;
}
new_data = nm_config_data_new (config_main_file, config_description, nm_config_data_get_no_auto_default (priv->config_data), keyfile);
g_free (config_main_file);
g_free (config_description);
g_key_file_unref (keyfile);
_set_config_data (self, new_data);
}
static const char *
_change_flags_one_to_string (NMConfigChangeFlags flag)
{
switch (flag) {
case NM_CONFIG_CHANGE_CONFIG_FILES:
return "config-files";
case NM_CONFIG_CHANGE_VALUES:
return "values";
case NM_CONFIG_CHANGE_CONNECTIVITY:
return "connectivity";
case NM_CONFIG_CHANGE_NO_AUTO_DEFAULT:
return "no-auto-default";
default:
g_return_val_if_reached ("unknown");
}
}
char *
nm_config_change_flags_to_string (NMConfigChangeFlags flags)
{
GString *str = g_string_new ("");
NMConfigChangeFlags s = 0x01;
while (flags) {
if (NM_FLAGS_HAS (flags, s)) {
if (str->len)
g_string_append_c (str, ',');
g_string_append (str, _change_flags_one_to_string (s));
}
flags = flags & ~s;
s <<= 1;
}
return g_string_free (str, FALSE);
}
static void
_set_config_data (NMConfig *self, NMConfigData *new_data)
{
NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (self);
NMConfigData *old_data = priv->config_data;
NMConfigChangeFlags changes;
gs_free char *log_str = NULL;
changes = nm_config_data_diff (old_data, new_data);
if (changes == NM_CONFIG_CHANGE_NONE) {
g_object_unref (new_data);
return;
}
nm_log_info (LOGD_CORE, "config: update %s (%s)", nm_config_data_get_config_description (new_data),
(log_str = nm_config_change_flags_to_string (changes)));
priv->config_data = new_data;
g_signal_emit (self, signals[SIGNAL_CONFIG_CHANGED], 0, new_data, changes, old_data);
g_object_unref (old_data);
}
NM_DEFINE_SINGLETON_DESTRUCTOR (NMConfig);
NM_DEFINE_SINGLETON_WEAK_REF (NMConfig);
NMConfig *
nm_config_get (void)
{
g_assert (singleton_instance);
return singleton_instance;
}
NMConfig *
nm_config_setup (const NMConfigCmdLineOptions *cli, GError **error)
{
g_assert (!singleton_instance);
singleton_instance = nm_config_new (cli, error);
if (singleton_instance)
nm_singleton_instance_weak_ref_register ();
return singleton_instance;
}
static gboolean
init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
{
NMConfig *self = NM_CONFIG (initable);
NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (self);
GKeyFile *keyfile;
char *config_main_file = NULL;
char *config_description = NULL;
char **no_auto_default;
char **no_auto_default_orig;
if (priv->config_dir) {
/* Object is already initialized. */
if (priv->config_data)
return TRUE;
g_set_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND, "unspecified error");
return FALSE;
}
if (priv->cli.config_dir)
priv->config_dir = g_strdup (priv->cli.config_dir);
else
priv->config_dir = g_strdup (NM_DEFAULT_SYSTEM_CONF_DIR);
keyfile = read_entire_config (&priv->cli,
priv->config_dir,
&config_main_file,
&config_description,
error);
if (!keyfile)
return FALSE;
/* Handle no-auto-default key and state file */
priv->no_auto_default = g_key_file_get_string_list (priv->keyfile, "main", "no-auto-default", NULL, NULL);
if (cli_no_auto_default_file)
priv->no_auto_default_file = g_strdup (cli_no_auto_default_file);
/* Initialize read only private members */
if (priv->cli.no_auto_default_file)
priv->no_auto_default_file = g_strdup (priv->cli.no_auto_default_file);
else
priv->no_auto_default_file = g_strdup (NM_NO_AUTO_DEFAULT_STATE_FILE);
merge_no_auto_default_state (singleton);
/* Now let command-line options override the config files, and fill in priv. */
if (cli_plugins && cli_plugins[0])
g_key_file_set_value (priv->keyfile, "main", "plugins", cli_plugins);
priv->plugins = g_key_file_get_string_list (priv->keyfile, "main", "plugins", NULL, NULL);
if (!priv->plugins && STRLEN (CONFIG_PLUGINS_DEFAULT) > 0)
priv->plugins = g_strsplit (CONFIG_PLUGINS_DEFAULT, ",", -1);
priv->plugins = g_key_file_get_string_list (keyfile, "main", "plugins", NULL, NULL);
if (!priv->plugins)
priv->plugins = g_new0 (char *, 1);
priv->monitor_connection_files = _get_bool_value (priv->keyfile, "main", "monitor-connection-files", FALSE);
priv->monitor_connection_files = _get_bool_value (keyfile, "main", "monitor-connection-files", FALSE);
priv->auth_polkit = _get_bool_value (priv->keyfile, "main", "auth-polkit", NM_CONFIG_DEFAULT_AUTH_POLKIT);
priv->auth_polkit = _get_bool_value (keyfile, "main", "auth-polkit", NM_CONFIG_DEFAULT_AUTH_POLKIT);
priv->dhcp_client = g_key_file_get_value (priv->keyfile, "main", "dhcp", NULL);
priv->dns_mode = g_key_file_get_value (priv->keyfile, "main", "dns", NULL);
priv->dhcp_client = g_key_file_get_value (keyfile, "main", "dhcp", NULL);
priv->dns_mode = g_key_file_get_value (keyfile, "main", "dns", NULL);
priv->log_level = g_key_file_get_value (priv->keyfile, "logging", "level", NULL);
priv->log_domains = g_key_file_get_value (priv->keyfile, "logging", "domains", NULL);
priv->log_level = g_key_file_get_value (keyfile, "logging", "level", NULL);
priv->log_domains = g_key_file_get_value (keyfile, "logging", "domains", NULL);
priv->debug = g_key_file_get_value (priv->keyfile, "main", "debug", NULL);
priv->debug = g_key_file_get_value (keyfile, "main", "debug", NULL);
if (cli_connectivity_uri && cli_connectivity_uri[0])
g_key_file_set_value (priv->keyfile, "connectivity", "uri", cli_connectivity_uri);
priv->connectivity_uri = g_key_file_get_value (priv->keyfile, "connectivity", "uri", NULL);
priv->ignore_carrier = g_key_file_get_string_list (keyfile, "main", "ignore-carrier", NULL, NULL);
if (cli_connectivity_interval >= 0)
g_key_file_set_integer (priv->keyfile, "connectivity", "interval", cli_connectivity_interval);
priv->connectivity_interval = g_key_file_get_integer (priv->keyfile, "connectivity", "interval", NULL);
priv->configure_and_quit = _get_bool_value (keyfile, "main", "configure-and-quit", FALSE);
if (cli_connectivity_response && cli_connectivity_response[0])
g_key_file_set_value (priv->keyfile, "connectivity", "response", cli_connectivity_response);
priv->connectivity_response = g_key_file_get_value (priv->keyfile, "connectivity", "response", NULL);
no_auto_default_orig = g_key_file_get_string_list (keyfile, "main", "no-auto-default", NULL, NULL);
no_auto_default = no_auto_default_merge_from_file (priv->no_auto_default_file, (const char *const *) no_auto_default_orig);
priv->ignore_carrier = g_key_file_get_string_list (priv->keyfile, "main", "ignore-carrier", NULL, NULL);
priv->config_data_orig = nm_config_data_new (config_main_file, config_description, (const char *const*) no_auto_default, keyfile);
priv->configure_and_quit = _get_bool_value (priv->keyfile, "main", "configure-and-quit", FALSE);
g_strfreev (no_auto_default);
g_strfreev (no_auto_default_orig);
return singleton;
priv->config_data = g_object_ref (priv->config_data_orig);
g_free (config_main_file);
g_free (config_description);
g_key_file_unref (keyfile);
return TRUE;
}
NMConfig *
nm_config_new (const NMConfigCmdLineOptions *cli, GError **error)
{
return NM_CONFIG (g_initable_new (NM_TYPE_CONFIG,
NULL,
error,
NM_CONFIG_CMD_LINE_OPTIONS, cli,
NULL));
}
static void
@@ -628,11 +886,6 @@ nm_config_init (NMConfig *config)
NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (config);
priv->auth_polkit = NM_CONFIG_DEFAULT_AUTH_POLKIT;
priv->keyfile = g_key_file_new ();
g_key_file_set_list_separator (priv->keyfile, ',');
priv->connectivity_interval = -1;
}
static void
@@ -640,34 +893,46 @@ finalize (GObject *gobject)
{
NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (gobject);
g_free (priv->nm_conf_path);
g_free (priv->config_dir);
g_free (priv->config_description);
g_free (priv->no_auto_default_file);
g_clear_pointer (&priv->keyfile, g_key_file_unref);
g_strfreev (priv->plugins);
g_free (priv->dhcp_client);
g_free (priv->dns_mode);
g_free (priv->log_level);
g_free (priv->log_domains);
g_free (priv->debug);
g_free (priv->connectivity_uri);
g_free (priv->connectivity_response);
g_strfreev (priv->no_auto_default);
g_strfreev (priv->ignore_carrier);
singleton = NULL;
_nm_config_cmd_line_options_clear (&priv->cli);
g_clear_pointer (&cli_config_path, g_free);
g_clear_pointer (&cli_config_dir, g_free);
g_clear_pointer (&cli_no_auto_default_file, g_free);
g_clear_pointer (&cli_plugins, g_free);
g_clear_pointer (&cli_connectivity_uri, g_free);
g_clear_pointer (&cli_connectivity_response, g_free);
g_clear_object (&priv->config_data);
g_clear_object (&priv->config_data_orig);
G_OBJECT_CLASS (nm_config_parent_class)->finalize (gobject);
}
static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
NMConfig *self = NM_CONFIG (object);
NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (self);
NMConfigCmdLineOptions *cli;
switch (prop_id) {
case PROP_CMD_LINE_OPTIONS:
/* construct only */
cli = g_value_get_pointer (value);
if (!cli)
_nm_config_cmd_line_options_clear (&priv->cli);
else
_nm_config_cmd_line_options_copy (cli, &priv->cli);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
nm_config_class_init (NMConfigClass *config_class)
@@ -676,5 +941,27 @@ nm_config_class_init (NMConfigClass *config_class)
g_type_class_add_private (config_class, sizeof (NMConfigPrivate));
object_class->finalize = finalize;
object_class->set_property = set_property;
g_object_class_install_property
(object_class, PROP_CMD_LINE_OPTIONS,
g_param_spec_pointer (NM_CONFIG_CMD_LINE_OPTIONS, "", "",
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
signals[SIGNAL_CONFIG_CHANGED] =
g_signal_new (NM_CONFIG_SIGNAL_CONFIG_CHANGED,
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMConfigClass, config_changed),
NULL, NULL, NULL,
G_TYPE_NONE, 3, NM_TYPE_CONFIG_DATA, NM_TYPE_CONFIG_CHANGE_FLAGS, NM_TYPE_CONFIG_DATA);
}
static void
nm_config_initable_iface_init (GInitableIface *iface)
{
iface->init = init_sync;
}

View File

@@ -26,6 +26,7 @@
#include <glib-object.h>
#include "nm-types.h"
#include "nm-config-data.h"
G_BEGIN_DECLS
@@ -36,20 +37,33 @@ G_BEGIN_DECLS
#define NM_IS_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_CONFIG))
#define NM_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_CONFIG, NMConfigClass))
typedef struct {
/* Properties */
#define NM_CONFIG_CMD_LINE_OPTIONS "cmd-line-options"
/* Signals */
#define NM_CONFIG_SIGNAL_CONFIG_CHANGED "config-changed"
typedef struct NMConfigCmdLineOptions NMConfigCmdLineOptions;
struct _NMConfig {
GObject parent;
} NMConfig;
};
typedef struct {
GObjectClass parent;
/* Signals */
void (*config_changed) (NMConfig *config, GHashTable *changes, NMConfigData *old_data);
} NMConfigClass;
GType nm_config_get_type (void);
NMConfig *nm_config_get (void);
const char *nm_config_get_path (NMConfig *config);
const char *nm_config_get_description (NMConfig *config);
char *nm_config_change_flags_to_string (NMConfigChangeFlags flags);
NMConfigData *nm_config_get_data (NMConfig *config);
NMConfigData *nm_config_get_data_orig (NMConfig *config);
const char **nm_config_get_plugins (NMConfig *config);
gboolean nm_config_get_monitor_connection_files (NMConfig *config);
gboolean nm_config_get_auth_polkit (NMConfig *config);
@@ -58,21 +72,24 @@ const char *nm_config_get_dns_mode (NMConfig *config);
const char *nm_config_get_log_level (NMConfig *config);
const char *nm_config_get_log_domains (NMConfig *config);
const char *nm_config_get_debug (NMConfig *config);
const char *nm_config_get_connectivity_uri (NMConfig *config);
guint nm_config_get_connectivity_interval (NMConfig *config);
const char *nm_config_get_connectivity_response (NMConfig *config);
gboolean nm_config_get_configure_and_quit (NMConfig *config);
gboolean nm_config_get_ethernet_can_auto_default (NMConfig *config, NMDevice *device);
void nm_config_set_ethernet_no_auto_default (NMConfig *config, NMDevice *device);
gboolean nm_config_get_ignore_carrier (NMConfig *config, NMDevice *device);
char *nm_config_get_value (NMConfig *config, const char *group, const char *key, GError **error);
/* for main.c only */
GOptionEntry *nm_config_get_options (void);
NMConfig *nm_config_new (GError **error);
NMConfigCmdLineOptions *nm_config_cmd_line_options_new (void);
void nm_config_cmd_line_options_free (NMConfigCmdLineOptions *cli);
void nm_config_cmd_line_options_add_to_entries (NMConfigCmdLineOptions *cli,
GOptionContext *opt_ctx);
gboolean nm_config_get_no_auto_default_for_device (NMConfig *config, NMDevice *device);
void nm_config_set_no_auto_default_for_device (NMConfig *config, NMDevice *device);
NMConfig *nm_config_new (const NMConfigCmdLineOptions *cli, GError **error);
NMConfig *nm_config_setup (const NMConfigCmdLineOptions *cli, GError **error);
void nm_config_reload (NMConfig *config);
GKeyFile *nm_config_create_keyfile (void);
G_END_DECLS

View File

@@ -28,7 +28,6 @@
#include "nm-connectivity.h"
#include "nm-logging.h"
#include "nm-config.h"
G_DEFINE_TYPE (NMConnectivity, nm_connectivity, G_TYPE_OBJECT)
@@ -37,14 +36,32 @@ G_DEFINE_TYPE (NMConnectivity, nm_connectivity, G_TYPE_OBJECT)
#define DEFAULT_RESPONSE "NetworkManager is online" /* NOT LOCALIZED */
#define _LOG_DEFAULT_DOMAIN LOGD_CONCHECK
#define _LOG(level, domain, ...) \
G_STMT_START { \
nm_log ((level), (domain), \
"%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
"connectivity: " \
_NM_UTILS_MACRO_REST(__VA_ARGS__)); \
} G_STMT_END
#define _LOGT(...) _LOG (LOGL_TRACE, _LOG_DEFAULT_DOMAIN, __VA_ARGS__)
#define _LOGD(...) _LOG (LOGL_DEBUG, _LOG_DEFAULT_DOMAIN, __VA_ARGS__)
#define _LOGI(...) _LOG (LOGL_INFO, _LOG_DEFAULT_DOMAIN, __VA_ARGS__)
#define _LOGW(...) _LOG (LOGL_WARN, _LOG_DEFAULT_DOMAIN, __VA_ARGS__)
#define _LOGE(...) _LOG (LOGL_ERR, _LOG_DEFAULT_DOMAIN, __VA_ARGS__)
typedef struct {
char *uri;
char *response;
guint interval;
gboolean online; /* whether periodic connectivity checking is enabled. */
#if WITH_CONCHECK
SoupSession *soup_session;
guint pending_checks;
gboolean initial_check_obsoleted;
guint check_id;
#endif
@@ -69,8 +86,8 @@ nm_connectivity_get_state (NMConnectivity *connectivity)
return NM_CONNECTIVITY_GET_PRIVATE (connectivity)->state;
}
static const char *
state_name (NMConnectivityState state)
const char *
nm_connectivity_state_to_string (NMConnectivityState state)
{
switch (state) {
case NM_CONNECTIVITY_UNKNOWN:
@@ -84,7 +101,7 @@ state_name (NMConnectivityState state)
case NM_CONNECTIVITY_FULL:
return "FULL";
default:
return "???";
g_return_val_if_reached ("???");
}
}
@@ -94,31 +111,41 @@ update_state (NMConnectivity *self, NMConnectivityState state)
NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self);
if (priv->state != state) {
nm_log_dbg (LOGD_CONCHECK, "Connectivity state changed from %s to %s",
state_name (priv->state), state_name (state));
_LOGD ("state changed from %s to %s",
nm_connectivity_state_to_string (priv->state),
nm_connectivity_state_to_string (state));
priv->state = state;
g_object_notify (G_OBJECT (self), NM_CONNECTIVITY_STATE);
}
}
#if WITH_CONCHECK
typedef struct {
GSimpleAsyncResult *simple;
char *uri;
char *response;
guint check_id_when_scheduled;
} ConCheckCbData;
static void
nm_connectivity_check_cb (SoupSession *session, SoupMessage *msg, gpointer user_data)
{
GSimpleAsyncResult *simple = user_data;
NMConnectivity *self;
NMConnectivityPrivate *priv;
ConCheckCbData *cb_data = user_data;
GSimpleAsyncResult *simple = cb_data->simple;
NMConnectivityState new_state;
const char *nm_header;
const char *uri = cb_data->uri;
const char *response = cb_data->response ? cb_data->response : DEFAULT_RESPONSE;
self = NM_CONNECTIVITY (g_async_result_get_source_object (G_ASYNC_RESULT (simple)));
/* it is safe to unref @self here, @simple holds yet another reference. */
g_object_unref (self);
priv = NM_CONNECTIVITY_GET_PRIVATE (self);
priv->pending_checks--;
if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)) {
nm_log_info (LOGD_CONCHECK, "Connectivity check for uri '%s' failed with '%s'.",
priv->uri, msg->reason_phrase);
_LOGI ("check for uri '%s' failed with '%s'", uri, msg->reason_phrase);
new_state = NM_CONNECTIVITY_LIMITED;
goto done;
}
@@ -126,32 +153,47 @@ nm_connectivity_check_cb (SoupSession *session, SoupMessage *msg, gpointer user_
/* Check headers; if we find the NM-specific one we're done */
nm_header = soup_message_headers_get_one (msg->response_headers, "X-NetworkManager-Status");
if (g_strcmp0 (nm_header, "online") == 0) {
nm_log_dbg (LOGD_CONCHECK, "Connectivity check for uri '%s' with Status header successful.", priv->uri);
_LOGD ("check for uri '%s' with Status header successful.", uri);
new_state = NM_CONNECTIVITY_FULL;
} else if (msg->status_code == SOUP_STATUS_OK) {
/* check response */
if (msg->response_body->data && (g_str_has_prefix (msg->response_body->data, priv->response))) {
nm_log_dbg (LOGD_CONCHECK, "Connectivity check for uri '%s' successful.",
priv->uri);
if (msg->response_body->data && g_str_has_prefix (msg->response_body->data, response)) {
_LOGD ("check for uri '%s' successful.", uri);
new_state = NM_CONNECTIVITY_FULL;
} else {
nm_log_info (LOGD_CONCHECK, "Connectivity check for uri '%s' did not match expected response '%s'; assuming captive portal.",
priv->uri, priv->response);
_LOGI ("check for uri '%s' did not match expected response '%s'; assuming captive portal.",
uri, response);
new_state = NM_CONNECTIVITY_PORTAL;
}
} else {
nm_log_info (LOGD_CONCHECK, "Connectivity check for uri '%s' returned status '%d %s'; assuming captive portal.",
priv->uri, msg->status_code, msg->reason_phrase);
_LOGI ("check for uri '%s' returned status '%d %s'; assuming captive portal.",
uri, msg->status_code, msg->reason_phrase);
new_state = NM_CONNECTIVITY_PORTAL;
}
done:
update_state (self, new_state);
/* Only update the state, if the call was done from external, or if the periodic check
* is still the one that called this async check. */
if (!cb_data->check_id_when_scheduled || cb_data->check_id_when_scheduled == priv->check_id) {
/* Only update the state, if the URI and response parameters did not change
* since invocation.
* The interval does not matter for exernal calls, and for internal calls
* we don't reach this line if the interval changed. */
if ( !g_strcmp0 (cb_data->uri, priv->uri)
&& !g_strcmp0 (cb_data->response, priv->response))
update_state (self, new_state);
}
g_simple_async_result_set_op_res_gssize (simple, new_state);
g_simple_async_result_complete (simple);
g_free (cb_data->uri);
g_free (cb_data->response);
g_slice_free (ConCheckCbData, cb_data);
}
#define IS_PERIODIC_CHECK(callback) (callback == run_check_complete)
static void
run_check_complete (GObject *object,
GAsyncResult *result,
@@ -162,7 +204,7 @@ run_check_complete (GObject *object,
nm_connectivity_check_finish (self, result, &error);
if (error) {
nm_log_err (LOGD_CONCHECK, "Connectivity check failed: %s", error->message);
_LOGE ("check failed: %s", error->message);
g_error_free (error);
}
}
@@ -183,39 +225,54 @@ idle_start_periodic_checks (gpointer user_data)
NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self);
priv->check_id = g_timeout_add_seconds (priv->interval, run_check, self);
if (!priv->pending_checks)
if (!priv->initial_check_obsoleted)
run_check (self);
return FALSE;
}
#endif
void
nm_connectivity_set_online (NMConnectivity *self,
gboolean online)
static void
_reschedule_periodic_checks (NMConnectivity *self, gboolean force_reschedule)
{
#if WITH_CONCHECK
NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self);
#endif
nm_log_dbg (LOGD_CONCHECK, "nm_connectivity_set_online(%s)", online ? "TRUE" : "FALSE");
#if WITH_CONCHECK
if (online && priv->uri && priv->interval) {
if (!priv->check_id)
if (priv->online && priv->uri && priv->interval) {
if (force_reschedule || !priv->check_id) {
if (priv->check_id)
g_source_remove (priv->check_id);
priv->check_id = g_timeout_add (0, idle_start_periodic_checks, self);
return;
} else if (priv->check_id) {
g_source_remove (priv->check_id);
priv->check_id = 0;
priv->initial_check_obsoleted = FALSE;
}
} else {
if (priv->check_id) {
g_source_remove (priv->check_id);
priv->check_id = 0;
}
}
if (priv->check_id)
return;
#endif
/* Either @online is %TRUE but we aren't checking connectivity, or
* @online is %FALSE. Either way we can update our status immediately.
*/
update_state (self, online ? NM_CONNECTIVITY_FULL : NM_CONNECTIVITY_NONE);
update_state (self, priv->online ? NM_CONNECTIVITY_FULL : NM_CONNECTIVITY_NONE);
}
void
nm_connectivity_set_online (NMConnectivity *self,
gboolean online)
{
NMConnectivityPrivate *priv= NM_CONNECTIVITY_GET_PRIVATE (self);
online = !!online;
if (priv->online != online) {
_LOGD ("set %s", online ? "online" : "offline");
priv->online = online;
_reschedule_periodic_checks (self, FALSE);
}
}
void
@@ -224,36 +281,42 @@ nm_connectivity_check_async (NMConnectivity *self,
gpointer user_data)
{
NMConnectivityPrivate *priv;
#if WITH_CONCHECK
SoupMessage *msg;
#endif
GSimpleAsyncResult *simple;
g_return_if_fail (NM_IS_CONNECTIVITY (self));
priv = NM_CONNECTIVITY_GET_PRIVATE (self);
#if WITH_CONCHECK
if (callback == run_check_complete)
nm_log_dbg (LOGD_CONCHECK, "Periodic connectivity check started with uri '%s'.", priv->uri);
else
#endif
nm_log_dbg (LOGD_CONCHECK, "Connectivity check started with uri '%s'.", priv->uri);
simple = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
nm_connectivity_check_async);
#if WITH_CONCHECK
if (priv->uri && priv->interval) {
SoupMessage *msg;
ConCheckCbData *cb_data = g_slice_new (ConCheckCbData);
msg = soup_message_new ("GET", priv->uri);
soup_message_set_flags (msg, SOUP_MESSAGE_NO_REDIRECT);
cb_data->simple = simple;
cb_data->uri = g_strdup (priv->uri);
cb_data->response = g_strdup (priv->response);
/* For internal calls (periodic), remember the check-id at time of scheduling. */
cb_data->check_id_when_scheduled = IS_PERIODIC_CHECK (callback) ? priv->check_id : 0;
soup_session_queue_message (priv->soup_session,
msg,
nm_connectivity_check_cb,
simple);
priv->pending_checks++;
cb_data);
priv->initial_check_obsoleted = TRUE;
_LOGD ("check: send %srequest to '%s'", IS_PERIODIC_CHECK (callback) ? "periodic " : "", priv->uri);
return;
} else {
g_warn_if_fail (!IS_PERIODIC_CHECK (callback));
_LOGD ("check: faking request. Connectivity check disabled");
}
#else
_LOGD ("check: faking request. Compiled without connectivity-check support");
#endif
g_simple_async_result_set_op_res_gssize (simple, priv->state);
@@ -275,38 +338,18 @@ nm_connectivity_check_finish (NMConnectivity *self,
return (NMConnectivityState) g_simple_async_result_get_op_res_gssize (simple);
}
/**************************************************************************/
NMConnectivity *
nm_connectivity_new (void)
nm_connectivity_new (const char *uri,
guint interval,
const char *response)
{
NMConnectivity *self;
NMConfig *config;
const char *check_response;
config = nm_config_get ();
check_response = nm_config_get_connectivity_response (config);
self = g_object_new (NM_TYPE_CONNECTIVITY,
NM_CONNECTIVITY_URI, nm_config_get_connectivity_uri (config),
NM_CONNECTIVITY_INTERVAL, nm_config_get_connectivity_interval (config),
NM_CONNECTIVITY_RESPONSE, check_response ? check_response : DEFAULT_RESPONSE,
return g_object_new (NM_TYPE_CONNECTIVITY,
NM_CONNECTIVITY_URI, uri,
NM_CONNECTIVITY_INTERVAL, interval,
NM_CONNECTIVITY_RESPONSE, response,
NULL);
g_return_val_if_fail (self != NULL, NULL);
update_state (self, NM_CONNECTIVITY_NONE);
return self;
}
static char *
get_non_empty_string_value (const GValue *val)
{
const char *s;
s = g_value_get_string (val);
if (s && s[0])
return g_strdup (s);
else
return NULL;
}
static void
@@ -315,32 +358,48 @@ set_property (GObject *object, guint property_id,
{
NMConnectivity *self = NM_CONNECTIVITY (object);
NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self);
const char *uri, *response;
guint interval;
switch (property_id) {
case PROP_URI:
g_free (priv->uri);
priv->uri = get_non_empty_string_value (value);
uri = g_value_get_string (value);
if (uri && !*uri)
uri = NULL;
#if WITH_CONCHECK
if (priv->uri) {
SoupURI *uri = soup_uri_new (priv->uri);
if (uri) {
SoupURI *soup_uri = soup_uri_new (uri);
if (!uri || !SOUP_URI_VALID_FOR_HTTP (uri)) {
nm_log_err (LOGD_CONCHECK, "Invalid uri '%s' for connectivity check.", priv->uri);
g_free (priv->uri);
priv->uri = NULL;
if (!soup_uri || !SOUP_URI_VALID_FOR_HTTP (soup_uri)) {
_LOGE ("invalid uri '%s' for connectivity check.", uri);
uri = NULL;
}
if (uri)
soup_uri_free (uri);
if (soup_uri)
soup_uri_free (soup_uri);
}
#endif
if (g_strcmp0 (uri, priv->uri) != 0) {
g_free (priv->uri);
priv->uri = g_strdup (uri);
_reschedule_periodic_checks (self, TRUE);
}
break;
case PROP_INTERVAL:
priv->interval = g_value_get_uint (value);
interval = g_value_get_uint (value);
if (priv->interval != interval) {
priv->interval = interval;
_reschedule_periodic_checks (self, TRUE);
}
break;
case PROP_RESPONSE:
g_free (priv->response);
priv->response = get_non_empty_string_value (value);
response = g_value_get_string (value);
if (g_strcmp0 (response, priv->response) != 0) {
/* a response %NULL means, DEFAULT_RESPONSE. Any other response
* (including "") is accepted. */
g_free (priv->response);
priv->response = g_strdup (response);
_reschedule_periodic_checks (self, TRUE);
}
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -363,7 +422,10 @@ get_property (GObject *object, guint property_id,
g_value_set_uint (value, priv->interval);
break;
case PROP_RESPONSE:
g_value_set_string (value, priv->response);
if (priv->response)
g_value_set_string (value, priv->response);
else
g_value_set_static_string (value, DEFAULT_RESPONSE);
break;
case PROP_STATE:
g_value_set_uint (value, priv->state);
@@ -378,11 +440,12 @@ get_property (GObject *object, guint property_id,
static void
nm_connectivity_init (NMConnectivity *self)
{
#if WITH_CONCHECK
NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self);
#if WITH_CONCHECK
priv->soup_session = soup_session_async_new_with_options (SOUP_SESSION_TIMEOUT, 15, NULL);
#endif
priv->state = NM_CONNECTIVITY_NONE;
}
@@ -392,8 +455,8 @@ dispose (GObject *object)
NMConnectivity *self = NM_CONNECTIVITY (object);
NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self);
g_free (priv->uri);
g_free (priv->response);
g_clear_pointer (&priv->uri, g_free);
g_clear_pointer (&priv->response, g_free);
#if WITH_CONCHECK
if (priv->soup_session) {
@@ -422,31 +485,34 @@ nm_connectivity_class_init (NMConnectivityClass *klass)
/* properties */
g_object_class_install_property
(object_class, PROP_URI,
g_param_spec_string (NM_CONNECTIVITY_URI, "", "",
NULL,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
(object_class, PROP_URI,
g_param_spec_string (NM_CONNECTIVITY_URI, "", "",
NULL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property
(object_class, PROP_INTERVAL,
g_param_spec_uint (NM_CONNECTIVITY_INTERVAL, "", "",
0, G_MAXUINT, 300,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS));
(object_class, PROP_INTERVAL,
g_param_spec_uint (NM_CONNECTIVITY_INTERVAL, "", "",
0, G_MAXUINT, 300,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property
(object_class, PROP_RESPONSE,
g_param_spec_string (NM_CONNECTIVITY_RESPONSE, "", "",
DEFAULT_RESPONSE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS));
(object_class, PROP_RESPONSE,
g_param_spec_string (NM_CONNECTIVITY_RESPONSE, "", "",
DEFAULT_RESPONSE,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property
(object_class, PROP_STATE,
g_param_spec_uint (NM_CONNECTIVITY_STATE, "", "",
NM_CONNECTIVITY_UNKNOWN, NM_CONNECTIVITY_FULL, NM_CONNECTIVITY_UNKNOWN,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
(object_class, PROP_STATE,
g_param_spec_uint (NM_CONNECTIVITY_STATE, "", "",
NM_CONNECTIVITY_UNKNOWN, NM_CONNECTIVITY_FULL, NM_CONNECTIVITY_UNKNOWN,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
}

View File

@@ -51,7 +51,11 @@ typedef struct {
GType nm_connectivity_get_type (void);
NMConnectivity *nm_connectivity_new (void);
const char *nm_connectivity_state_to_string (NMConnectivityState state);
NMConnectivity *nm_connectivity_new (const char *uri,
guint interval,
const char *response);
void nm_connectivity_set_online (NMConnectivity *self,
gboolean online);

View File

@@ -315,6 +315,7 @@ main (int argc, char *argv[])
&argc,
options,
NULL,
NULL,
_("nm-iface-helper is a small, standalone process that manages a single network interface.")))
exit (1);
@@ -480,6 +481,12 @@ main (int argc, char *argv[])
/*******************************************************/
/* Stub functions */
void
nm_main_config_reload ()
{
nm_log_info (LOGD_CORE, "reloading configuration not supported");
}
gconstpointer nm_config_get (void);
const char *nm_config_get_dhcp_client (gpointer unused);
gboolean nm_config_get_configure_and_quit (gpointer unused);

View File

@@ -167,6 +167,7 @@ typedef struct {
GSList *devices;
NMState state;
NMConfig *config;
NMConnectivity *connectivity;
int ignore_link_added_cb;
@@ -463,6 +464,18 @@ active_connection_get_by_path (NMManager *manager, const char *path)
/************************************************************************/
static void
_config_changed_cb (NMConfig *config, NMConfigData *config_data, NMConfigChangeFlags changes, NMConfigData *old_data, NMManager *self)
{
g_object_set (NM_MANAGER_GET_PRIVATE (self)->connectivity,
NM_CONNECTIVITY_URI, nm_config_data_get_connectivity_uri (config_data),
NM_CONNECTIVITY_INTERVAL, nm_config_data_get_connectivity_interval (config_data),
NM_CONNECTIVITY_RESPONSE, nm_config_data_get_connectivity_response (config_data),
NULL);
}
/************************************************************************/
static NMDevice *
nm_manager_get_device_by_udi (NMManager *manager, const char *udi)
{
@@ -4274,12 +4287,9 @@ connectivity_changed (NMConnectivity *connectivity,
gpointer user_data)
{
NMManager *self = NM_MANAGER (user_data);
NMConnectivityState state;
static const char *connectivity_states[] = { "UNKNOWN", "NONE", "PORTAL", "LIMITED", "FULL" };
state = nm_connectivity_get_state (connectivity);
nm_log_dbg (LOGD_CORE, "connectivity checking indicates %s",
connectivity_states[state]);
nm_connectivity_state_to_string (nm_connectivity_get_state (connectivity)));
nm_manager_update_state (self);
g_object_notify (G_OBJECT (self), NM_MANAGER_CONNECTIVITY);
@@ -4722,6 +4732,7 @@ nm_manager_new (NMSettings *settings,
NMManagerPrivate *priv;
DBusGConnection *bus;
DBusConnection *dbus_connection;
NMConfigData *config_data;
g_assert (settings);
@@ -4753,7 +4764,16 @@ nm_manager_new (NMSettings *settings,
g_signal_connect (priv->policy, "notify::" NM_POLICY_ACTIVATING_IP6_DEVICE,
G_CALLBACK (policy_activating_device_changed), singleton);
priv->connectivity = nm_connectivity_new ();
priv->config = g_object_ref (nm_config_get ());
g_signal_connect (G_OBJECT (priv->config),
NM_CONFIG_SIGNAL_CONFIG_CHANGED,
G_CALLBACK (_config_changed_cb),
singleton);
config_data = nm_config_get_data (priv->config);
priv->connectivity = nm_connectivity_new (nm_config_data_get_connectivity_uri (config_data),
nm_config_data_get_connectivity_interval (config_data),
nm_config_data_get_connectivity_response (config_data));
g_signal_connect (priv->connectivity, "notify::" NM_CONNECTIVITY_STATE,
G_CALLBACK (connectivity_changed), singleton);
@@ -5074,7 +5094,14 @@ dispose (GObject *object)
g_clear_object (&priv->primary_connection);
g_clear_object (&priv->activating_connection);
g_clear_object (&priv->connectivity);
if (priv->config) {
g_signal_handlers_disconnect_by_func (priv->config, _config_changed_cb, manager);
g_clear_object (&priv->config);
}
if (priv->connectivity) {
g_signal_handlers_disconnect_by_func (priv->connectivity, connectivity_changed, manager);
g_clear_object (&priv->connectivity);
}
g_free (priv->hostname);

View File

@@ -26,6 +26,8 @@ typedef struct _NMActiveConnection NMActiveConnection;
typedef struct _NMVpnConnection NMVpnConnection;
typedef struct _NMActRequest NMActRequest;
typedef struct _NMAuthSubject NMAuthSubject;
typedef struct _NMConfig NMConfig;
typedef struct _NMConfigData NMConfigData;
typedef struct _NMConnectionProvider NMConnectionProvider;
typedef struct _NMConnectivity NMConnectivity;
typedef struct _NMDBusManager NMDBusManager;

View File

@@ -1669,7 +1669,7 @@ default_wired_clear_tag (NMSettings *self,
g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (default_wired_connection_updated_by_user_cb), self);
if (add_to_no_auto_default)
nm_config_set_ethernet_no_auto_default (NM_SETTINGS_GET_PRIVATE (self)->config, device);
nm_config_set_no_auto_default_for_device (NM_SETTINGS_GET_PRIVATE (self)->config, device);
}
void

View File

@@ -847,7 +847,7 @@ nm_system_config_factory (void)
priv = SC_PLUGIN_EXAMPLE_GET_PRIVATE (singleton);
/* Cache the config file path */
priv->conf_file = nm_config_get_path (nm_config_get ());
priv->conf_file = nm_config_data_get_config_main_file (nm_config_get_data (nm_config_get ()));
} else {
/* This function should never be called twice */
g_assert_not_reached ();

View File

@@ -123,9 +123,9 @@ is_managed_plugin (void)
{
char *result = NULL;
result = nm_config_get_value (nm_config_get (),
IFNET_KEY_FILE_GROUP, IFNET_KEY_FILE_KEY_MANAGED,
NULL);
result = nm_config_data_get_value (nm_config_get_data_orig (nm_config_get ()),
IFNET_KEY_FILE_GROUP, IFNET_KEY_FILE_KEY_MANAGED,
NULL);
if (result) {
gboolean ret = is_true (result);
g_free (result);
@@ -264,9 +264,9 @@ reload_connections (NMSystemConfigInterface *config)
nm_log_info (LOGD_SETTINGS, "Loading connections");
str_auto_refresh = nm_config_get_value (nm_config_get (),
IFNET_KEY_FILE_GROUP, "auto_refresh",
NULL);
str_auto_refresh = nm_config_data_get_value (nm_config_get_data_orig (nm_config_get ()),
IFNET_KEY_FILE_GROUP, "auto_refresh",
NULL);
if (str_auto_refresh && is_true (str_auto_refresh))
auto_refresh = TRUE;
g_free (str_auto_refresh);

View File

@@ -456,12 +456,12 @@ SCPluginIfupdown_init (NMSystemConfigInterface *config)
g_hash_table_destroy (auto_ifaces);
/* Check the config file to find out whether to manage interfaces */
value = nm_config_get_value (nm_config_get (),
IFUPDOWN_KEY_FILE_GROUP, IFUPDOWN_KEY_FILE_KEY_MANAGED,
&error);
value = nm_config_data_get_value (nm_config_get_data_orig (nm_config_get ()),
IFUPDOWN_KEY_FILE_GROUP, IFUPDOWN_KEY_FILE_KEY_MANAGED,
&error);
if (error) {
nm_log_info (LOGD_SETTINGS, "loading system config file (%s) caused error: %s",
nm_config_get_path (nm_config_get ()),
nm_config_data_get_config_main_file (nm_config_get_data (nm_config_get ())),
error->message);
} else {
gboolean manage_well_known;

View File

@@ -843,7 +843,7 @@ nm_settings_keyfile_plugin_new (void)
singleton = SC_PLUGIN_KEYFILE (g_object_new (SC_TYPE_PLUGIN_KEYFILE, NULL));
priv = SC_PLUGIN_KEYFILE_GET_PRIVATE (singleton);
priv->conf_file = nm_config_get_path (nm_config_get ());
priv->conf_file = nm_config_data_get_config_main_file (nm_config_get_data (nm_config_get ()));
/* plugin_set_hostname() has to be called *after* priv->conf_file is set */
priv->hostname = plugin_get_hostname (singleton);

View File

@@ -27,9 +27,12 @@
#include <nm-config.h>
#include "nm-test-device.h"
#include "nm-fake-platform.h"
#include "nm-logging.h"
static void
setup_config (const char *config_file, const char *config_dir, ...)
#include "nm-test-utils.h"
static NMConfig *
setup_config (GError **error, const char *config_file, const char *config_dir, ...)
{
va_list ap;
GPtrArray *args;
@@ -37,6 +40,11 @@ setup_config (const char *config_file, const char *config_dir, ...)
int argc;
GOptionContext *context;
gboolean success;
NMConfig *config;
GError *local_error = NULL;
NMConfigCmdLineOptions *cli;
g_assert (!error || !*error);
args = g_ptr_array_new ();
g_ptr_array_add (args, "test-config");
@@ -53,8 +61,10 @@ setup_config (const char *config_file, const char *config_dir, ...)
argv = (char **)args->pdata;
argc = args->len;
cli = nm_config_cmd_line_options_new ();
context = g_option_context_new (NULL);
g_option_context_add_main_entries (context, nm_config_get_options (), NULL);
nm_config_cmd_line_options_add_to_entries (cli, context);
success = g_option_context_parse (context, &argc, &argv, NULL);
g_option_context_free (context);
@@ -62,6 +72,18 @@ setup_config (const char *config_file, const char *config_dir, ...)
g_printerr ("Invalid options.\n");
g_ptr_array_free (args, TRUE);
config = nm_config_setup (cli, &local_error);
if (error) {
g_assert (!config);
g_assert (local_error);
g_propagate_error (error, local_error);
} else {
g_assert (config);
g_assert_no_error (local_error);
}
nm_config_cmd_line_options_free (cli);
return config;
}
static void
@@ -72,14 +94,12 @@ test_config_simple (void)
const char **plugins;
char *value;
setup_config (SRCDIR "/NetworkManager.conf", "/no/such/dir", NULL);
config = nm_config_new (&error);
g_assert_no_error (error);
config = setup_config (NULL, SRCDIR "/NetworkManager.conf", "/no/such/dir", NULL);
g_assert_cmpstr (nm_config_get_path (config), ==, SRCDIR "/NetworkManager.conf");
g_assert_cmpstr (nm_config_data_get_config_main_file (nm_config_get_data_orig (config)), ==, SRCDIR "/NetworkManager.conf");
g_assert_cmpstr (nm_config_get_dhcp_client (config), ==, "dhclient");
g_assert_cmpstr (nm_config_get_log_level (config), ==, "INFO");
g_assert_cmpint (nm_config_get_connectivity_interval (config), ==, 100);
g_assert_cmpint (nm_config_data_get_connectivity_interval (nm_config_get_data_orig (config)), ==, 100);
plugins = nm_config_get_plugins (config);
g_assert_cmpint (g_strv_length ((char **)plugins), ==, 3);
@@ -87,16 +107,16 @@ test_config_simple (void)
g_assert_cmpstr (plugins[1], ==, "bar");
g_assert_cmpstr (plugins[2], ==, "baz");
value = nm_config_get_value (config, "extra-section", "extra-key", NULL);
value = nm_config_data_get_value (nm_config_get_data_orig (config), "extra-section", "extra-key", NULL);
g_assert_cmpstr (value, ==, "some value");
g_free (value);
value = nm_config_get_value (config, "extra-section", "no-key", &error);
value = nm_config_data_get_value (nm_config_get_data_orig (config), "extra-section", "no-key", &error);
g_assert (!value);
g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND);
g_clear_error (&error);
value = nm_config_get_value (config, "no-section", "no-key", &error);
value = nm_config_data_get_value (nm_config_get_data_orig (config), "no-section", "no-key", &error);
g_assert (!value);
g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND);
g_clear_error (&error);
@@ -107,45 +127,38 @@ test_config_simple (void)
static void
test_config_non_existent (void)
{
NMConfig *config;
GError *error = NULL;
setup_config (SRCDIR "/no-such-file", "/no/such/dir", NULL);
config = nm_config_new (&error);
g_assert (!config);
setup_config (&error, SRCDIR "/no-such-file", "/no/such/dir", NULL);
g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND);
g_clear_error (&error);
}
static void
test_config_parse_error (void)
{
NMConfig *config;
GError *error = NULL;
setup_config (SRCDIR "/bad.conf", "/no/such/dir", NULL);
config = nm_config_new (&error);
g_assert (!config);
setup_config (&error, SRCDIR "/bad.conf", "/no/such/dir", NULL);
g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_PARSE);
g_clear_error (&error);
}
static void
test_config_override (void)
{
NMConfig *config;
GError *error = NULL;
const char **plugins;
setup_config (SRCDIR "/NetworkManager.conf", "/no/such/dir",
"--plugins", "alpha,beta,gamma,delta",
"--connectivity-interval", "12",
NULL);
config = nm_config_new (&error);
g_assert_no_error (error);
config = setup_config (NULL, SRCDIR "/NetworkManager.conf", "/no/such/dir",
"--plugins", "alpha,beta,gamma,delta",
"--connectivity-interval", "12",
NULL);
g_assert_cmpstr (nm_config_get_path (config), ==, SRCDIR "/NetworkManager.conf");
g_assert_cmpstr (nm_config_data_get_config_main_file (nm_config_get_data_orig (config)), ==, SRCDIR "/NetworkManager.conf");
g_assert_cmpstr (nm_config_get_dhcp_client (config), ==, "dhclient");
g_assert_cmpstr (nm_config_get_log_level (config), ==, "INFO");
g_assert_cmpint (nm_config_get_connectivity_interval (config), ==, 12);
g_assert_cmpint (nm_config_data_get_connectivity_interval (nm_config_get_data_orig (config)), ==, 12);
plugins = nm_config_get_plugins (config);
g_assert_cmpint (g_strv_length ((char **)plugins), ==, 4);
@@ -175,37 +188,36 @@ test_config_no_auto_default (void)
g_assert_cmpint (nwrote, ==, 18);
close (fd);
setup_config (SRCDIR "/NetworkManager.conf", "/no/such/dir",
"--no-auto-default", state_file,
NULL);
config = nm_config_new (&error);
g_assert_no_error (error);
config = setup_config (NULL, SRCDIR "/NetworkManager.conf", "/no/such/dir",
"--no-auto-default", state_file,
NULL);
dev1 = nm_test_device_new ("11:11:11:11:11:11");
dev2 = nm_test_device_new ("22:22:22:22:22:22");
dev3 = nm_test_device_new ("33:33:33:33:33:33");
dev4 = nm_test_device_new ("44:44:44:44:44:44");
g_assert (!nm_config_get_ethernet_can_auto_default (config, dev1));
g_assert (!nm_config_get_ethernet_can_auto_default (config, dev2));
g_assert (nm_config_get_ethernet_can_auto_default (config, dev3));
g_assert (!nm_config_get_ethernet_can_auto_default (config, dev4));
g_assert (nm_config_get_no_auto_default_for_device (config, dev1));
g_assert (nm_config_get_no_auto_default_for_device (config, dev2));
g_assert (!nm_config_get_no_auto_default_for_device (config, dev3));
g_assert (nm_config_get_no_auto_default_for_device (config, dev4));
nm_config_set_ethernet_no_auto_default (config, dev3);
g_assert (!nm_config_get_ethernet_can_auto_default (config, dev3));
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*config: update * (no-auto-default)*");
nm_config_set_no_auto_default_for_device (config, dev3);
g_test_assert_expected_messages ();
g_assert (nm_config_get_no_auto_default_for_device (config, dev3));
g_object_unref (config);
setup_config (SRCDIR "/NetworkManager.conf", "/no/such/dir",
"--no-auto-default", state_file,
NULL);
config = nm_config_new (&error);
g_assert_no_error (error);
config = setup_config (NULL, SRCDIR "/NetworkManager.conf", "/no/such/dir",
"--no-auto-default", state_file,
NULL);
g_assert (!nm_config_get_ethernet_can_auto_default (config, dev1));
g_assert (!nm_config_get_ethernet_can_auto_default (config, dev2));
g_assert (!nm_config_get_ethernet_can_auto_default (config, dev3));
g_assert (!nm_config_get_ethernet_can_auto_default (config, dev4));
g_assert (nm_config_get_no_auto_default_for_device (config, dev1));
g_assert (nm_config_get_no_auto_default_for_device (config, dev2));
g_assert (nm_config_get_no_auto_default_for_device (config, dev3));
g_assert (nm_config_get_no_auto_default_for_device (config, dev4));
g_object_unref (config);
@@ -222,20 +234,17 @@ static void
test_config_confdir (void)
{
NMConfig *config;
GError *error = NULL;
const char **plugins;
char *value;
setup_config (SRCDIR "/NetworkManager.conf", SRCDIR "/conf.d", NULL);
config = nm_config_new (&error);
g_assert_no_error (error);
config = setup_config (NULL, SRCDIR "/NetworkManager.conf", SRCDIR "/conf.d", NULL);
g_assert_cmpstr (nm_config_get_path (config), ==, SRCDIR "/NetworkManager.conf");
g_assert_cmpstr (nm_config_data_get_config_main_file (nm_config_get_data_orig (config)), ==, SRCDIR "/NetworkManager.conf");
g_assert_cmpstr (nm_config_get_dhcp_client (config), ==, "dhcpcd");
g_assert_cmpstr (nm_config_get_log_level (config), ==, "INFO");
g_assert_cmpstr (nm_config_get_log_domains (config), ==, "PLATFORM,DNS,WIFI");
g_assert_cmpstr (nm_config_get_connectivity_uri (config), ==, "http://example.net");
g_assert_cmpint (nm_config_get_connectivity_interval (config), ==, 100);
g_assert_cmpstr (nm_config_data_get_connectivity_uri (nm_config_get_data_orig (config)), ==, "http://example.net");
g_assert_cmpint (nm_config_data_get_connectivity_interval (nm_config_get_data_orig (config)), ==, 100);
plugins = nm_config_get_plugins (config);
g_assert_cmpint (g_strv_length ((char **)plugins), ==, 5);
@@ -245,21 +254,21 @@ test_config_confdir (void)
g_assert_cmpstr (plugins[3], ==, "one");
g_assert_cmpstr (plugins[4], ==, "two");
value = nm_config_get_value (config, "main", "extra", NULL);
value = nm_config_data_get_value (nm_config_get_data_orig (config), "main", "extra", NULL);
g_assert_cmpstr (value, ==, "hello");
g_free (value);
value = nm_config_get_value (config, "main", "new", NULL);
value = nm_config_data_get_value (nm_config_get_data_orig (config), "main", "new", NULL);
g_assert_cmpstr (value, ==, "something"); /* not ",something" */
g_free (value);
value = nm_config_get_value (config, "order", "a", NULL);
value = nm_config_data_get_value (nm_config_get_data_orig (config), "order", "a", NULL);
g_assert_cmpstr (value, ==, "90");
g_free (value);
value = nm_config_get_value (config, "order", "b", NULL);
value = nm_config_data_get_value (nm_config_get_data_orig (config), "order", "b", NULL);
g_assert_cmpstr (value, ==, "10");
g_free (value);
value = nm_config_get_value (config, "order", "c", NULL);
value = nm_config_data_get_value (nm_config_get_data_orig (config), "order", "c", NULL);
g_assert_cmpstr (value, ==, "0");
g_free (value);
@@ -269,24 +278,20 @@ test_config_confdir (void)
static void
test_config_confdir_parse_error (void)
{
NMConfig *config;
GError *error = NULL;
/* Using SRCDIR as the conf dir will pick up bad.conf */
setup_config (SRCDIR "/NetworkManager.conf", SRCDIR, NULL);
config = nm_config_new (&error);
g_assert (!config);
setup_config (&error, SRCDIR "/NetworkManager.conf", SRCDIR, NULL);
g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_PARSE);
g_clear_error (&error);
}
NMTST_DEFINE ();
int
main (int argc, char **argv)
{
#if !GLIB_CHECK_VERSION (2, 35, 0)
g_type_init ();
#endif
g_test_init (&argc, &argv, NULL);
nmtst_init_assert_logging (&argc, &argv);
nm_fake_platform_setup ();