summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2015-10-05 18:31:19 +0200
committerThomas Haller <thaller@redhat.com>2015-10-05 18:32:42 +0200
commit7b446137f5fa61c9c19ebede709943003ffc84ea (patch)
tree21f9f49dab41d634e493c44ac2b96acab5625a42
parentd5bfe04dea290ce288b8fe141a20c66ad6588e55 (diff)
parentda0ded49279cce454c9aefeccd6943e7d58f3475 (diff)
downloadNetworkManager-7b446137f5fa61c9c19ebede709943003ffc84ea.tar.gz
config: merge branch 'th/config-enable-bgo755935'
https://bugzilla.gnome.org/show_bug.cgi?id=755935
-rw-r--r--include/nm-macros-internal.h15
-rw-r--r--man/NetworkManager.conf.xml.in97
-rw-r--r--src/NetworkManagerUtils.c152
-rw-r--r--src/NetworkManagerUtils.h6
-rw-r--r--src/nm-config-data.c16
-rw-r--r--src/nm-config.c127
-rw-r--r--src/nm-config.h11
-rw-r--r--src/tests/config/Makefile.am2
-rw-r--r--src/tests/config/conf.d/20-config-enable-1.conf5
-rw-r--r--src/tests/config/global-dns-disabled.conf8
-rw-r--r--src/tests/config/global-dns-invalid.conf1
-rw-r--r--src/tests/config/test-config.c43
-rw-r--r--src/tests/test-general.c143
13 files changed, 555 insertions, 71 deletions
diff --git a/include/nm-macros-internal.h b/include/nm-macros-internal.h
index b1d75e68ed..0bf25821ad 100644
--- a/include/nm-macros-internal.h
+++ b/include/nm-macros-internal.h
@@ -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__ */
diff --git a/man/NetworkManager.conf.xml.in b/man/NetworkManager.conf.xml.in
index a8b7f3a38d..f7bcd1a359 100644
--- a/man/NetworkManager.conf.xml.in
+++ b/man/NetworkManager.conf.xml.in
@@ -643,14 +643,6 @@ ipv6.ip6-privacy=1
<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>
<para>
@@ -703,6 +695,95 @@ ipv6.ip6-privacy=1
</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>
<variablelist>
diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c
index d5bb6c87f0..726ceb9b4a 100644
--- a/src/NetworkManagerUtils.c
+++ b/src/NetworkManagerUtils.c
@@ -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
diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h
index 3af93e5a03..bf90e741cd 100644
--- a/src/NetworkManagerUtils.h
+++ b/src/NetworkManagerUtils.h
@@ -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);
diff --git a/src/nm-config-data.c b/src/nm-config-data.c
index 02467c53d7..66b1da5916 100644
--- a/src/nm-config-data.c
+++ b/src/nm-config-data.c
@@ -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)
diff --git a/src/nm-config.c b/src/nm-config.c
index f2b72e3a57..f070ff9756 100644
--- a/src/nm-config.c
+++ b/src/nm-config.c
@@ -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);
diff --git a/src/nm-config.h b/src/nm-config.h
index 0e96c3e85c..eb195138bd 100644
--- a/src/nm-config.h
+++ b/src/nm-config.h
@@ -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__ */
diff --git a/src/tests/config/Makefile.am b/src/tests/config/Makefile.am
index 6ad9876f1f..80f923c46e 100644
--- a/src/tests/config/Makefile.am
+++ b/src/tests/config/Makefile.am
@@ -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
diff --git a/src/tests/config/conf.d/20-config-enable-1.conf b/src/tests/config/conf.d/20-config-enable-1.conf
new file mode 100644
index 0000000000..e6800f5236
--- /dev/null
+++ b/src/tests/config/conf.d/20-config-enable-1.conf
@@ -0,0 +1,5 @@
+[.config]
+enable=nm-version:1.5.32,env:test-match-env-1
+
+[test-group-config-enable-1]
+key1=enabled
diff --git a/src/tests/config/global-dns-disabled.conf b/src/tests/config/global-dns-disabled.conf
deleted file mode 100644
index 53ccd832e2..0000000000
--- a/src/tests/config/global-dns-disabled.conf
+++ /dev/null
@@ -1,8 +0,0 @@
-[global-dns]
-enable=no
-searches=foo.com
-options=timeout:5
-
-[global-dns-domain-*]
-servers=1.2.3.4
-options=myoption
diff --git a/src/tests/config/global-dns-invalid.conf b/src/tests/config/global-dns-invalid.conf
index 10ecc9b04c..e490f609cc 100644
--- a/src/tests/config/global-dns-invalid.conf
+++ b/src/tests/config/global-dns-invalid.conf
@@ -1,7 +1,6 @@
# Invalid configuration, since there isn't a default domain section
[global-dns]
-enable=yes
searches=foo.com
options=timeout:5
diff --git a/src/tests/config/test-config.c b/src/tests/config/test-config.c
index d3b2db6920..ed6f875740 100644
--- a/src/tests/config/test-config.c
+++ b/src/tests/config/test-config.c
@@ -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.
diff --git a/src/tests/test-general.c b/src/tests/test-general.c
index ba3d958fb3..3c2a33a97d 100644
--- a/src/tests/test-general.c
+++ b/src/tests/test-general.c
@@ -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 ();
}