summary refs log tree commit diff
path: root/libnm-core
diff options
context:
space:
mode:
Diffstat (limited to 'libnm-core')
-rw-r--r--libnm-core/Makefile.in1
-rw-r--r--libnm-core/nm-connection.c29
-rw-r--r--libnm-core/nm-core-enum-types.c1
-rw-r--r--libnm-core/nm-errors.h2
-rw-r--r--libnm-core/nm-setting-ip-config.c62
-rw-r--r--libnm-core/nm-setting-ip-config.h4
-rw-r--r--libnm-core/nm-setting-ip4-config.c12
-rw-r--r--libnm-core/nm-setting-ip6-config.c12
-rw-r--r--libnm-core/nm-setting.c2
-rw-r--r--libnm-core/nm-utils.c2
-rw-r--r--libnm-core/nm-version.h14
-rw-r--r--libnm-core/nm-vpn-editor-plugin.c2
-rw-r--r--libnm-core/tests/Makefile.in1
-rw-r--r--libnm-core/tests/test-general.c97
14 files changed, 226 insertions, 15 deletions
diff --git a/libnm-core/Makefile.in b/libnm-core/Makefile.in
index 2bedf38b..bdef6648 100644
--- a/libnm-core/Makefile.in
+++ b/libnm-core/Makefile.in
@@ -458,6 +458,7 @@ NEWT_LIBS = @NEWT_LIBS@
 NM = @NM@
 NMEDIT = @NMEDIT@
 NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@
+NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@
 NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@
 NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@
 NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c
index 7a0e1f6b..04385aae 100644
--- a/libnm-core/nm-connection.c
+++ b/libnm-core/nm-connection.c
@@ -724,6 +724,7 @@ _normalize_ip_config (NMConnection *self, GHashTable *parameters)
 	const char *default_ip6_method = NULL;
 	NMSettingIPConfig *s_ip4, *s_ip6;
 	NMSetting *setting;
+	gboolean changed = FALSE;
 
 	if (parameters)
 		default_ip6_method = g_hash_table_lookup (parameters, NM_CONNECTION_NORMALIZE_PARAM_IP6_CONFIG_METHOD);
@@ -756,6 +757,19 @@ _normalize_ip_config (NMConnection *self, GHashTable *parameters)
 			              NM_SETTING_IP_CONFIG_METHOD, default_ip4_method,
 			              NULL);
 			nm_connection_add_setting (self, setting);
+		} else {
+			if (   nm_setting_ip_config_get_gateway (s_ip4)
+			    && nm_setting_ip_config_get_never_default (s_ip4)) {
+				g_object_set (s_ip4, NM_SETTING_IP_CONFIG_GATEWAY, NULL, NULL);
+				changed = TRUE;
+			}
+
+			if (   nm_streq0 (nm_setting_ip_config_get_method (s_ip4),
+			                  NM_SETTING_IP4_CONFIG_METHOD_DISABLED)
+			    && !nm_setting_ip_config_get_may_fail (s_ip4)) {
+				g_object_set (s_ip4, NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, NULL);
+				changed = TRUE;
+			}
 		}
 		if (!s_ip6) {
 			setting = nm_setting_ip6_config_new ();
@@ -765,8 +779,21 @@ _normalize_ip_config (NMConnection *self, GHashTable *parameters)
 			              NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
 			              NULL);
 			nm_connection_add_setting (self, setting);
+		} else {
+			if (   nm_setting_ip_config_get_gateway (s_ip6)
+			    && nm_setting_ip_config_get_never_default (s_ip6)) {
+				g_object_set (s_ip6, NM_SETTING_IP_CONFIG_GATEWAY, NULL, NULL);
+				changed = TRUE;
+			}
+
+			if (   nm_streq0 (nm_setting_ip_config_get_method (s_ip6),
+			                  NM_SETTING_IP6_CONFIG_METHOD_IGNORE)
+			    && !nm_setting_ip_config_get_may_fail (s_ip6)) {
+				g_object_set (s_ip6, NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, NULL);
+				changed = TRUE;
+			}
 		}
-		return !s_ip4 || !s_ip6;
+		return !s_ip4 || !s_ip6 || changed;
 	}
 }
 
diff --git a/libnm-core/nm-core-enum-types.c b/libnm-core/nm-core-enum-types.c
index 83f5e889..cd26f02e 100644
--- a/libnm-core/nm-core-enum-types.c
+++ b/libnm-core/nm-core-enum-types.c
@@ -678,6 +678,7 @@ nm_manager_error_get_type (void)
         { NM_MANAGER_ERROR_ALREADY_ENABLED_OR_DISABLED, "NM_MANAGER_ERROR_ALREADY_ENABLED_OR_DISABLED", "AlreadyEnabledOrDisabled" },
         { NM_MANAGER_ERROR_UNKNOWN_LOG_LEVEL, "NM_MANAGER_ERROR_UNKNOWN_LOG_LEVEL", "UnknownLogLevel" },
         { NM_MANAGER_ERROR_UNKNOWN_LOG_DOMAIN, "NM_MANAGER_ERROR_UNKNOWN_LOG_DOMAIN", "UnknownLogDomain" },
+        { NM_MANAGER_ERROR_INVALID_ARGUMENTS, "NM_MANAGER_ERROR_INVALID_ARGUMENTS", "InvalidArguments" },
         { 0, NULL, NULL }
       };
       GType g_define_type_id =
diff --git a/libnm-core/nm-errors.h b/libnm-core/nm-errors.h
index f5e08f9a..2a572f4e 100644
--- a/libnm-core/nm-errors.h
+++ b/libnm-core/nm-errors.h
@@ -185,6 +185,7 @@ GQuark nm_device_error_quark (void);
  *   enabled/disabled.
  * @NM_MANAGER_ERROR_UNKNOWN_LOG_LEVEL: Unknown log level in SetLogging
  * @NM_MANAGER_ERROR_UNKNOWN_LOG_DOMAIN: Unknown log domain in SetLogging
+ * @NM_MANAGER_ERROR_INVALID_ARGUMENTS: Invalid arguments for D-Bus request
  *
  * Errors related to the main "network management" interface of NetworkManager.
  * These may be returned from #NMClient methods that invoke D-Bus operations on
@@ -204,6 +205,7 @@ typedef enum {
 	NM_MANAGER_ERROR_ALREADY_ENABLED_OR_DISABLED, /*< nick=AlreadyEnabledOrDisabled >*/
 	NM_MANAGER_ERROR_UNKNOWN_LOG_LEVEL,           /*< nick=UnknownLogLevel >*/
 	NM_MANAGER_ERROR_UNKNOWN_LOG_DOMAIN,          /*< nick=UnknownLogDomain >*/
+	NM_MANAGER_ERROR_INVALID_ARGUMENTS,           /*< nick=InvalidArguments >*/
 } NMManagerError;
 
 GQuark nm_manager_error_quark (void);
diff --git a/libnm-core/nm-setting-ip-config.c b/libnm-core/nm-setting-ip-config.c
index 3e7f93b0..bdcbc23b 100644
--- a/libnm-core/nm-setting-ip-config.c
+++ b/libnm-core/nm-setting-ip-config.c
@@ -1120,6 +1120,7 @@ typedef struct {
 	GPtrArray *dns;        /* array of IP address strings */
 	GPtrArray *dns_search; /* array of domain name strings */
 	GPtrArray *dns_options;/* array of DNS options */
+	gint dns_priority;
 	GPtrArray *addresses;  /* array of NMIPAddress */
 	GPtrArray *routes;     /* array of NMIPRoute */
 	gint64 route_metric;
@@ -1140,6 +1141,7 @@ enum {
 	PROP_DNS,
 	PROP_DNS_SEARCH,
 	PROP_DNS_OPTIONS,
+	PROP_DNS_PRIORITY,
 	PROP_ADDRESSES,
 	PROP_GATEWAY,
 	PROP_ROUTES,
@@ -1684,6 +1686,22 @@ nm_setting_ip_config_clear_dns_options (NMSettingIPConfig *setting, gboolean is_
 }
 
 /**
+ * nm_setting_ip_config_get_dns_priority:
+ * @setting: the #NMSettingIPConfig
+ *
+ * Returns: the priority of DNS servers
+ *
+ * Since: 1.2.4
+ **/
+gint
+nm_setting_ip_config_get_dns_priority (NMSettingIPConfig *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), 0);
+
+	return NM_SETTING_IP_CONFIG_GET_PRIVATE (setting)->dns_priority;
+}
+
+/**
  * nm_setting_ip_config_get_num_addresses:
  * @setting: the #NMSettingIPConfig
  *
@@ -2274,6 +2292,16 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 		}
 	}
 
+	if (priv->gateway && priv->never_default) {
+		g_set_error (error,
+		             NM_CONNECTION_ERROR,
+		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		             _("a gateway is incompatible with '%s'"),
+		             NM_SETTING_IP_CONFIG_NEVER_DEFAULT);
+		g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), NM_SETTING_IP_CONFIG_GATEWAY);
+		return NM_SETTING_VERIFY_NORMALIZABLE_ERROR;
+	}
+
 	return TRUE;
 }
 
@@ -2352,6 +2380,9 @@ set_property (GObject *object, guint prop_id,
 			}
 		}
 		break;
+	case PROP_DNS_PRIORITY:
+		priv->dns_priority = g_value_get_int (value);
+		break;
 	case PROP_ADDRESSES:
 		g_ptr_array_unref (priv->addresses);
 		priv->addresses = _nm_utils_copy_array (g_value_get_boxed (value),
@@ -2424,6 +2455,9 @@ get_property (GObject *object, guint prop_id,
 	case PROP_DNS_OPTIONS:
 		g_value_take_boxed (value, priv->dns_options ? _nm_utils_ptrarray_to_strv (priv->dns_options) : NULL);
 		break;
+	case PROP_DNS_PRIORITY:
+		g_value_set_int (value, priv->dns_priority);
+		break;
 	case PROP_ADDRESSES:
 		g_value_take_boxed (value, _nm_utils_copy_array (priv->addresses,
 		                                                 (NMUtilsCopyFunc) nm_ip_address_dup,
@@ -2576,6 +2610,34 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *setting_class)
 		                     G_PARAM_STATIC_STRINGS));
 
 	/**
+	 * NMSettingIPConfig:dns-priority:
+	 *
+	 * DNS priority.
+	 *
+	 * The relative priority to be used when determining the order of DNS
+	 * servers in resolv.conf.  A lower value means that servers will be on top
+	 * of the file.  Zero selects the default value, which is 50 for VPNs and
+	 * 100 for other connections.  When multiple devices have configurations
+	 * with the same priority, the one with an active default route will be
+	 * preferred.  Note that when using dns=dnsmasq the order is meaningless
+	 * since dnsmasq forwards queries to all known servers at the same time.
+	 *
+	 * Negative values have the special effect of excluding other configurations
+	 * with a greater priority value; so in presence of at least a negative
+	 * priority, only DNS servers from configurations with the lowest priority
+	 * value will be used.
+	 *
+	 * Since: 1.2.4
+	 **/
+	g_object_class_install_property
+	    (object_class, PROP_DNS_PRIORITY,
+	     g_param_spec_int (NM_SETTING_IP_CONFIG_DNS_PRIORITY, "", "",
+	                       G_MININT32, G_MAXINT32, 0,
+	                       G_PARAM_READWRITE |
+	                       G_PARAM_CONSTRUCT |
+	                       G_PARAM_STATIC_STRINGS));
+
+	/**
 	 * NMSettingIPConfig:addresses:
 	 *
 	 * Array of IP addresses.
diff --git a/libnm-core/nm-setting-ip-config.h b/libnm-core/nm-setting-ip-config.h
index 79c7e639..a41c5466 100644
--- a/libnm-core/nm-setting-ip-config.h
+++ b/libnm-core/nm-setting-ip-config.h
@@ -136,6 +136,7 @@ void         nm_ip_route_set_attribute       (NMIPRoute   *route,
 #define NM_SETTING_IP_CONFIG_DNS                "dns"
 #define NM_SETTING_IP_CONFIG_DNS_SEARCH         "dns-search"
 #define NM_SETTING_IP_CONFIG_DNS_OPTIONS        "dns-options"
+#define NM_SETTING_IP_CONFIG_DNS_PRIORITY       "dns-priority"
 #define NM_SETTING_IP_CONFIG_ADDRESSES          "addresses"
 #define NM_SETTING_IP_CONFIG_GATEWAY            "gateway"
 #define NM_SETTING_IP_CONFIG_ROUTES             "routes"
@@ -219,6 +220,9 @@ gboolean      nm_setting_ip_config_remove_dns_option_by_value (NMSettingIPConfig
                                                                const char        *dns_option);
 void          nm_setting_ip_config_clear_dns_options          (NMSettingIPConfig *setting, gboolean is_set);
 
+NM_AVAILABLE_IN_1_2_4
+gint          nm_setting_ip_config_get_dns_priority (NMSettingIPConfig *setting);
+
 guint         nm_setting_ip_config_get_num_addresses          (NMSettingIPConfig *setting);
 NMIPAddress  *nm_setting_ip_config_get_address                (NMSettingIPConfig *setting,
                                                                int                idx);
diff --git a/libnm-core/nm-setting-ip4-config.c b/libnm-core/nm-setting-ip4-config.c
index 9b479a08..b3c8462e 100644
--- a/libnm-core/nm-setting-ip4-config.c
+++ b/libnm-core/nm-setting-ip4-config.c
@@ -225,6 +225,18 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 		return FALSE;
 	}
 
+	/* Failures from here on are NORMALIZABLE... */
+
+	if (   !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)
+	    && !nm_setting_ip_config_get_may_fail (s_ip)) {
+		g_set_error_literal (error,
+		                     NM_CONNECTION_ERROR,
+		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		                     _("property should be TRUE when method is set to disabled"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_MAY_FAIL);
+		return NM_SETTING_VERIFY_NORMALIZABLE;
+	}
+
 	return TRUE;
 }
 
diff --git a/libnm-core/nm-setting-ip6-config.c b/libnm-core/nm-setting-ip6-config.c
index 1f0b11fc..4d320e22 100644
--- a/libnm-core/nm-setting-ip6-config.c
+++ b/libnm-core/nm-setting-ip6-config.c
@@ -201,6 +201,18 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 		return FALSE;
 	}
 
+	/* Failures from here on are NORMALIZABLE... */
+
+	if (   !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)
+	    && !nm_setting_ip_config_get_may_fail (s_ip)) {
+		g_set_error_literal (error,
+		                     NM_CONNECTION_ERROR,
+		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		                     _("property should be TRUE when method is set to ignore"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_MAY_FAIL);
+		return NM_SETTING_VERIFY_NORMALIZABLE;
+	}
+
 	return TRUE;
 }
 
diff --git a/libnm-core/nm-setting.c b/libnm-core/nm-setting.c
index 0c41bd84..fcd8dff7 100644
--- a/libnm-core/nm-setting.c
+++ b/libnm-core/nm-setting.c
@@ -945,7 +945,7 @@ _nm_setting_new_from_dbus (GType setting_type,
 		}
 	}
 
-	return nm_unauto (&setting);
+	return g_steal_pointer (&setting);
 }
 
 /**
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c
index 70c268fa..1080d9ea 100644
--- a/libnm-core/nm-utils.c
+++ b/libnm-core/nm-utils.c
@@ -2399,8 +2399,8 @@ nm_utils_file_is_private_key (const char *filename, gboolean *out_encrypted)
 	const char *extensions[] = { ".der", ".pem", ".p12", ".key", NULL };
 
 	g_return_val_if_fail (filename != NULL, FALSE);
-	g_return_val_if_fail (out_encrypted == NULL || *out_encrypted == FALSE, FALSE);
 
+	NM_SET_OUT (out_encrypted, FALSE);
 	if (!file_has_extension (filename, extensions))
 		return FALSE;
 
diff --git a/libnm-core/nm-version.h b/libnm-core/nm-version.h
index d7f112bf..3b448819 100644
--- a/libnm-core/nm-version.h
+++ b/libnm-core/nm-version.h
@@ -90,18 +90,10 @@
 # define NM_AVAILABLE_IN_1_2
 #endif
 
-#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_4
-# define NM_DEPRECATED_IN_1_4           G_DEPRECATED
-# define NM_DEPRECATED_IN_1_4_FOR(f)    G_DEPRECATED_FOR(f)
+#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_2_4
+# define NM_AVAILABLE_IN_1_2_4          G_UNAVAILABLE(1.2,4)
 #else
-# define NM_DEPRECATED_IN_1_4
-# define NM_DEPRECATED_IN_1_4_FOR(f)
-#endif
-
-#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_4
-# define NM_AVAILABLE_IN_1_4            G_UNAVAILABLE(1,4)
-#else
-# define NM_AVAILABLE_IN_1_4
+# define NM_AVAILABLE_IN_1_2_4
 #endif
 
 #endif  /* NM_VERSION_H */
diff --git a/libnm-core/nm-vpn-editor-plugin.c b/libnm-core/nm-vpn-editor-plugin.c
index c4db3788..6c78c209 100644
--- a/libnm-core/nm-vpn-editor-plugin.c
+++ b/libnm-core/nm-vpn-editor-plugin.c
@@ -206,7 +206,7 @@ _nm_vpn_editor_plugin_load (const char *plugin_name,
 		return NULL;
 	}
 
-	return nm_unauto (&editor_plugin);
+	return g_steal_pointer (&editor_plugin);
 }
 
 /**
diff --git a/libnm-core/tests/Makefile.in b/libnm-core/tests/Makefile.in
index 356ce8df..1ffcabc7 100644
--- a/libnm-core/tests/Makefile.in
+++ b/libnm-core/tests/Makefile.in
@@ -586,6 +586,7 @@ NEWT_LIBS = @NEWT_LIBS@
 NM = @NM@
 NMEDIT = @NMEDIT@
 NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@
+NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@
 NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@
 NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@
 NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c
index dcbcb880..c71e2d26 100644
--- a/libnm-core/tests/test-general.c
+++ b/libnm-core/tests/test-general.c
@@ -1968,6 +1968,7 @@ test_connection_diff_a_only (void)
 			{ NM_SETTING_IP_CONFIG_NEVER_DEFAULT,      NM_SETTING_DIFF_RESULT_IN_A },
 			{ NM_SETTING_IP_CONFIG_MAY_FAIL,           NM_SETTING_DIFF_RESULT_IN_A },
 			{ NM_SETTING_IP_CONFIG_DAD_TIMEOUT,        NM_SETTING_DIFF_RESULT_IN_A },
+			{ NM_SETTING_IP_CONFIG_DNS_PRIORITY,       NM_SETTING_DIFF_RESULT_IN_A },
 			{ NULL, NM_SETTING_DIFF_RESULT_UNKNOWN },
 		} },
 	};
@@ -3717,6 +3718,100 @@ test_connection_normalize_infiniband_mtu (void)
 }
 
 static void
+test_connection_normalize_gateway_never_default (void)
+{
+	gs_unref_object NMConnection *con = NULL;
+	NMSettingIPConfig *s_ip4, *s_ip6;
+	NMIPAddress *addr;
+	gs_free_error GError *error = NULL;
+
+	con = nmtst_create_minimal_connection ("test1", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
+	nmtst_assert_connection_verifies_and_normalizable (con);
+
+	s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
+	g_object_set (G_OBJECT (s_ip4),
+	              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
+	              NULL);
+
+	addr = nm_ip_address_new (AF_INET, "1.1.1.1", 24, &error);
+	g_assert_no_error (error);
+	nm_setting_ip_config_add_address (s_ip4, addr);
+	nm_ip_address_unref (addr);
+
+	g_object_set (s_ip4,
+	              NM_SETTING_IP_CONFIG_GATEWAY, "1.1.1.254",
+	              NM_SETTING_IP_CONFIG_NEVER_DEFAULT, FALSE,
+	              NULL);
+
+	s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new ();
+	g_object_set (s_ip6,
+	              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO,
+	              NULL);
+
+	nm_connection_add_setting (con, (NMSetting *) s_ip4);
+	nm_connection_add_setting (con, (NMSetting *) s_ip6);
+
+	nmtst_assert_connection_verifies_without_normalization (con);
+	g_assert_cmpstr ("1.1.1.254", ==, nm_setting_ip_config_get_gateway (s_ip4));
+
+	/* Now set never-default to TRUE and check that the gateway is
+	 * removed during normalization
+	 * */
+	g_object_set (s_ip4,
+	              NM_SETTING_IP_CONFIG_NEVER_DEFAULT, TRUE,
+	              NULL);
+
+	nmtst_assert_connection_verifies_after_normalization (con,
+	                                                      NM_CONNECTION_ERROR,
+	                                                      NM_CONNECTION_ERROR_INVALID_PROPERTY);
+	nmtst_connection_normalize (con);
+	g_assert_cmpstr (NULL, ==, nm_setting_ip_config_get_gateway (s_ip4));
+}
+
+static void
+test_connection_normalize_may_fail (void)
+{
+	gs_unref_object NMConnection *con = NULL;
+	NMSettingIPConfig *s_ip4, *s_ip6;
+	gs_free_error GError *error = NULL;
+
+	con = nmtst_create_minimal_connection ("test2", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
+	nmtst_assert_connection_verifies_and_normalizable (con);
+
+	s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
+	g_object_set (G_OBJECT (s_ip4),
+	              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
+	              NM_SETTING_IP_CONFIG_MAY_FAIL, FALSE,
+	              NULL);
+
+	s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new ();
+	g_object_set (s_ip6,
+	              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO,
+	              NM_SETTING_IP_CONFIG_MAY_FAIL, FALSE,
+	              NULL);
+
+	nm_connection_add_setting (con, (NMSetting *) s_ip4);
+	nm_connection_add_setting (con, (NMSetting *) s_ip6);
+
+	nmtst_assert_connection_verifies_without_normalization (con);
+
+	/* Now set method=disabled/ignore and check that may-fail becomes TRUE
+	 * after normalization
+	 * */
+	g_object_set (s_ip4,
+	              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
+	              NULL);
+	g_object_set (s_ip6,
+	              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+	              NULL);
+
+	nmtst_assert_connection_verifies (con);
+	nmtst_connection_normalize (con);
+	g_assert_cmpint (nm_setting_ip_config_get_may_fail (s_ip4), ==, TRUE);
+	g_assert_cmpint (nm_setting_ip_config_get_may_fail (s_ip6), ==, TRUE);
+}
+
+static void
 test_setting_ip4_gateway (void)
 {
 	NMConnection *conn;
@@ -5010,6 +5105,8 @@ int main (int argc, char **argv)
 	g_test_add_func ("/core/general/test_connection_normalize_slave_type_1", test_connection_normalize_slave_type_1);
 	g_test_add_func ("/core/general/test_connection_normalize_slave_type_2", test_connection_normalize_slave_type_2);
 	g_test_add_func ("/core/general/test_connection_normalize_infiniband_mtu", test_connection_normalize_infiniband_mtu);
+	g_test_add_func ("/core/general/test_connection_normalize_gateway_never_default", test_connection_normalize_gateway_never_default);
+	g_test_add_func ("/core/general/test_connection_normalize_may_fail", test_connection_normalize_may_fail);
 
 	g_test_add_func ("/core/general/test_setting_connection_permissions_helpers", test_setting_connection_permissions_helpers);
 	g_test_add_func ("/core/general/test_setting_connection_permissions_property", test_setting_connection_permissions_property);