config: merge branch 'th/config-enable-bgo755935'

https://bugzilla.gnome.org/show_bug.cgi?id=755935
This commit is contained in:
Thomas Haller 2015-10-05 18:31:19 +02:00
commit 7b446137f5
13 changed files with 555 additions and 71 deletions

View file

@ -286,4 +286,19 @@ nm_strstrip (char *str)
/*****************************************************************************/
static inline guint
nm_encode_version (guint major, guint minor, guint micro) {
/* analog to the preprocessor macro NM_ENCODE_VERSION(). */
return (major << 16) | (minor << 8) | micro;
}
static inline void
nm_decode_version (guint version, guint *major, guint *minor, guint *micro) {
*major = (version & 0xFFFF0000u) >> 16;
*minor = (version & 0x0000FF00u) >> 8;
*micro = (version & 0x000000FFu);
}
/*****************************************************************************/
#endif /* __NM_MACROS_INTERNAL_H__ */

View file

@ -642,14 +642,6 @@ ipv6.ip6-privacy=1
connection-specific configuration.</para>
<para>
<variablelist>
<varlistentry>
<term><varname>enable</varname></term>
<listitem>
<para>
Whether the global DNS configuration should be used.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>searches</varname></term>
<listitem>
@ -702,6 +694,95 @@ ipv6.ip6-privacy=1
</para>
</refsect1>
<refsect1>
<title><literal>.config</literal> sections</title>
<para>This is a special section that contains options which apply
to the configuration file that contains the option.
</para>
<para>
<variablelist>
<varlistentry>
<term><varname>enable</varname></term>
<listitem>
<para>
Defaults to "<literal>true</literal>". If "<literal>false</literal>",
the configuration file will be skipped during loading.
Note that the main configation file <literal>NetworkManger.conf</literal>
cannot be disabled.
<programlisting>
# always skip loading the config file
[.config]
enable=false
</programlisting>
</para>
<para>
You can also match against the version of NetworkManager. For example
the following are valid configurations:
<programlisting>
# only load on version 1.0.6
[.config]
enable=nm-version:1.0.6
# load on all versions 1.0.x, but not 1.2.x
[.config]
enable=nm-version:1.0
# only load on versions &gt;= 1.1.6. This does not match
# with version 1.2.0 or 1.4.4. Only the last digit is considered.
[.config]
enable=nm-version-min:1.1.6
# only load on versions &gt;= 1.2. Contrary to the previous
# example, this also matches with 1.2.0, 1.2.10, 1.4.4, etc.
[.config]
enable=nm-version-min:1.2
# Match against the maximum allowed version. The example matches
# versions 1.2.0, 1.2.2, 1.2.4. Again, only the last version digit
# is allowed to be smaller. So this would not match match on 1.1.10.
[.config]
enable=nm-version-max:1.2.6
</programlisting>
</para>
<para>
You can also match against the value of the environment variable
<literal>NM_CONFIG_ENABLE_TAG</literal>, like:
<programlisting>
# always skip loading the file when running NetworkManager with
# environment variable "NM_CONFIG_ENABLE_TAG=TAG1"
[.config]
enable=env:TAG1
</programlisting>
</para>
<para>
More then one match can be specified. The configuration will be
enabled if one of the predicates matches ("or"). The special prefix "except:" can
be used to negate the match. Note that if one except-predicate
matches, the entire configuration will be disabled.
In other words, a except predicate always wins over other predicates.
<programlisting>
# enable the configuration either when the environment variable
# is present or the version is at least 1.2.0.
[.config]
enable=env:TAG2,nm-version-min:1.2
# enable the configuration for version &gt;= 1.2.0, but disable
# it when the environment variable is set to "TAG3"
[.config]
enable=except:env:TAG3,nm-version-min:1.2
# enable the configuration on &gt;= 1.3, &gt;= 1.2.6, and &gt;= 1.0.16.
# Useful if a certain feature is only present since those releases.
[.config]
enable=nm-version-min:1.3,nm-version-min:1.2.6,nm-version-min:1.0.16
</programlisting>
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</refsect1>
<refsect1>
<title>Plugins</title>

View file

@ -188,6 +188,40 @@ _nm_singleton_instance_register_destruction (GObject *instance)
/*****************************************************************************/
gint
nm_utils_ascii_str_to_bool (const char *str,
gint default_value)
{
gsize len;
char *s = NULL;
if (!str)
return default_value;
while (str[0] && g_ascii_isspace (str[0]))
str++;
if (!str[0])
return default_value;
len = strlen (str);
if (g_ascii_isspace (str[len - 1])) {
s = g_strdup (str);
g_strchomp (s);
str = s;
}
if (!g_ascii_strcasecmp (str, "true") || !g_ascii_strcasecmp (str, "yes") || !g_ascii_strcasecmp (str, "on") || !g_ascii_strcasecmp (str, "1"))
default_value = TRUE;
else if (!g_ascii_strcasecmp (str, "false") || !g_ascii_strcasecmp (str, "no") || !g_ascii_strcasecmp (str, "off") || !g_ascii_strcasecmp (str, "0"))
default_value = FALSE;
if (s)
g_free (s);
return default_value;
}
/*****************************************************************************/
/*
* nm_ethernet_address_is_valid:
* @addr: pointer to a binary or ASCII Ethernet address
@ -1159,6 +1193,22 @@ nm_utils_find_helper(const char *progname, const char *try_first, GError **error
#define DEVICE_TYPE_TAG "type:"
#define SUBCHAN_TAG "s390-subchannels:"
#define EXCEPT_TAG "except:"
#define MATCH_TAG_CONFIG_NM_VERSION "nm-version:"
#define MATCH_TAG_CONFIG_NM_VERSION_MIN "nm-version-min:"
#define MATCH_TAG_CONFIG_NM_VERSION_MAX "nm-version-max:"
#define MATCH_TAG_CONFIG_ENV "env:"
#define _spec_has_prefix(pspec, tag) \
({ \
const char **_spec = (pspec); \
gboolean _has = FALSE; \
\
if (!g_ascii_strncasecmp (*_spec, (""tag), STRLEN (tag))) { \
*_spec += STRLEN (tag); \
_has = TRUE; \
} \
_has; \
})
static const char *
_match_except (const char *spec_str, gboolean *out_except)
@ -1388,6 +1438,108 @@ nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels)
return match;
}
static gboolean
_match_config_nm_version (const char *str, const char *tag, guint cur_nm_version)
{
gs_free char *s_ver = NULL;
gs_strfreev char **s_ver_tokens = NULL;
gint v_maj = -1, v_min = -1, v_mic = -1;
guint c_maj = -1, c_min = -1, c_mic = -1;
guint n_tokens;
s_ver = g_strdup (str);
g_strstrip (s_ver);
/* Let's be strict with the accepted format here. No funny stuff!! */
if (s_ver[strspn (s_ver, ".0123456789")] != '\0')
return FALSE;
s_ver_tokens = g_strsplit (s_ver, ".", -1);
n_tokens = g_strv_length (s_ver_tokens);
if (n_tokens == 0 || n_tokens > 3)
return FALSE;
v_maj = _nm_utils_ascii_str_to_int64 (s_ver_tokens[0], 10, 0, 0xFFFF, -1);
if (v_maj < 0)
return FALSE;
if (n_tokens >= 2) {
v_min = _nm_utils_ascii_str_to_int64 (s_ver_tokens[1], 10, 0, 0xFF, -1);
if (v_min < 0)
return FALSE;
}
if (n_tokens >= 3) {
v_mic = _nm_utils_ascii_str_to_int64 (s_ver_tokens[2], 10, 0, 0xFF, -1);
if (v_mic < 0)
return FALSE;
}
nm_decode_version (cur_nm_version, &c_maj, &c_min, &c_mic);
#define CHECK_AND_RETURN_FALSE(cur, val, tag, is_last_digit) \
G_STMT_START { \
if (!strcmp (tag, MATCH_TAG_CONFIG_NM_VERSION_MIN)) { \
if (cur < val) \
return FALSE; \
} else if (!strcmp (tag, MATCH_TAG_CONFIG_NM_VERSION_MAX)) { \
if (cur > val) \
return FALSE; \
} else { \
if (cur != val) \
return FALSE; \
} \
if (!(is_last_digit)) { \
if (cur != val) \
return FALSE; \
} \
} G_STMT_END
if (v_mic >= 0)
CHECK_AND_RETURN_FALSE (c_mic, v_mic, tag, TRUE);
if (v_min >= 0)
CHECK_AND_RETURN_FALSE (c_min, v_min, tag, v_mic < 0);
CHECK_AND_RETURN_FALSE (c_maj, v_maj, tag, v_min < 0);
return TRUE;
}
NMMatchSpecMatchType
nm_match_spec_match_config (const GSList *specs, guint cur_nm_version, const char *env)
{
const GSList *iter;
NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH;
if (!specs)
return NM_MATCH_SPEC_NO_MATCH;
for (iter = specs; iter; iter = g_slist_next (iter)) {
const char *spec_str = iter->data;
gboolean except;
gboolean v_match;
if (!spec_str || !*spec_str)
continue;
spec_str = _match_except (spec_str, &except);
if (_spec_has_prefix (&spec_str, MATCH_TAG_CONFIG_NM_VERSION))
v_match = _match_config_nm_version (spec_str, MATCH_TAG_CONFIG_NM_VERSION, cur_nm_version);
else if (_spec_has_prefix (&spec_str, MATCH_TAG_CONFIG_NM_VERSION_MIN))
v_match = _match_config_nm_version (spec_str, MATCH_TAG_CONFIG_NM_VERSION_MIN, cur_nm_version);
else if (_spec_has_prefix (&spec_str, MATCH_TAG_CONFIG_NM_VERSION_MAX))
v_match = _match_config_nm_version (spec_str, MATCH_TAG_CONFIG_NM_VERSION_MAX, cur_nm_version);
else if (_spec_has_prefix (&spec_str, MATCH_TAG_CONFIG_ENV))
v_match = env && env[0] && !strcmp (spec_str, env);
else
continue;
if (v_match) {
if (except)
return NM_MATCH_SPEC_NEG_MATCH;
match = NM_MATCH_SPEC_MATCH;
}
}
return match;
}
/**
* nm_match_spec_split:
* @value: the string of device specs

View file

@ -114,6 +114,11 @@ gboolean nm_utils_error_is_cancelled (GError *error,
/*****************************************************************************/
gint nm_utils_ascii_str_to_bool (const char *str,
gint default_value);
/*****************************************************************************/
gboolean nm_ethernet_address_is_valid (gconstpointer addr, gssize len);
in_addr_t nm_utils_ip4_address_clear_host_address (in_addr_t addr, guint8 plen);
@ -182,6 +187,7 @@ NMMatchSpecMatchType nm_match_spec_device_type (const GSList *specs, const char
NMMatchSpecMatchType nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr);
NMMatchSpecMatchType nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels);
NMMatchSpecMatchType nm_match_spec_interface_name (const GSList *specs, const char *interface_name);
NMMatchSpecMatchType nm_match_spec_match_config (const GSList *specs, guint nm_version, const char *env);
GSList *nm_match_spec_split (const char *value);
char *nm_match_spec_join (GSList *specs);

View file

@ -731,7 +731,7 @@ load_global_dns (GKeyFile *keyfile, gboolean internal)
: NM_CONFIG_KEYFILE_GROUPPREFIX_GLOBAL_DNS_DOMAIN;
domain_prefix_len = strlen (domain_prefix);
if (!keyfile || !nm_config_keyfile_get_boolean (keyfile, group, NM_CONFIG_KEYFILE_KEY_GLOBAL_DNS_ENABLE, FALSE))
if (!nm_config_keyfile_has_global_dns_config (keyfile, internal))
return NULL;
conf = g_malloc0 (sizeof (NMGlobalDnsConfig));
@ -1087,10 +1087,10 @@ _get_connection_info_init (ConnectionInfo *connection_info, GKeyFile *keyfile, c
/* pass ownership of @group on... */
connection_info->group_name = group;
connection_info->match_device.spec = nm_config_get_device_match_spec (keyfile,
group,
"match-device",
&connection_info->match_device.has);
connection_info->match_device.spec = nm_config_get_match_spec (keyfile,
group,
"match-device",
&connection_info->match_device.has);
connection_info->stop_match = nm_config_keyfile_get_boolean (keyfile, group, "stop-match", FALSE);
}
@ -1362,10 +1362,10 @@ constructed (GObject *object)
priv->dns_mode = nm_strstrip (g_key_file_get_string (priv->keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "dns", NULL));
priv->rc_manager = nm_strstrip (g_key_file_get_string (priv->keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "rc-manager", NULL));
priv->ignore_carrier = nm_config_get_device_match_spec (priv->keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "ignore-carrier", NULL);
priv->assume_ipv6ll_only = nm_config_get_device_match_spec (priv->keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "assume-ipv6ll-only", NULL);
priv->ignore_carrier = nm_config_get_match_spec (priv->keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "ignore-carrier", NULL);
priv->assume_ipv6ll_only = nm_config_get_match_spec (priv->keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "assume-ipv6ll-only", NULL);
priv->no_auto_default.specs_config = nm_config_get_device_match_spec (priv->keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "no-auto-default", NULL);
priv->no_auto_default.specs_config = nm_config_get_match_spec (priv->keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "no-auto-default", NULL);
priv->global_dns = load_global_dns (priv->keyfile_user, FALSE);
if (!priv->global_dns)

View file

@ -126,32 +126,7 @@ gint
nm_config_parse_boolean (const char *str,
gint default_value)
{
gsize len;
char *s = NULL;
if (!str)
return default_value;
while (str[0] && g_ascii_isspace (str[0]))
str++;
if (!str[0])
return default_value;
len = strlen (str);
if (g_ascii_isspace (str[len - 1])) {
s = g_strdup (str);
g_strchomp (s);
str = s;
}
if (!g_ascii_strcasecmp (str, "true") || !g_ascii_strcasecmp (str, "yes") || !g_ascii_strcasecmp (str, "on") || !g_ascii_strcasecmp (str, "1"))
default_value = TRUE;
else if (!g_ascii_strcasecmp (str, "false") || !g_ascii_strcasecmp (str, "no") || !g_ascii_strcasecmp (str, "off") || !g_ascii_strcasecmp (str, "0"))
default_value = FALSE;
if (s)
g_free (s);
return default_value;
return nm_utils_ascii_str_to_bool (str, default_value);
}
gint
@ -520,6 +495,47 @@ nm_config_create_keyfile ()
return keyfile;
}
/* this is an external variable, to make loading testable. Other then that,
* no code is supposed to change this. */
guint _nm_config_match_nm_version = NM_VERSION_CUR_STABLE;
char *_nm_config_match_env = NULL;
static gboolean
ignore_config_snippet (GKeyFile *keyfile, gboolean is_base_config)
{
GSList *specs;
gboolean as_bool;
NMMatchSpecMatchType match_type;
if (is_base_config)
return FALSE;
if (!g_key_file_has_key (keyfile, NM_CONFIG_KEYFILE_GROUP_CONFIG, NM_CONFIG_KEYFILE_KEY_CONFIG_ENABLE, NULL))
return FALSE;
/* first, let's try to parse the value as plain boolean. If that is possible, we don't treat
* the value as match-spec. */
as_bool = nm_config_keyfile_get_boolean (keyfile, NM_CONFIG_KEYFILE_GROUP_CONFIG, NM_CONFIG_KEYFILE_KEY_CONFIG_ENABLE, -1);
if (as_bool != -1)
return !as_bool;
if (G_UNLIKELY (!_nm_config_match_env)) {
const char *e;
e = g_getenv ("NM_CONFIG_ENABLE_TAG");
_nm_config_match_env = g_strdup (e ? e : "");
}
/* second, interpret the value as match-spec. */
specs = nm_config_get_match_spec (keyfile, NM_CONFIG_KEYFILE_GROUP_CONFIG, NM_CONFIG_KEYFILE_KEY_CONFIG_ENABLE, NULL);
match_type = nm_match_spec_match_config (specs,
_nm_config_match_nm_version,
_nm_config_match_env);
g_slist_free_full (specs, g_free);
return match_type != NM_MATCH_SPEC_MATCH;
}
static int
_sort_groups_cmp (const char **pa, const char **pb, gpointer dummy)
{
@ -593,7 +609,7 @@ _setting_is_string_list (const char *group, const char *key)
}
static gboolean
read_config (GKeyFile *keyfile, const char *dirname, const char *path, GError **error)
read_config (GKeyFile *keyfile, gboolean is_base_config, const char *dirname, const char *path, GError **error)
{
GKeyFile *kf;
char **groups, **keys;
@ -623,6 +639,16 @@ read_config (GKeyFile *keyfile, const char *dirname, const char *path, GError **
return FALSE;
}
if (ignore_config_snippet (kf, is_base_config)) {
g_key_file_free (kf);
return TRUE;
}
/* the config-group is internal to every configuration snippets. It doesn't make sense
* to merge the into the global configuration, and it doesn't make sense to preserve the
* group beyond this point. */
g_key_file_remove_group (keyfile, NM_CONFIG_KEYFILE_GROUP_CONFIG, NULL);
/* Override the current settings with the new ones */
groups = g_key_file_get_groups (kf, &ngroups);
if (!groups)
@ -769,7 +795,7 @@ read_base_config (GKeyFile *keyfile,
/* Try a user-specified config file first */
if (cli_config_main_file) {
/* Bad user-specific config file path is a hard error */
if (read_config (keyfile, NULL, cli_config_main_file, error)) {
if (read_config (keyfile, TRUE, NULL, cli_config_main_file, error)) {
*out_config_main_file = g_strdup (cli_config_main_file);
return TRUE;
} else
@ -784,7 +810,7 @@ read_base_config (GKeyFile *keyfile,
*/
/* Try deprecated nm-system-settings.conf first */
if (read_config (keyfile, NULL, DEFAULT_CONFIG_MAIN_FILE_OLD, &my_error)) {
if (read_config (keyfile, TRUE, NULL, DEFAULT_CONFIG_MAIN_FILE_OLD, &my_error)) {
*out_config_main_file = g_strdup (DEFAULT_CONFIG_MAIN_FILE_OLD);
return TRUE;
}
@ -797,7 +823,7 @@ read_base_config (GKeyFile *keyfile,
g_clear_error (&my_error);
/* Try the standard config file location next */
if (read_config (keyfile, NULL, DEFAULT_CONFIG_MAIN_FILE, &my_error)) {
if (read_config (keyfile, TRUE, NULL, DEFAULT_CONFIG_MAIN_FILE, &my_error)) {
*out_config_main_file = g_strdup (DEFAULT_CONFIG_MAIN_FILE);
return TRUE;
}
@ -903,7 +929,7 @@ read_entire_config (const NMConfigCmdLineOptions *cli,
continue;
}
if (!read_config (keyfile, system_config_dir, filename, error)) {
if (!read_config (keyfile, FALSE, system_config_dir, filename, error)) {
g_key_file_free (keyfile);
return NULL;
}
@ -919,7 +945,7 @@ read_entire_config (const NMConfigCmdLineOptions *cli,
g_assert (o_config_main_file);
for (i = 0; i < confs->len; i++) {
if (!read_config (keyfile, config_dir, confs->pdata[i], error)) {
if (!read_config (keyfile, FALSE, config_dir, confs->pdata[i], error)) {
g_key_file_free (keyfile);
return NULL;
}
@ -1040,6 +1066,34 @@ _keyfile_serialize_section (GKeyFile *keyfile, const char *group)
return g_string_free (str, FALSE);
}
gboolean
nm_config_keyfile_has_global_dns_config (GKeyFile *keyfile, gboolean internal)
{
gs_strfreev char **groups = NULL;
guint g;
const char *prefix;
if (!keyfile)
return FALSE;
if (g_key_file_has_group (keyfile,
internal
? NM_CONFIG_KEYFILE_GROUP_GLOBAL_DNS
: NM_CONFIG_KEYFILE_GROUP_INTERN_GLOBAL_DNS))
return TRUE;
groups = g_key_file_get_groups (keyfile, NULL);
if (!groups)
return FALSE;
prefix = internal ? NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_GLOBAL_DNS_DOMAIN : NM_CONFIG_KEYFILE_GROUPPREFIX_GLOBAL_DNS_DOMAIN;
for (g = 0; groups[g]; g++) {
if (g_str_has_prefix (groups[g], prefix))
return TRUE;
}
return FALSE;
}
/**
* intern_config_read:
* @filename: the filename where to store the internal config
@ -1092,6 +1146,9 @@ intern_config_read (const char *filename,
const char *group = groups[g];
gboolean is_intern, is_atomic;
if (!strcmp (group, NM_CONFIG_KEYFILE_GROUP_CONFIG))
continue;
keys = g_key_file_get_keys (keyfile, group, NULL, NULL);
if (!keys)
continue;
@ -1190,7 +1247,7 @@ out:
* deletion of options from user configuration may cause the
* internal options to appear again.
*/
if (nm_config_keyfile_get_boolean (keyfile_conf, NM_CONFIG_KEYFILE_GROUP_GLOBAL_DNS, NM_CONFIG_KEYFILE_KEY_GLOBAL_DNS_ENABLE, FALSE)) {
if (nm_config_keyfile_has_global_dns_config (keyfile_conf, FALSE)) {
if (g_key_file_remove_group (keyfile_intern, NM_CONFIG_KEYFILE_GROUP_INTERN_GLOBAL_DNS, NULL))
needs_rewrite = TRUE;
for (g = 0; groups && groups[g]; g++) {
@ -1416,7 +1473,7 @@ intern_config_write (const char *filename,
/************************************************************************/
GSList *
nm_config_get_device_match_spec (const GKeyFile *keyfile, const char *group, const char *key, gboolean *out_has_key)
nm_config_get_match_spec (const GKeyFile *keyfile, const char *group, const char *key, gboolean *out_has_key)
{
gs_free char *value = NULL;
@ -1468,8 +1525,6 @@ nm_config_set_global_dns (NMConfig *self, NMGlobalDnsConfig *global_dns, GError
goto done;
/* Set new values */
g_key_file_set_string (keyfile, NM_CONFIG_KEYFILE_GROUP_INTERN_GLOBAL_DNS, NM_CONFIG_KEYFILE_KEY_GLOBAL_DNS_ENABLE, "yes");
nm_config_keyfile_set_string_list (keyfile, NM_CONFIG_KEYFILE_GROUP_INTERN_GLOBAL_DNS,
"searches", nm_global_dns_config_get_searches (global_dns),
-1);

View file

@ -56,13 +56,14 @@ G_BEGIN_DECLS
#define NM_CONFIG_KEYFILE_GROUP_LOGGING "logging"
#define NM_CONFIG_KEYFILE_GROUP_CONNECTIVITY "connectivity"
#define NM_CONFIG_KEYFILE_GROUP_GLOBAL_DNS "global-dns"
#define NM_CONFIG_KEYFILE_GROUP_CONFIG ".config"
#define NM_CONFIG_KEYFILE_GROUP_KEYFILE "keyfile"
#define NM_CONFIG_KEYFILE_GROUP_IFUPDOWN "ifupdown"
#define NM_CONFIG_KEYFILE_GROUP_IFNET "ifnet"
#define NM_CONFIG_KEYFILE_KEY_LOGGING_BACKEND "backend"
#define NM_CONFIG_KEYFILE_KEY_GLOBAL_DNS_ENABLE "enable"
#define NM_CONFIG_KEYFILE_KEY_CONFIG_ENABLE "enable"
#define NM_CONFIG_KEYFILE_KEY_ATOMIC_SECTION_WAS ".was"
#define NM_CONFIG_KEYFILE_KEY_IFNET_AUTO_REFRESH "auto_refresh"
#define NM_CONFIG_KEYFILE_KEY_IFNET_MANAGED "managed"
@ -143,12 +144,18 @@ void nm_config_keyfile_set_string_list (GKeyFile *keyfile,
const char *key,
const char *const* strv,
gssize len);
GSList *nm_config_get_device_match_spec (const GKeyFile *keyfile, const char *group, const char *key, gboolean *out_has_key);
gboolean nm_config_keyfile_has_global_dns_config (GKeyFile *keyfile, gboolean internal);
GSList *nm_config_get_match_spec (const GKeyFile *keyfile, const char *group, const char *key, gboolean *out_has_key);
void _nm_config_sort_groups (char **groups, gsize ngroups);
gboolean nm_config_set_global_dns (NMConfig *self, NMGlobalDnsConfig *global_dns, GError **error);
/* internal defines ... */
extern guint _nm_config_match_nm_version;
extern char *_nm_config_match_env;
G_END_DECLS
#endif /* __NETWORKMANAGER_CONFIG_H__ */

View file

@ -30,8 +30,8 @@ TESTS = test-config
EXTRA_DIST = \
NetworkManager.conf \
bad.conf \
global-dns-disabled.conf \
global-dns-invalid.conf \
conf.d/00-overrides.conf \
conf.d/10-more.conf \
conf.d/20-config-enable-1.conf \
conf.d/90-last.conf

View file

@ -0,0 +1,5 @@
[.config]
enable=nm-version:1.5.32,env:test-match-env-1
[test-group-config-enable-1]
key1=enabled

View file

@ -1,8 +0,0 @@
[global-dns]
enable=no
searches=foo.com
options=timeout:5
[global-dns-domain-*]
servers=1.2.3.4
options=myoption

View file

@ -1,7 +1,6 @@
# Invalid configuration, since there isn't a default domain section
[global-dns]
enable=yes
searches=foo.com
options=timeout:5

View file

@ -305,13 +305,6 @@ test_config_global_dns (void)
g_object_unref (config);
/* Check that a file without "enable=yes" gives a NULL configuration */
config = setup_config (NULL, SRCDIR "/global-dns-disabled.conf", "", NULL,
"/no/such/dir", "", NULL);
dns = nm_config_data_get_global_dns_config (nm_config_get_data_orig (config));
g_assert (!dns);
g_object_unref (config);
/* Check that a file without a default domain section gives a NULL configuration */
config = setup_config (NULL, SRCDIR "/global-dns-invalid.conf", "", NULL,
"/no/such/dir", "", NULL);
@ -905,6 +898,40 @@ test_config_signal (void)
/*****************************************************************************/
static void
test_config_enable (void)
{
gs_unref_object NMConfig *config = NULL;
guint match_nm_version = _nm_config_match_nm_version;
char *match_env = g_strdup (_nm_config_match_env);
g_clear_pointer (&_nm_config_match_env, g_free);
_nm_config_match_env = g_strdup ("something-else");
_nm_config_match_nm_version = nm_encode_version (1, 3, 4);
config = setup_config (NULL, SRCDIR "/NetworkManager.conf", "", NULL, SRCDIR "/conf.d", "", NULL);
assert_config_value (nm_config_get_data_orig (config), "test-group-config-enable-1", "key1", NULL);
g_clear_object (&config);
_nm_config_match_nm_version = nm_encode_version (1, 5, 32);
config = setup_config (NULL, SRCDIR "/NetworkManager.conf", "", NULL, SRCDIR "/conf.d", "", NULL);
assert_config_value (nm_config_get_data_orig (config), "test-group-config-enable-1", "key1", "enabled");
g_clear_object (&config);
_nm_config_match_nm_version = nm_encode_version (1, 5, 3);
g_clear_pointer (&_nm_config_match_env, g_free);
_nm_config_match_env = g_strdup ("test-match-env-1");
config = setup_config (NULL, SRCDIR "/NetworkManager.conf", "", NULL, SRCDIR "/conf.d", "", NULL);
assert_config_value (nm_config_get_data_orig (config), "test-group-config-enable-1", "key1", "enabled");
g_clear_object (&config);
_nm_config_match_nm_version = match_nm_version;
g_clear_pointer (&_nm_config_match_env, g_free);
_nm_config_match_env = match_env;
}
/*****************************************************************************/
NMTST_DEFINE ();
int
@ -933,6 +960,8 @@ main (int argc, char **argv)
g_test_add_func ("/config/signal", test_config_signal);
g_test_add_func ("/config/enable", test_config_enable);
/* This one has to come last, because it leaves its values in
* nm-config.c's global variables, and there's no way to reset
* those to NULL.

View file

@ -773,6 +773,148 @@ test_nm_match_spec_interface_name (void)
/*******************************************/
static void
_do_test_match_spec_match_config (const char *file, gint line, const char *spec_str, guint version, guint v_maj, guint v_min, guint v_mic, NMMatchSpecMatchType expected)
{
GSList *specs;
NMMatchSpecMatchType match_result;
guint c_maj, c_min, c_mic;
g_assert_cmpint (version, ==, nm_encode_version (v_maj, v_min, v_mic));
nm_decode_version (version, &c_maj, &c_min, &c_mic);
g_assert_cmpint (c_maj, ==, c_maj);
g_assert_cmpint (c_min, ==, c_min);
g_assert_cmpint (c_mic, ==, c_mic);
specs = nm_match_spec_split (spec_str);
match_result = nm_match_spec_match_config (specs, version, NULL);
if (expected != match_result)
g_error ("%s:%d: faild comparing \"%s\" with %u.%u.%u. Expected %d, but got %d", file, line, spec_str, v_maj, v_min, v_mic, (int) expected, (int) match_result);
if (g_slist_length (specs) == 1 && match_result != NM_MATCH_SPEC_NEG_MATCH) {
/* there is only one spec in the list... test that we match except: */
char *sss = g_strdup_printf ("except:%s", (char *) specs->data);
GSList *specs2 = g_slist_append (NULL, sss);
NMMatchSpecMatchType match_result2;
match_result2 = nm_match_spec_match_config (specs2, version, NULL);
if (match_result == NM_MATCH_SPEC_NO_MATCH)
g_assert_cmpint (match_result2, ==, NM_MATCH_SPEC_NO_MATCH);
else
g_assert_cmpint (match_result2, ==, NM_MATCH_SPEC_NEG_MATCH);
g_slist_free_full (specs2, g_free);
}
g_slist_free_full (specs, g_free);
}
#define do_test_match_spec_match_config(spec, v_maj, v_min, v_mic, expected) \
_do_test_match_spec_match_config (__FILE__, __LINE__, (""spec), NM_ENCODE_VERSION ((v_maj), (v_min), (v_mic)), (v_maj), (v_min), (v_mic), (expected))
static void
test_nm_match_spec_match_config (void)
{
do_test_match_spec_match_config ("", 1, 2, 3, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version:1.2.3", 1, 2, 2, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version:1.2.3", 1, 2, 3, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version:1.2.3", 1, 2, 4, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version:1.2", 1, 1, 2, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version:1.2", 1, 2, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version:1.2", 1, 2, 2, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version:1.2", 1, 2, 3, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version:1.2", 1, 2, 4, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version:1.2", 1, 3, 0, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2.3", 0, 2, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2.3", 1, 1, 1, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2.3", 1, 2, 2, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2.3", 1, 2, 3, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2.3", 1, 2, 5, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2.3", 1, 3, 0, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2.3", 1, 3, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2.3", 1, 4, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2", 0, 2, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2", 1, 1, 1, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2", 1, 2, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2", 1, 2, 3, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2", 1, 2, 5, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2", 1, 3, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2", 1, 3, 30, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2", 1, 4, 30, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1", 0, 2, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1", 1, 1, 1, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1", 1, 2, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1", 1, 2, 3, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1", 1, 2, 5, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1", 1, 3, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1", 1, 3, 30, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1", 1, 4, 30, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2.3", 0, 2, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2.3", 1, 1, 1, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2.3", 1, 2, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2.3", 1, 2, 1, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2.3", 1, 2, 2, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2.3", 1, 2, 3, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2.3", 1, 2, 5, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2.3", 1, 3, 0, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2.3", 1, 3, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2.3", 1, 4, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2", 0, 2, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2", 1, 1, 1, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2", 1, 2, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2", 1, 2, 3, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2", 1, 2, 5, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2", 1, 3, 0, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2", 1, 3, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2", 1, 4, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-max:1", 0, 2, 30, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1", 1, 1, 1, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1", 1, 2, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1", 1, 2, 3, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1", 1, 2, 5, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1", 1, 3, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1", 1, 3, 30, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1", 1, 4, 30, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1", 2, 4, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("except:nm-version:1.4.8", 1, 6, 0, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,except:nm-version:1.4.8", 1, 6, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 2, 0, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 2, 0, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 2, 15, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 2, 16, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 2, 17, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 2, 20, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 3, 0, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 4, 0, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 4, 5, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 4, 6, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 4, 7, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 4, 8, NM_MATCH_SPEC_NEG_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 4, 9, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 5, 0, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 6, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 6, 5, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 7, 7, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 8, 8, NM_MATCH_SPEC_MATCH);
}
/*******************************************/
NMTST_DEFINE ();
int
@ -796,6 +938,7 @@ main (int argc, char **argv)
g_test_add_func ("/general/connection-sort/autoconnect-priority", test_connection_sort_autoconnect_priority);
g_test_add_func ("/general/nm_match_spec_interface_name", test_nm_match_spec_interface_name);
g_test_add_func ("/general/nm_match_spec_match_config", test_nm_match_spec_match_config);
return g_test_run ();
}