summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2015-01-11 13:34:56 +0100
committerThomas Haller <thaller@redhat.com>2015-01-11 13:35:15 +0100
commit1bb1bfe6e7c8206ba5e157b15b1a4db81b24fd80 (patch)
tree9a9515997755876d3d9e75a93ff984ce9f07441c
parent207ab013a11bb4c730297a2eedf8600e33f33e23 (diff)
parent41e6c4fac1890e4302e4bfd1aa21be362cce51f2 (diff)
downloadNetworkManager-1bb1bfe6e7c8206ba5e157b15b1a4db81b24fd80.tar.gz
core: merge branch 'th/route-fixes-bgo741871'
https://bugzilla.gnome.org/show_bug.cgi?id=741871
-rw-r--r--libnm-core/nm-setting-ip4-config.c9
-rw-r--r--libnm-core/nm-setting-ip6-config.c9
-rw-r--r--src/platform/nm-linux-platform.c23
-rw-r--r--src/platform/tests/test-route.c7
-rw-r--r--src/settings/plugins/ifcfg-rh/reader.c4
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open2
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c13
-rw-r--r--src/settings/plugins/ifcfg-rh/writer.c14
8 files changed, 75 insertions, 6 deletions
diff --git a/libnm-core/nm-setting-ip4-config.c b/libnm-core/nm-setting-ip4-config.c
index 686192678a..81cc1f8889 100644
--- a/libnm-core/nm-setting-ip4-config.c
+++ b/libnm-core/nm-setting-ip4-config.c
@@ -571,6 +571,15 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *ip4_class)
* ---end---
*/
+ /* ---ifcfg-rh---
+ * property: route-metric
+ * variable: IPV4_ROUTE_METRIC(+)
+ * default: -1
+ * description: IPV4_ROUTE_METRIC is the default IPv4 metric for routes on this connection.
+ * If set to -1, a default metric based on the device type is used.
+ * ---end---
+ */
+
/**
* NMSettingIP4Config:dhcp-client-id:
*
diff --git a/libnm-core/nm-setting-ip6-config.c b/libnm-core/nm-setting-ip6-config.c
index f5d903340c..29ca551525 100644
--- a/libnm-core/nm-setting-ip6-config.c
+++ b/libnm-core/nm-setting-ip6-config.c
@@ -488,6 +488,15 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class)
* ---end---
*/
+ /* ---ifcfg-rh---
+ * property: route-metric
+ * variable: IPV6_ROUTE_METRIC(+)
+ * default: -1
+ * description: IPV6_ROUTE_METRIC is the default IPv6 metric for routes on this connection.
+ * If set to -1, a default metric based on the device type is used.
+ * ---end---
+ */
+
/**
* NMSettingIP6Config:ip6-privacy:
*
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index 5d1522ce98..0c35376cdb 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -3845,6 +3845,8 @@ ip6_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
struct in6_addr network, int plen, struct in6_addr gateway,
guint32 metric, guint32 mss)
{
+ metric = nm_utils_ip6_route_metric_normalize (metric);
+
return add_object (platform, build_rtnl_route (AF_INET6, ifindex, source, &network, plen, &gateway, NULL, metric, mss));
}
@@ -3863,7 +3865,7 @@ route_search_cache (struct nl_cache *cache, int family, int ifindex, const void
if (!_route_match (rtnlroute, family, ifindex, FALSE))
continue;
- if (metric && metric != rtnl_route_get_priority (rtnlroute))
+ if (metric != rtnl_route_get_priority (rtnlroute))
continue;
dst = rtnl_route_get_dst (rtnlroute);
@@ -3884,7 +3886,7 @@ route_search_cache (struct nl_cache *cache, int family, int ifindex, const void
}
static gboolean
-refresh_route (NMPlatform *platform, int family, int ifindex, const void *network, int plen, int metric)
+refresh_route (NMPlatform *platform, int family, int ifindex, const void *network, int plen, guint32 metric)
{
struct nl_cache *cache;
auto_nl_object struct rtnl_route *cached_object = NULL;
@@ -3910,6 +3912,19 @@ ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen
cache = choose_cache_by_type (platform, OBJECT_TYPE_IP4_ROUTE);
+ if (metric == 0) {
+ /* Deleting an IPv4 route with metric 0 does not only delete an exectly matching route.
+ * If no route with metric 0 exists, it might delete another route to the same destination.
+ * For nm_platform_ip4_route_delete() we don't want this semantic.
+ *
+ * Instead, re-fetch the route from kernel, and if that fails, there is nothing to do.
+ * On success, there is still a race that we might end up deleting the wrong route. */
+ if (!refresh_object (platform, (struct nl_object *) route, FALSE, NM_PLATFORM_REASON_INTERNAL)) {
+ rtnl_route_put ((struct rtnl_route *) route);
+ return TRUE;
+ }
+ }
+
/* when deleting an IPv4 route, several fields of the provided route must match.
* Lookup in the cache so that we hopefully get the right values. */
cached_object = (struct rtnl_route *) nl_cache_search (cache, route);
@@ -3962,6 +3977,8 @@ ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, in
{
struct in6_addr gateway = IN6ADDR_ANY_INIT;
+ metric = nm_utils_ip6_route_metric_normalize (metric);
+
return delete_object (platform, build_rtnl_route (AF_INET6, ifindex, NM_IP_CONFIG_SOURCE_UNKNOWN ,&network, plen, &gateway, NULL, metric, 0), FALSE) &&
refresh_route (platform, AF_INET6, ifindex, &network, plen, metric);
}
@@ -3989,6 +4006,8 @@ ip4_route_exists (NMPlatform *platform, int ifindex, in_addr_t network, int plen
static gboolean
ip6_route_exists (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, guint32 metric)
{
+ metric = nm_utils_ip6_route_metric_normalize (metric);
+
return ip_route_exists (platform, AF_INET6, ifindex, &network, plen, metric);
}
diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c
index 2c70b412bb..9ccca0a0f6 100644
--- a/src/platform/tests/test-route.c
+++ b/src/platform/tests/test-route.c
@@ -2,6 +2,7 @@
#include "test-common.h"
#include "nm-test-utils.h"
+#include "NetworkManagerUtils.h"
#define DEVICE_NAME "nm-test-device"
@@ -205,21 +206,21 @@ test_ip6_route (void)
rts[0].plen = 128;
rts[0].ifindex = ifindex;
rts[0].gateway = in6addr_any;
- rts[0].metric = metric;
+ rts[0].metric = nm_utils_ip6_route_metric_normalize (metric);
rts[0].mss = mss;
rts[1].source = NM_IP_CONFIG_SOURCE_USER;
rts[1].network = network;
rts[1].plen = plen;
rts[1].ifindex = ifindex;
rts[1].gateway = gateway;
- rts[1].metric = metric;
+ rts[1].metric = nm_utils_ip6_route_metric_normalize (metric);
rts[1].mss = mss;
rts[2].source = NM_IP_CONFIG_SOURCE_USER;
rts[2].network = in6addr_any;
rts[2].plen = 0;
rts[2].ifindex = ifindex;
rts[2].gateway = gateway;
- rts[2].metric = metric;
+ rts[2].metric = nm_utils_ip6_route_metric_normalize (metric);
rts[2].mss = mss;
g_assert_cmpint (routes->len, ==, 3);
g_assert (!memcmp (routes->data, rts, sizeof (rts)));
diff --git a/src/settings/plugins/ifcfg-rh/reader.c b/src/settings/plugins/ifcfg-rh/reader.c
index fe8112baae..e892394dcf 100644
--- a/src/settings/plugins/ifcfg-rh/reader.c
+++ b/src/settings/plugins/ifcfg-rh/reader.c
@@ -960,6 +960,8 @@ make_ip4_setting (shvarFile *ifcfg,
NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, !svTrueValue (ifcfg, "PEERROUTES", TRUE),
NM_SETTING_IP_CONFIG_NEVER_DEFAULT, never_default,
NM_SETTING_IP_CONFIG_MAY_FAIL, !svTrueValue (ifcfg, "IPV4_FAILURE_FATAL", FALSE),
+ NM_SETTING_IP_CONFIG_ROUTE_METRIC, svGetValueInt64 (ifcfg, "IPV4_ROUTE_METRIC", 10,
+ -1, G_MAXUINT32, -1),
NULL);
if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0)
@@ -1356,6 +1358,8 @@ make_ip6_setting (shvarFile *ifcfg,
NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, !svTrueValue (ifcfg, "IPV6_PEERROUTES", TRUE),
NM_SETTING_IP_CONFIG_NEVER_DEFAULT, never_default,
NM_SETTING_IP_CONFIG_MAY_FAIL, !svTrueValue (ifcfg, "IPV6_FAILURE_FATAL", FALSE),
+ NM_SETTING_IP_CONFIG_ROUTE_METRIC, svGetValueInt64 (ifcfg, "IPV6_ROUTE_METRIC", 10,
+ -1, G_MAXUINT32, -1),
NM_SETTING_IP6_CONFIG_IP6_PRIVACY, ip6_privacy_val,
NULL);
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open
index 48db45b25d..b089103dae 100644
--- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open
@@ -12,3 +12,5 @@ ONBOOT=yes
USERCTL=yes
PEERDNS=yes
IPV6INIT=no
+IPV4_ROUTE_METRIC=104
+IPV6_ROUTE_METRIC=106
diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
index fecacaed40..e05a4ccb20 100644
--- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
+++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
@@ -2439,7 +2439,7 @@ test_read_wifi_open (void)
NMSettingConnection *s_con;
NMSettingWireless *s_wireless;
NMSettingWirelessSecurity *s_wsec;
- NMSettingIPConfig *s_ip4;
+ NMSettingIPConfig *s_ip4, *s_ip6;
GError *error = NULL;
const char *tmp;
GBytes *ssid;
@@ -2584,6 +2584,8 @@ test_read_wifi_open (void)
TEST_IFCFG_WIFI_OPEN,
NM_SETTING_IP4_CONFIG_SETTING_NAME);
+ g_assert_cmpint (nm_setting_ip_config_get_route_metric (s_ip4), ==, 104);
+
/* Method */
tmp = nm_setting_ip_config_get_method (s_ip4);
ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0,
@@ -2592,6 +2594,10 @@ test_read_wifi_open (void)
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP_CONFIG_METHOD);
+ s_ip6 = nm_connection_get_setting_ip6_config (connection);
+ g_assert( s_ip6);
+ g_assert_cmpint (nm_setting_ip_config_get_route_metric (s_ip6), ==, 106);
+
g_object_unref (connection);
}
@@ -5775,6 +5781,7 @@ test_write_wired_static (void)
NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
NM_SETTING_IP_CONFIG_GATEWAY, "1.1.1.1",
+ NM_SETTING_IP_CONFIG_ROUTE_METRIC, (gint64) 204,
NULL);
addr = nm_ip_address_new (AF_INET, "1.1.1.3", 24, &error);
@@ -5800,6 +5807,7 @@ test_write_wired_static (void)
g_object_set (s_ip6,
NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_MANUAL,
NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
+ NM_SETTING_IP_CONFIG_ROUTE_METRIC, (gint64) 206,
NULL);
/* Add addresses */
@@ -5883,6 +5891,9 @@ test_write_wired_static (void)
nm_setting_ip_config_remove_dns_search (reread_s_ip4, 3);
nm_setting_ip_config_remove_dns_search (reread_s_ip4, 2);
+ g_assert_cmpint (nm_setting_ip_config_get_route_metric (reread_s_ip4), ==, 204);
+ g_assert_cmpint (nm_setting_ip_config_get_route_metric (reread_s_ip6), ==, 206);
+
ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
"wired-static-write", "written and re-read connection weren't the same.");
diff --git a/src/settings/plugins/ifcfg-rh/writer.c b/src/settings/plugins/ifcfg-rh/writer.c
index f4ffffd6a8..300b0c1665 100644
--- a/src/settings/plugins/ifcfg-rh/writer.c
+++ b/src/settings/plugins/ifcfg-rh/writer.c
@@ -1806,6 +1806,7 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
char *route_path = NULL;
gint32 j;
guint32 i, n, num;
+ gint64 route_metric;
GString *searches;
gboolean success = FALSE;
gboolean fake_ip4 = FALSE;
@@ -2015,6 +2016,11 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
nm_setting_ip_config_get_may_fail (s_ip4) ? "no" : "yes",
FALSE);
+ route_metric = nm_setting_ip_config_get_route_metric (s_ip4);
+ tmp = route_metric != -1 ? g_strdup_printf ("%"G_GINT64_FORMAT, route_metric) : NULL;
+ svSetValue (ifcfg, "IPV4_ROUTE_METRIC", tmp, FALSE);
+ g_free (tmp);
+
/* Static routes - route-<name> file */
route_path = utils_get_route_path (ifcfg->fileName);
if (!route_path) {
@@ -2249,10 +2255,12 @@ write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
NMSettingIPConfig *s_ip4;
const char *value;
char *addr_key;
+ char *tmp;
guint32 i, num, num4;
GString *searches;
NMIPAddress *addr;
const char *dns;
+ gint64 route_metric;
GString *ip_str1, *ip_str2, *ip_ptr;
char *route6_path;
@@ -2266,6 +2274,7 @@ write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
svSetValue (ifcfg, "IPV6_PEERDNS", "yes", FALSE);
svSetValue (ifcfg, "IPV6_PEERROUTES", "yes", FALSE);
svSetValue (ifcfg, "IPV6_FAILURE_FATAL", "no", FALSE);
+ svSetValue (ifcfg, "IPV6_ROUTE_METRIC", NULL, FALSE);
return TRUE;
}
@@ -2380,6 +2389,11 @@ write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
nm_setting_ip_config_get_may_fail (s_ip6) ? "no" : "yes",
FALSE);
+ route_metric = nm_setting_ip_config_get_route_metric (s_ip6);
+ tmp = route_metric != -1 ? g_strdup_printf ("%"G_GINT64_FORMAT, route_metric) : NULL;
+ svSetValue (ifcfg, "IPV6_ROUTE_METRIC", tmp, FALSE);
+ g_free (tmp);
+
/* IPv6 Privacy Extensions */
svSetValue (ifcfg, "IPV6_PRIVACY", NULL, FALSE);
svSetValue (ifcfg, "IPV6_PRIVACY_PREFER_PUBLIC_IP", NULL, FALSE);