summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2019-08-03 08:15:50 +0200
committerThomas Haller <thaller@redhat.com>2019-08-10 10:24:05 +0200
commit903123d645529e0997b0ab4b516161b426ccebd2 (patch)
tree5bc1f3bfcfde1d133ebcaa6b82c7f6229d1bd43f
parent7d2de190d5e69ad498e94c372bb4de268838983e (diff)
downloadNetworkManager-th/static-default-route.tar.gz
all: allow configuring default-routes as manual, static routesth/static-default-route
Up until now, a default-route (with prefix length zero) could not be configured directly. The user could only set ipv4.gateway, ipv4.never-default, ipv4.route-metric and ipv4.route-table to influence the setting of the default-route (respectively for IPv6). That is a problematic limitation. For one, whether a route has prefix length zero or non-zero does not make a fundamental difference. Also, it makes it impossible to configure all the routing attributes that one can configure otherwise for static routes. For example, the default-route could not be configured as "onlink", could not have a special MTU, nor could it be placed in a dedicated routing table. Fix that by lifting the restriction. Note that "ipv4.never-default" does not apply to /0 manual routes. Likewise, the previous manners of configuring default-routes ("ipv4.gateway") don't conflict with manual default-routes. Server-side this all the pieces are already in place to accept a default-route as static routes. This was done by earlier commits like 5c299454b49b ('core: rework tracking of gateway/default-route in ip-config'). A long time ago, NMIPRoute would assert that the prefix length is positive. That was relaxed by commit a2e93f2de4ac ('libnm: allow zero prefix length for NMIPRoute'), already before 1.0.0. Using libnm from before 1.0.0 would result in assertion failures. Note that the default-route-metric-penalty based on connectivity checking applies to all /0 routes, even these static routes. Be they added due to DHCP, "ipv4.gateway", "ipv4.routes" or "wireguard.peer-routes". I wonder whether doing that unconditionally is desirable, and maybe there should be a way to opt-out/opt-in for the entire profile or even per-routes. https://bugzilla.redhat.com/show_bug.cgi?id=1714438
-rw-r--r--clients/common/nm-meta-setting-desc.c2
-rw-r--r--libnm-core/nm-keyfile.c30
-rw-r--r--libnm-core/nm-setting-ip-config.c11
-rw-r--r--src/nm-ip4-config.c2
-rw-r--r--src/nm-ip6-config.c2
-rw-r--r--src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c11
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c15
7 files changed, 33 insertions, 40 deletions
diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c
index 86682e2e76..9b13bd7540 100644
--- a/clients/common/nm-meta-setting-desc.c
+++ b/clients/common/nm-meta-setting-desc.c
@@ -367,7 +367,7 @@ _parse_ip_route (int family,
}
prefix = MAX_PREFIX;
if (plen) {
- if ((prefix = _nm_utils_ascii_str_to_int64 (plen, 10, 1, MAX_PREFIX, -1)) == -1) {
+ if ((prefix = _nm_utils_ascii_str_to_int64 (plen, 10, 0, MAX_PREFIX, -1)) == -1) {
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT,
_("invalid prefix '%s'; <1-%d> allowed"),
plen, MAX_PREFIX);
diff --git a/libnm-core/nm-keyfile.c b/libnm-core/nm-keyfile.c
index b0c7a13478..9b032c4cd8 100644
--- a/libnm-core/nm-keyfile.c
+++ b/libnm-core/nm-keyfile.c
@@ -248,15 +248,16 @@ static gpointer
build_route (KeyfileReaderInfo *info,
const char *property_name,
int family,
- const char *dest_str, guint32 plen,
- const char *gateway_str, const char *metric_str)
+ const char *dest_str,
+ guint32 plen,
+ const char *gateway_str,
+ const char *metric_str)
{
NMIPRoute *route;
guint32 u32;
gint64 metric = -1;
GError *error = NULL;
- g_return_val_if_fail (plen, NULL);
g_return_val_if_fail (dest_str, NULL);
/* Next hop */
@@ -294,7 +295,10 @@ build_route (KeyfileReaderInfo *info,
metric = u32;
}
- route = nm_ip_route_new (family, dest_str, plen, gateway_str,
+ route = nm_ip_route_new (family,
+ dest_str,
+ plen,
+ gateway_str,
metric,
&error);
if (!route) {
@@ -517,8 +521,7 @@ read_one_ip_address_or_route (KeyfileReaderInfo *info,
/* parse plen, fallback to defaults */
if (plen_str) {
- if ( !get_one_int (info, property_name, plen_str, ipv6 ? 128 : 32, &plen)
- || (route && plen == 0)) {
+ if (!get_one_int (info, property_name, plen_str, ipv6 ? 128 : 32, &plen)) {
plen = DEFAULT_PREFIX (route, ipv6);
if ( info->error
|| !handle_warn (info, property_name, NM_KEYFILE_WARN_SEVERITY_WARN,
@@ -536,12 +539,19 @@ read_one_ip_address_or_route (KeyfileReaderInfo *info,
/* build the appropriate data structure for NetworkManager settings */
if (route) {
- result = build_route (info, property_name,
+ result = build_route (info,
+ property_name,
ipv6 ? AF_INET6 : AF_INET,
- address_str, plen, gateway_str, metric_str);
+ address_str,
+ plen,
+ gateway_str,
+ metric_str);
} else {
- result = build_address (info, ipv6 ? AF_INET6 : AF_INET,
- address_str, plen, property_name);
+ result = build_address (info,
+ ipv6 ? AF_INET6 : AF_INET,
+ address_str,
+ plen,
+ property_name);
if (!result)
return NULL;
if (gateway_str)
diff --git a/libnm-core/nm-setting-ip-config.c b/libnm-core/nm-setting-ip-config.c
index 3475ab5365..37c0adb873 100644
--- a/libnm-core/nm-setting-ip-config.c
+++ b/libnm-core/nm-setting-ip-config.c
@@ -1335,7 +1335,7 @@ nm_ip_route_attribute_validate (const char *name,
if (str) {
addr = nm_strndup_a (200, addr, str - addr, &addr_free);
str++;
- if (_nm_utils_ascii_str_to_int64 (str, 10, 1, family == AF_INET ? 32 : 128, -1) < 0) {
+ if (_nm_utils_ascii_str_to_int64 (str, 10, 0, family == AF_INET ? 32 : 128, -1) < 0) {
g_set_error (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_FAILED,
@@ -5005,15 +5005,6 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), NM_SETTING_IP_CONFIG_ROUTES);
return FALSE;
}
- if (nm_ip_route_get_prefix (route) == 0) {
- g_set_error (error,
- NM_CONNECTION_ERROR,
- NM_CONNECTION_ERROR_INVALID_PROPERTY,
- _("%d. route cannot be a default route"),
- (int) (i + 1));
- g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), NM_SETTING_IP_CONFIG_ROUTES);
- return FALSE;
- }
}
if (priv->routing_rules) {
diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c
index 36e75bb2d2..4a620c9569 100644
--- a/src/nm-ip4-config.c
+++ b/src/nm-ip4-config.c
@@ -991,8 +991,6 @@ nm_ip4_config_merge_setting (NMIP4Config *self,
route.plen = nm_ip_route_get_prefix (s_route);
nm_assert (route.plen <= 32);
- if (route.plen == 0)
- continue;
nm_ip_route_get_next_hop_binary (s_route, &route.gateway);
if (nm_ip_route_get_metric (s_route) == -1)
diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c
index 1810d51185..3f0cd9b3bf 100644
--- a/src/nm-ip6-config.c
+++ b/src/nm-ip6-config.c
@@ -672,8 +672,6 @@ nm_ip6_config_merge_setting (NMIP6Config *self,
route.plen = nm_ip_route_get_prefix (s_route);
nm_assert (route.plen <= 128);
- if (route.plen == 0)
- continue;
nm_ip_route_get_next_hop_binary (s_route, &route.gateway);
if (nm_ip_route_get_metric (s_route) == -1)
diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c
index 9c3ae10af8..9205de8643 100644
--- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c
+++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c
@@ -1116,15 +1116,6 @@ next:
? info_to->v.addr.plen
: (addr_family == AF_INET ? 32 : 128);
- if ( ( (addr_family == AF_INET && !info_to->v.addr.addr.addr4)
- || (addr_family == AF_INET6 && IN6_IS_ADDR_UNSPECIFIED (&info_to->v.addr.addr.addr6)))
- && prefix == 0) {
- /* we ignore default routes by returning -ERANGE. */
- g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
- "Ignore manual default route");
- return -ERANGE;
- }
-
route = nm_ip_route_new_binary (addr_family,
&info_to->v.addr.addr,
prefix,
@@ -1244,7 +1235,7 @@ read_one_ip4_route (shvarFile *ifcfg,
return FALSE;
if (has_key) {
prefix = nm_utils_ip4_netmask_to_prefix (netmask);
- if (prefix == 0 || netmask != _nm_utils_ip4_prefix_to_netmask (prefix)) {
+ if (netmask != _nm_utils_ip4_prefix_to_netmask (prefix)) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
"Invalid IP4 netmask '%s' \"%s\"", netmask_tag, nm_utils_inet4_ntop (netmask, inet_buf));
return FALSE;
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 45e90b919c..db394d8fa5 100644
--- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
+++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
@@ -1520,10 +1520,8 @@ test_read_wired_ipv6_manual (void)
NMIPAddress *ip6_addr;
NMIPRoute *ip6_route;
- NMTST_EXPECT_NM_WARN ("*ignoring manual default route*");
connection = _connection_from_file (TEST_IFCFG_DIR"/ifcfg-test-wired-ipv6-manual",
NULL, TYPE_ETHERNET, &unmanaged);
- g_test_assert_expected_messages ();
g_assert (!unmanaged);
/* ===== CONNECTION SETTING ===== */
@@ -1581,7 +1579,7 @@ test_read_wired_ipv6_manual (void)
g_assert_cmpint (nm_ip_address_get_prefix (ip6_addr), ==, 96);
/* Routes */
- g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip6), ==, 3);
+ g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip6), ==, 4);
/* Route #1 */
ip6_route = nm_setting_ip_config_get_route (s_ip6, 0);
g_assert (ip6_route);
@@ -1592,12 +1590,19 @@ test_read_wired_ipv6_manual (void)
/* Route #2 */
ip6_route = nm_setting_ip_config_get_route (s_ip6, 1);
g_assert (ip6_route);
+ g_assert_cmpstr (nm_ip_route_get_dest (ip6_route), ==, "::");
+ g_assert_cmpint (nm_ip_route_get_prefix (ip6_route), ==, 0);
+ g_assert_cmpstr (nm_ip_route_get_next_hop (ip6_route), ==, "dead::beaf");
+ g_assert_cmpint (nm_ip_route_get_metric (ip6_route), ==, -1);
+ /* Route #3 */
+ ip6_route = nm_setting_ip_config_get_route (s_ip6, 2);
+ g_assert (ip6_route);
g_assert_cmpstr (nm_ip_route_get_dest (ip6_route), ==, "abbe::cafe");
g_assert_cmpint (nm_ip_route_get_prefix (ip6_route), ==, 64);
g_assert_cmpstr (nm_ip_route_get_next_hop (ip6_route), ==, NULL);
g_assert_cmpint (nm_ip_route_get_metric (ip6_route), ==, 777);
- /* Route #3 */
- ip6_route = nm_setting_ip_config_get_route (s_ip6, 2);
+ /* Route #4 */
+ ip6_route = nm_setting_ip_config_get_route (s_ip6, 3);
g_assert (ip6_route);
g_assert_cmpstr (nm_ip_route_get_dest (ip6_route), ==, "aaaa::cccc");
g_assert_cmpint (nm_ip_route_get_prefix (ip6_route), ==, 64);