370 lines
13 KiB
Diff
370 lines
13 KiB
Diff
From 9588c4633a07147875d933556212716779e32a36 Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Thu, 4 Jun 2015 15:57:42 +0200
|
|
Subject: [PATCH] core: detect route-metric when creating nm-generated-assumed
|
|
connection
|
|
|
|
When generating a connection to assume it, also record the route-metric.
|
|
Do that by looking at the metric of the (best) default-route.
|
|
|
|
This is especially important since d51975ed921a5876b76e081b8f3df4e2ca1f1ca9.
|
|
Now NM would also manage the default-route for assumed connections.
|
|
So the generated assumed connection would have a route metric based on
|
|
the device type, which might differ from the external configuration.
|
|
This caused NM to replace the externally configured default-route.
|
|
|
|
https://bugzilla.gnome.org/show_bug.cgi?id=750405
|
|
(cherry picked from commit bc75cd53a8c5ba525016bfddc1644be59a45ed41)
|
|
---
|
|
src/nm-ip4-config.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
|
|
src/nm-ip4-config.h | 1 +
|
|
src/nm-ip6-config.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
|
|
src/nm-ip6-config.h | 1 +
|
|
4 files changed, 90 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c
|
|
index db8c4b4..e5cb6c7 100644
|
|
--- a/src/nm-ip4-config.c
|
|
+++ b/src/nm-ip4-config.c
|
|
@@ -56,6 +56,7 @@ typedef struct {
|
|
GArray *wins;
|
|
guint32 mtu;
|
|
NMIPConfigSource mtu_source;
|
|
+ gint64 route_metric;
|
|
} NMIP4ConfigPrivate;
|
|
|
|
/* internal guint32 are assigned to gobject properties of type uint. Ensure, that uint is large enough */
|
|
@@ -218,6 +219,10 @@ nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf)
|
|
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.
|
|
*/
|
|
@@ -335,6 +340,7 @@ nm_ip4_config_commit (const NMIP4Config *config, int ifindex, gboolean routes_fu
|
|
void
|
|
nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIPConfig *setting, guint32 default_route_metric)
|
|
{
|
|
+ NMIP4ConfigPrivate *priv;
|
|
guint naddresses, nroutes, nnameservers, nsearches;
|
|
int i;
|
|
|
|
@@ -343,6 +349,8 @@ nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIPConfig *setting, gu
|
|
|
|
g_return_if_fail (NM_IS_SETTING_IP4_CONFIG (setting));
|
|
|
|
+ priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
+
|
|
g_object_freeze_notify (G_OBJECT (config));
|
|
|
|
naddresses = nm_setting_ip_config_get_num_addresses (setting);
|
|
@@ -362,6 +370,9 @@ nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIPConfig *setting, gu
|
|
nm_ip4_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);
|
|
@@ -430,6 +441,7 @@ nm_ip4_config_create_setting (const NMIP4Config *config)
|
|
guint naddresses, nroutes, nnameservers, nsearches;
|
|
const char *method = NULL;
|
|
int i;
|
|
+ gint64 route_metric;
|
|
|
|
s_ip4 = NM_SETTING_IP_CONFIG (nm_setting_ip4_config_new ());
|
|
|
|
@@ -445,6 +457,7 @@ nm_ip4_config_create_setting (const NMIP4Config *config)
|
|
nroutes = nm_ip4_config_get_num_routes (config);
|
|
nnameservers = nm_ip4_config_get_num_nameservers (config);
|
|
nsearches = nm_ip4_config_get_num_searches (config);
|
|
+ route_metric = nm_ip4_config_get_route_metric (config);
|
|
|
|
/* Addresses */
|
|
for (i = 0; i < naddresses; i++) {
|
|
@@ -480,7 +493,11 @@ nm_ip4_config_create_setting (const NMIP4Config *config)
|
|
/* Use 'disabled' if the method wasn't previously set */
|
|
if (!method)
|
|
method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
|
|
- g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, method, NULL);
|
|
+
|
|
+ g_object_set (s_ip4,
|
|
+ NM_SETTING_IP_CONFIG_METHOD, method,
|
|
+ NM_SETTING_IP_CONFIG_ROUTE_METRIC, (gint64) route_metric,
|
|
+ NULL);
|
|
|
|
/* Routes */
|
|
for (i = 0; i < nroutes; i++) {
|
|
@@ -523,11 +540,15 @@ nm_ip4_config_create_setting (const NMIP4Config *config)
|
|
void
|
|
nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src)
|
|
{
|
|
+ NMIP4ConfigPrivate *dst_priv, *src_priv;
|
|
guint32 i;
|
|
|
|
g_return_if_fail (src != NULL);
|
|
g_return_if_fail (dst != NULL);
|
|
|
|
+ dst_priv = NM_IP4_CONFIG_GET_PRIVATE (dst);
|
|
+ src_priv = NM_IP4_CONFIG_GET_PRIVATE (src);
|
|
+
|
|
g_object_freeze_notify (G_OBJECT (dst));
|
|
|
|
/* addresses */
|
|
@@ -546,6 +567,11 @@ nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src)
|
|
for (i = 0; i < nm_ip4_config_get_num_routes (src); i++)
|
|
nm_ip4_config_add_route (dst, nm_ip4_config_get_route (src, i));
|
|
|
|
+ if (dst_priv->route_metric == -1)
|
|
+ dst_priv->route_metric = src_priv->route_metric;
|
|
+ else
|
|
+ dst_priv->route_metric = MIN (dst_priv->route_metric, src_priv->route_metric);
|
|
+
|
|
/* domains */
|
|
for (i = 0; i < nm_ip4_config_get_num_domains (src); i++)
|
|
nm_ip4_config_add_domain (dst, nm_ip4_config_get_domain (src, i));
|
|
@@ -727,6 +753,8 @@ nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src)
|
|
if (!nm_ip4_config_get_num_addresses (dst))
|
|
nm_ip4_config_set_gateway (dst, 0);
|
|
|
|
+ /* ignore route_metric */
|
|
+
|
|
/* routes */
|
|
for (i = 0; i < nm_ip4_config_get_num_routes (src); i++) {
|
|
idx = _routes_get_index (dst, nm_ip4_config_get_route (src, i));
|
|
@@ -796,6 +824,7 @@ nm_ip4_config_intersect (NMIP4Config *dst, const NMIP4Config *src)
|
|
i++;
|
|
}
|
|
|
|
+ /* ignore route_metric */
|
|
/* ignore nameservers */
|
|
|
|
/* default gateway */
|
|
@@ -872,6 +901,11 @@ nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *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_ip4_config_get_num_addresses (src);
|
|
are_equal = num == nm_ip4_config_get_num_addresses (dst);
|
|
@@ -1153,6 +1187,14 @@ nm_ip4_config_get_gateway (const NMIP4Config *config)
|
|
return priv->gateway;
|
|
}
|
|
|
|
+gint64
|
|
+nm_ip4_config_get_route_metric (const NMIP4Config *config)
|
|
+{
|
|
+ NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
+
|
|
+ return priv->route_metric;
|
|
+}
|
|
+
|
|
/******************************************************************/
|
|
|
|
void
|
|
@@ -1856,6 +1898,7 @@ nm_ip4_config_init (NMIP4Config *config)
|
|
priv->searches = g_ptr_array_new_with_free_func (g_free);
|
|
priv->nis = g_array_new (FALSE, TRUE, sizeof (guint32));
|
|
priv->wins = g_array_new (FALSE, TRUE, sizeof (guint32));
|
|
+ priv->route_metric = -1;
|
|
}
|
|
|
|
static void
|
|
diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h
|
|
index 4636752..ea8320d 100644
|
|
--- a/src/nm-ip4-config.h
|
|
+++ b/src/nm-ip4-config.h
|
|
@@ -81,6 +81,7 @@ void nm_ip4_config_set_never_default (NMIP4Config *config, gboolean never_defaul
|
|
gboolean nm_ip4_config_get_never_default (const NMIP4Config *config);
|
|
void nm_ip4_config_set_gateway (NMIP4Config *config, guint32 gateway);
|
|
guint32 nm_ip4_config_get_gateway (const NMIP4Config *config);
|
|
+gint64 nm_ip4_config_get_route_metric (const NMIP4Config *config);
|
|
|
|
/* Addresses */
|
|
void nm_ip4_config_reset_addresses (NMIP4Config *config);
|
|
diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c
|
|
index 48aeb64..a528bf1 100644
|
|
--- a/src/nm-ip6-config.c
|
|
+++ b/src/nm-ip6-config.c
|
|
@@ -50,6 +50,7 @@ typedef struct {
|
|
GPtrArray *domains;
|
|
GPtrArray *searches;
|
|
guint32 mss;
|
|
+ gint64 route_metric;
|
|
} NMIP6ConfigPrivate;
|
|
|
|
|
|
@@ -329,6 +330,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 +413,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 +423,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 +445,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 +511,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 +527,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 +567,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++) {
|
|
@@ -601,11 +618,15 @@ nm_ip6_config_create_setting (const NMIP6Config *config)
|
|
void
|
|
nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src)
|
|
{
|
|
+ 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 */
|
|
@@ -624,6 +645,11 @@ nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src)
|
|
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
|
|
+ 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));
|
|
@@ -776,6 +802,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 +852,7 @@ nm_ip6_config_intersect (NMIP6Config *dst, const NMIP6Config *src)
|
|
i++;
|
|
}
|
|
|
|
+ /* ignore route_metric */
|
|
/* ignore nameservers */
|
|
|
|
/* default gateway */
|
|
@@ -902,6 +931,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 +1146,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 +1714,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
|
|
diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h
|
|
index 66f1588..c7f3f51 100644
|
|
--- a/src/nm-ip6-config.h
|
|
+++ b/src/nm-ip6-config.h
|
|
@@ -81,6 +81,7 @@ void nm_ip6_config_set_never_default (NMIP6Config *config, gboolean never_defaul
|
|
gboolean nm_ip6_config_get_never_default (const NMIP6Config *config);
|
|
void nm_ip6_config_set_gateway (NMIP6Config *config, const struct in6_addr *);
|
|
const struct in6_addr *nm_ip6_config_get_gateway (const NMIP6Config *config);
|
|
+gint64 nm_ip6_config_get_route_metric (const NMIP6Config *config);
|
|
|
|
/* Addresses */
|
|
void nm_ip6_config_reset_addresses (NMIP6Config *config);
|
|
--
|
|
2.4.3
|
|
|