diff options
author | Thomas Haller <thaller@redhat.com> | 2019-08-03 08:15:50 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2019-08-10 10:24:05 +0200 |
commit | 903123d645529e0997b0ab4b516161b426ccebd2 (patch) | |
tree | 5bc1f3bfcfde1d133ebcaa6b82c7f6229d1bd43f | |
parent | 7d2de190d5e69ad498e94c372bb4de268838983e (diff) | |
download | NetworkManager-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.c | 2 | ||||
-rw-r--r-- | libnm-core/nm-keyfile.c | 30 | ||||
-rw-r--r-- | libnm-core/nm-setting-ip-config.c | 11 | ||||
-rw-r--r-- | src/nm-ip4-config.c | 2 | ||||
-rw-r--r-- | src/nm-ip6-config.c | 2 | ||||
-rw-r--r-- | src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 11 | ||||
-rw-r--r-- | src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c | 15 |
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); |