summary refs log tree commit diff
path: root/src/NetworkManagerUtils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/NetworkManagerUtils.c')
-rw-r--r--src/NetworkManagerUtils.c133
1 files changed, 99 insertions, 34 deletions
diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c
index ecb1d8ae..596c5bb3 100644
--- a/src/NetworkManagerUtils.c
+++ b/src/NetworkManagerUtils.c
@@ -175,37 +175,78 @@ nm_utils_get_ip_config_method (NMConnection *connection,
 	if (ip_setting_type == NM_TYPE_SETTING_IP4_CONFIG) {
 		g_return_val_if_fail (s_con != NULL, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
 
-		if (nm_setting_connection_get_master (s_con))
+		s_ip4 = nm_connection_get_setting_ip4_config (connection);
+		if (!s_ip4)
 			return NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
-		else {
-			s_ip4 = nm_connection_get_setting_ip4_config (connection);
-			if (!s_ip4)
-				return NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
-			method = nm_setting_ip_config_get_method (s_ip4);
-			g_return_val_if_fail (method != NULL, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
-
-			return method;
-		}
+		method = nm_setting_ip_config_get_method (s_ip4);
+		g_return_val_if_fail (method != NULL, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
+
+		return method;
 
 	} else if (ip_setting_type == NM_TYPE_SETTING_IP6_CONFIG) {
 		g_return_val_if_fail (s_con != NULL, NM_SETTING_IP6_CONFIG_METHOD_AUTO);
 
-		if (nm_setting_connection_get_master (s_con))
+		s_ip6 = nm_connection_get_setting_ip6_config (connection);
+		if (!s_ip6)
 			return NM_SETTING_IP6_CONFIG_METHOD_IGNORE;
-		else {
-			s_ip6 = nm_connection_get_setting_ip6_config (connection);
-			if (!s_ip6)
-				return NM_SETTING_IP6_CONFIG_METHOD_IGNORE;
-			method = nm_setting_ip_config_get_method (s_ip6);
-			g_return_val_if_fail (method != NULL, NM_SETTING_IP6_CONFIG_METHOD_AUTO);
-
-			return method;
-		}
+		method = nm_setting_ip_config_get_method (s_ip6);
+		g_return_val_if_fail (method != NULL, NM_SETTING_IP6_CONFIG_METHOD_AUTO);
+
+		return method;
 
 	} else
 		g_assert_not_reached ();
 }
 
+gboolean
+nm_utils_connection_has_default_route (NMConnection *connection,
+                                       int addr_family,
+                                       gboolean *out_is_never_default)
+{
+	const char *method;
+	NMSettingIPConfig *s_ip;
+	gboolean is_never_default = FALSE;
+	gboolean has_default_route = FALSE;
+
+	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
+	g_return_val_if_fail (NM_IN_SET (addr_family, AF_INET, AF_INET6), FALSE);
+
+	if (!connection)
+		goto out;
+
+	if (addr_family == AF_INET)
+		s_ip = nm_connection_get_setting_ip4_config (connection);
+	else
+		s_ip = nm_connection_get_setting_ip6_config (connection);
+	if (!s_ip)
+		goto out;
+	if (nm_setting_ip_config_get_never_default (s_ip)) {
+		is_never_default = TRUE;
+		goto out;
+	}
+
+	if (addr_family == AF_INET) {
+		method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG);
+		if (NM_IN_STRSET (method, NULL,
+		                          NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
+		                          NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL))
+			goto out;
+	} else {
+		method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG);
+		if (NM_IN_STRSET (method, NULL,
+		                          NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+		                          NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL))
+			goto out;
+	}
+
+	has_default_route = TRUE;
+out:
+	NM_SET_OUT (out_is_never_default, is_never_default);
+	return has_default_route;
+}
+
+/*****************************************************************************/
+
 void
 nm_utils_complete_generic (NMPlatform *platform,
                            NMConnection *connection,
@@ -250,7 +291,7 @@ nm_utils_complete_generic (NMPlatform *platform,
 	}
 
 	/* Normalize */
-	parameters = g_hash_table_new (g_str_hash, g_str_equal);
+	parameters = g_hash_table_new (nm_str_hash, g_str_equal);
 	g_hash_table_insert (parameters, NM_CONNECTION_NORMALIZE_PARAM_IP6_CONFIG_METHOD,
 	                     default_enable_ipv6 ? NM_SETTING_IP6_CONFIG_METHOD_AUTO : NM_SETTING_IP6_CONFIG_METHOD_IGNORE);
 	nm_connection_normalize (connection, parameters, NULL, NULL);
@@ -392,12 +433,14 @@ check_ip_routes (NMConnection *orig,
                  gint64 default_metric,
                  gboolean v4)
 {
-	gs_free NMIPRoute **routes1 = NULL, **routes2 = NULL;
+	gs_free NMIPRoute **routes1 = NULL;
+	NMIPRoute **routes2;
 	NMSettingIPConfig *s_ip1, *s_ip2;
 	gint64 m;
 	const char *s_name;
 	GHashTable *props;
-	guint i, num;
+	guint i, i1, i2, num1, num2;
+	const guint8 PLEN = v4 ? 32 : 128;
 
 	s_name = v4 ? NM_SETTING_IP4_CONFIG_SETTING_NAME :
 	              NM_SETTING_IP6_CONFIG_SETTING_NAME;
@@ -414,27 +457,49 @@ check_ip_routes (NMConnection *orig,
 	if (!s_ip1 || !s_ip2)
 		return FALSE;
 
-	num = nm_setting_ip_config_get_num_routes (s_ip1);
-	if (num != nm_setting_ip_config_get_num_routes (s_ip2))
-		return FALSE;
+	num1 = nm_setting_ip_config_get_num_routes (s_ip1);
+	num2 = nm_setting_ip_config_get_num_routes (s_ip2);
 
-	routes1 = g_new (NMIPRoute *, num);
-	routes2 = g_new (NMIPRoute *, num);
+	routes1 = g_new (NMIPRoute *, (gsize) num1 + num2);
+	routes2 = &routes1[num1];
 
-	for (i = 0; i < num; i++) {
+	for (i = 0; i < num1; i++)
 		routes1[i] = nm_setting_ip_config_get_route (s_ip1, i);
+	for (i = 0; i < num2; i++)
 		routes2[i] = nm_setting_ip_config_get_route (s_ip2, i);
-	}
 
 	m = nm_setting_ip_config_get_route_metric (s_ip2);
 	if (m != -1)
 		default_metric = m;
 
-	g_qsort_with_data (routes1, num, sizeof (NMIPRoute *), route_ptr_compare, &default_metric);
-	g_qsort_with_data (routes2, num, sizeof (NMIPRoute *), route_ptr_compare, &default_metric);
+	g_qsort_with_data (routes1, num1, sizeof (NMIPRoute *), route_ptr_compare, &default_metric);
+	g_qsort_with_data (routes2, num2, sizeof (NMIPRoute *), route_ptr_compare, &default_metric);
+
+	for (i1 = 0, i2 = 0; i2 < num2; i1++) {
+		if (i1 >= num1)
+			return FALSE;
+		if (route_compare (routes1[i1], routes2[i2], default_metric) == 0) {
+			i2++;
+			continue;
+		}
+
+		/* if @orig (@routes1) contains /32 routes that are missing in @candidate,
+		 * we accept that.
+		 *
+		 * A /32 may have been added automatically, as a direct-route to the gateway.
+		 * The generated connection (@orig) would contain that route, so we shall ignore
+		 * it.
+		 *
+		 * Likeweise for /128 for IPv6. */
+		if (nm_ip_route_get_prefix (routes1[i1]) == PLEN)
+			continue;
+
+		return FALSE;
+	}
 
-	for (i = 0; i < num; i++) {
-		if (route_compare (routes1[i], routes2[i], default_metric))
+	/* check that @orig has no left-over (except host routes that we ignore). */
+	for (; i1 < num1; i1++) {
+		if (nm_ip_route_get_prefix (routes1[i1]) != PLEN)
 			return FALSE;
 	}