summary refs log tree commit diff
path: root/src/nm-ip6-config.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2015-08-28 01:13:48 +0200
committerMichael Biebl <biebl@debian.org>2015-08-28 01:13:48 +0200
commit81836c2d44802b4cca833d7775dd627e0797a7e2 (patch)
tree91154e6cefc0465306603f51ec0010d9963bbea4 /src/nm-ip6-config.c
parent50a58f0fabd8a34c1b6108a107e08abe3c1ccd24 (diff)
Imported Upstream version 1.0.6 upstream/1.0.6
Diffstat (limited to 'src/nm-ip6-config.c')
-rw-r--r--src/nm-ip6-config.c66
1 files changed, 58 insertions, 8 deletions
diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c
index 48aeb64a..9647268d 100644
--- a/src/nm-ip6-config.c
+++ b/src/nm-ip6-config.c
@@ -34,6 +34,7 @@
 #include "nm-ip6-config-glue.h"
 #include "nm-route-manager.h"
 #include "NetworkManagerUtils.h"
+#include "nm-macros-internal.h"
 
 G_DEFINE_TYPE (NMIP6Config, nm_ip6_config, G_TYPE_OBJECT)
 
@@ -50,6 +51,7 @@ typedef struct {
 	GPtrArray *domains;
 	GPtrArray *searches;
 	guint32 mss;
+	gint64 route_metric;
 } NMIP6ConfigPrivate;
 
 
@@ -329,6 +331,10 @@ nm_ip6_config_capture (int ifindex, gboolean capture_resolv_conf, NMSettingIP6Co
 		i++;
 	}
 
+	/* we detect the route metric based on the default route. All non-default
+	 * routes have their route metrics explicitly set. */
+	priv->route_metric = has_gateway ? (gint64) lowest_metric : (gint64) -1;
+
 	/* If there is a host route to the gateway, ignore that route.  It is
 	 * automatically added by NetworkManager when needed.
 	 */
@@ -408,6 +414,7 @@ nm_ip6_config_commit (const NMIP6Config *config, int ifindex, gboolean routes_fu
 void
 nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIPConfig *setting, guint32 default_route_metric)
 {
+	NMIP6ConfigPrivate *priv;
 	guint naddresses, nroutes, nnameservers, nsearches;
 	const char *gateway_str;
 	int i;
@@ -417,6 +424,8 @@ nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIPConfig *setting, gu
 
 	g_return_if_fail (NM_IS_SETTING_IP6_CONFIG (setting));
 
+	priv = NM_IP6_CONFIG_GET_PRIVATE (config);
+
 	naddresses = nm_setting_ip_config_get_num_addresses (setting);
 	nroutes = nm_setting_ip_config_get_num_routes (setting);
 	nnameservers = nm_setting_ip_config_get_num_dns (setting);
@@ -437,6 +446,9 @@ nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIPConfig *setting, gu
 		nm_ip6_config_set_gateway (config, &gateway);
 	}
 
+	if (priv->route_metric  == -1)
+		priv->route_metric = nm_setting_ip_config_get_route_metric (setting);
+
 	/* Addresses */
 	for (i = 0; i < naddresses; i++) {
 		NMIPAddress *s_addr = nm_setting_ip_config_get_address (setting, i);
@@ -500,6 +512,7 @@ nm_ip6_config_create_setting (const NMIP6Config *config)
 	guint naddresses, nroutes, nnameservers, nsearches;
 	const char *method = NULL;
 	int i;
+	gint64 route_metric;
 
 	s_ip6 = NM_SETTING_IP_CONFIG (nm_setting_ip6_config_new ());
 
@@ -515,6 +528,7 @@ nm_ip6_config_create_setting (const NMIP6Config *config)
 	nroutes = nm_ip6_config_get_num_routes (config);
 	nnameservers = nm_ip6_config_get_num_nameservers (config);
 	nsearches = nm_ip6_config_get_num_searches (config);
+	route_metric = nm_ip6_config_get_route_metric (config);
 
 	/* Addresses */
 	for (i = 0; i < naddresses; i++) {
@@ -554,7 +568,11 @@ nm_ip6_config_create_setting (const NMIP6Config *config)
 	/* Use 'ignore' if the method wasn't previously set */
 	if (!method)
 		method = NM_SETTING_IP6_CONFIG_METHOD_IGNORE;
-	g_object_set (s_ip6, NM_SETTING_IP_CONFIG_METHOD, method, NULL);
+
+	g_object_set (s_ip6,
+	              NM_SETTING_IP_CONFIG_METHOD, method,
+	              NM_SETTING_IP_CONFIG_ROUTE_METRIC, (gint64) route_metric,
+	              NULL);
 
 	/* Routes */
 	for (i = 0; i < nroutes; i++) {
@@ -599,13 +617,17 @@ nm_ip6_config_create_setting (const NMIP6Config *config)
 /******************************************************************/
 
 void
-nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src)
+nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src, NMIPConfigMergeFlags merge_flags)
 {
+	NMIP6ConfigPrivate *dst_priv, *src_priv;
 	guint32 i;
 
 	g_return_if_fail (src != NULL);
 	g_return_if_fail (dst != NULL);
 
+	dst_priv = NM_IP6_CONFIG_GET_PRIVATE (dst);
+	src_priv = NM_IP6_CONFIG_GET_PRIVATE (src);
+
 	g_object_freeze_notify (G_OBJECT (dst));
 
 	/* addresses */
@@ -621,16 +643,27 @@ nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src)
 		nm_ip6_config_set_gateway (dst, nm_ip6_config_get_gateway (src));
 
 	/* routes */
-	for (i = 0; i < nm_ip6_config_get_num_routes (src); i++)
-		nm_ip6_config_add_route (dst, nm_ip6_config_get_route (src, i));
+	if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_ROUTES)) {
+		for (i = 0; i < nm_ip6_config_get_num_routes (src); i++)
+			nm_ip6_config_add_route (dst, nm_ip6_config_get_route (src, i));
+	}
+
+	if (dst_priv->route_metric == -1)
+		dst_priv->route_metric = src_priv->route_metric;
+	else if (src_priv->route_metric != -1)
+		dst_priv->route_metric = MIN (dst_priv->route_metric, src_priv->route_metric);
 
 	/* domains */
-	for (i = 0; i < nm_ip6_config_get_num_domains (src); i++)
-		nm_ip6_config_add_domain (dst, nm_ip6_config_get_domain (src, i));
+	if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
+		for (i = 0; i < nm_ip6_config_get_num_domains (src); i++)
+			nm_ip6_config_add_domain (dst, nm_ip6_config_get_domain (src, i));
+	}
 
 	/* dns searches */
-	for (i = 0; i < nm_ip6_config_get_num_searches (src); i++)
-		nm_ip6_config_add_search (dst, nm_ip6_config_get_search (src, i));
+	if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
+		for (i = 0; i < nm_ip6_config_get_num_searches (src); i++)
+			nm_ip6_config_add_search (dst, nm_ip6_config_get_search (src, i));
+	}
 
 	if (nm_ip6_config_get_mss (src))
 		nm_ip6_config_set_mss (dst, nm_ip6_config_get_mss (src));
@@ -776,6 +809,8 @@ nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src)
 	if (!nm_ip6_config_get_num_addresses (dst))
 		nm_ip6_config_set_gateway (dst, NULL);
 
+	/* ignore route_metric */
+
 	/* routes */
 	for (i = 0; i < nm_ip6_config_get_num_routes (src); i++) {
 		idx = _routes_get_index (dst, nm_ip6_config_get_route (src, i));
@@ -824,6 +859,7 @@ nm_ip6_config_intersect (NMIP6Config *dst, const NMIP6Config *src)
 			i++;
 	}
 
+	/* ignore route_metric */
 	/* ignore nameservers */
 
 	/* default gateway */
@@ -902,6 +938,11 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev
 		has_relevant_changes = TRUE;
 	}
 
+	if (src_priv->route_metric != dst_priv->route_metric) {
+		dst_priv->route_metric = src_priv->route_metric;
+		has_minor_changes = TRUE;
+	}
+
 	/* addresses */
 	num = nm_ip6_config_get_num_addresses (src);
 	are_equal = num == nm_ip6_config_get_num_addresses (dst);
@@ -1112,6 +1153,14 @@ nm_ip6_config_get_gateway (const NMIP6Config *config)
 	return IN6_IS_ADDR_UNSPECIFIED (&priv->gateway) ? NULL : &priv->gateway;
 }
 
+gint64
+nm_ip6_config_get_route_metric (const NMIP6Config *config)
+{
+	NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config);
+
+	return priv->route_metric;
+}
+
 /******************************************************************/
 
 void
@@ -1672,6 +1721,7 @@ nm_ip6_config_init (NMIP6Config *config)
 	priv->nameservers = g_array_new (FALSE, TRUE, sizeof (struct in6_addr));
 	priv->domains = g_ptr_array_new_with_free_func (g_free);
 	priv->searches = g_ptr_array_new_with_free_func (g_free);
+	priv->route_metric = -1;
 }
 
 static void