mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-24 23:00:40 +01:00
merge: branch 'bg/warn-unreachable-gateways'
Warn about directly unreachable gateways https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/2360
This commit is contained in:
commit
7d0427890a
9 changed files with 604 additions and 1 deletions
8
NEWS
8
NEWS
|
|
@ -12,6 +12,14 @@ USE AT YOUR OWN RISK. NOT RECOMMENDED FOR PRODUCTION USE!
|
|||
suffixes when appropriate. This affects, for example, the URL and filename
|
||||
of the release tarball and the version reported by nmcli and the daemon.
|
||||
As an exception, the C API will continue to use the 90+ scheme for RC versions.
|
||||
* Connection profiles with manual IP addressing and with gateways that are not
|
||||
directly reachable will generate a warning on activation and when they are
|
||||
added/modified via nmcli and nmtui. NetworkManager currently adds on-link
|
||||
routes for them automatically, but this will change in the future. To fix the
|
||||
warning, users should add addresses or routes whose subnets cover these
|
||||
gateways. A gateway (either the default gateway or the next-hop of a route) is
|
||||
considered directly reachable if it falls within the subnet of a direct route
|
||||
(a route without a next hop) or of a prefix route from a static address.
|
||||
* Restrict the connectivity check to use the DNS servers defined on the
|
||||
same link. If the link has no DNS servers, the connectivity check will
|
||||
use any servers available in the system.
|
||||
|
|
|
|||
|
|
@ -3684,6 +3684,7 @@ nm_device_create_l3_config_data_from_connection(NMDevice *self, NMConnection *co
|
|||
{
|
||||
NML3ConfigData *l3cd;
|
||||
int ifindex;
|
||||
gs_free char *gw_warning = NULL;
|
||||
|
||||
nm_assert(NM_IS_DEVICE(self));
|
||||
nm_assert(!connection || NM_IS_CONNECTION(connection));
|
||||
|
|
@ -3704,6 +3705,10 @@ nm_device_create_l3_config_data_from_connection(NMDevice *self, NMConnection *co
|
|||
nm_l3_config_data_set_ip6_privacy(l3cd, _prop_get_ipv6_ip6_privacy(self, connection));
|
||||
nm_l3_config_data_set_mptcp_flags(l3cd, _prop_get_connection_mptcp_flags(self, connection));
|
||||
|
||||
gw_warning = nm_connection_get_unreachable_gateways_warning(connection, FALSE);
|
||||
if (gw_warning)
|
||||
_LOGW(LOGD_IP, "%s", gw_warning);
|
||||
|
||||
return l3cd;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1149,3 +1149,202 @@ nm_setting_ovs_other_config_check_val(const char *val, GError **error)
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
NMIPAddr dest;
|
||||
guint prefix;
|
||||
} DirectRoute;
|
||||
|
||||
static void
|
||||
_setting_ip_config_collect_unreachable_gateways(NMSettingIPConfig *s_ip, GHashTable **result)
|
||||
{
|
||||
const int addr_family = nm_setting_ip_config_get_addr_family(s_ip);
|
||||
guint num_routes;
|
||||
guint num_addrs;
|
||||
guint n_direct_routes = 0;
|
||||
NMIPAddr gw_bin = NM_IP_ADDR_INIT;
|
||||
guint i;
|
||||
guint j;
|
||||
const char *gateway;
|
||||
gs_free DirectRoute *direct_routes = NULL;
|
||||
|
||||
num_routes = nm_setting_ip_config_get_num_routes(s_ip);
|
||||
num_addrs = nm_setting_ip_config_get_num_addresses(s_ip);
|
||||
|
||||
direct_routes = g_new0(DirectRoute, num_routes + num_addrs);
|
||||
|
||||
/* Collect direct routes (routes without a gateway) from the setting. */
|
||||
for (i = 0; i < num_routes; i++) {
|
||||
NMIPRoute *route = nm_setting_ip_config_get_route(s_ip, i);
|
||||
|
||||
if (nm_ip_route_get_next_hop(route))
|
||||
continue;
|
||||
|
||||
nm_ip_route_get_dest_binary(route, &direct_routes[n_direct_routes].dest);
|
||||
direct_routes[n_direct_routes].prefix = nm_ip_route_get_prefix(route);
|
||||
n_direct_routes++;
|
||||
}
|
||||
|
||||
/* Add prefix routes (device routes) for each static address. */
|
||||
for (i = 0; i < num_addrs; i++) {
|
||||
NMIPAddress *addr = nm_setting_ip_config_get_address(s_ip, i);
|
||||
|
||||
nm_ip_address_get_address_binary(addr, &direct_routes[n_direct_routes].dest);
|
||||
direct_routes[n_direct_routes].prefix = nm_ip_address_get_prefix(addr);
|
||||
n_direct_routes++;
|
||||
}
|
||||
|
||||
/* Check the setting's default gateway. */
|
||||
gateway = nm_setting_ip_config_get_gateway(s_ip);
|
||||
if (gateway && nm_inet_parse_bin(addr_family, gateway, NULL, &gw_bin)) {
|
||||
gboolean reachable = FALSE;
|
||||
|
||||
if (addr_family == AF_INET6 && IN6_IS_ADDR_LINKLOCAL(&gw_bin.addr6))
|
||||
reachable = TRUE;
|
||||
|
||||
if (!reachable) {
|
||||
for (j = 0; j < n_direct_routes; j++) {
|
||||
if (nm_ip_addr_same_prefix(addr_family,
|
||||
&gw_bin,
|
||||
&direct_routes[j].dest,
|
||||
direct_routes[j].prefix)) {
|
||||
reachable = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!reachable) {
|
||||
if (!*result)
|
||||
*result = g_hash_table_new(nm_str_hash, g_str_equal);
|
||||
g_hash_table_add(*result, (gpointer) gateway);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check gateways of each route in the setting. */
|
||||
for (i = 0; i < num_routes; i++) {
|
||||
NMIPRoute *route = nm_setting_ip_config_get_route(s_ip, i);
|
||||
NMIPAddr next_hop = NM_IP_ADDR_INIT;
|
||||
gboolean reachable = FALSE;
|
||||
GVariant *attribute;
|
||||
|
||||
if (!nm_ip_route_get_next_hop_binary(route, &next_hop))
|
||||
continue;
|
||||
|
||||
if (addr_family == AF_INET6 && IN6_IS_ADDR_LINKLOCAL(&next_hop.addr6))
|
||||
continue;
|
||||
|
||||
attribute = nm_ip_route_get_attribute(route, NM_IP_ROUTE_ATTRIBUTE_ONLINK);
|
||||
if (attribute && g_variant_is_of_type(attribute, G_VARIANT_TYPE("b"))
|
||||
&& g_variant_get_boolean(attribute)) {
|
||||
/* the gateway of a onlink route is reachable */
|
||||
continue;
|
||||
}
|
||||
|
||||
for (j = 0; j < n_direct_routes; j++) {
|
||||
if (nm_ip_addr_same_prefix(addr_family,
|
||||
&next_hop,
|
||||
&direct_routes[j].dest,
|
||||
direct_routes[j].prefix)) {
|
||||
reachable = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!reachable) {
|
||||
if (!*result)
|
||||
*result = g_hash_table_new(nm_str_hash, g_str_equal);
|
||||
g_hash_table_add(*result, (gpointer) nm_ip_route_get_next_hop(route));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_connection_get_unreachable_gateways:
|
||||
* @connection: the #NMConnection
|
||||
*
|
||||
* Checks whether there are gateways (either the default gateway or gateways
|
||||
* of routes) that are not directly reachable in the IPv4 and IPv6 settings
|
||||
* of the connection. A gateway is considered directly reachable if it falls
|
||||
* within the subnet of a direct route (a route without a next hop) or of a
|
||||
* prefix route from a static address.
|
||||
*
|
||||
* Returns: a %NULL-terminated array of gateway strings not directly reachable,
|
||||
* or %NULL if all gateways are reachable. The individual strings are owned
|
||||
* by the setting. Free the returned array with g_free().
|
||||
*/
|
||||
const char **
|
||||
nm_connection_get_unreachable_gateways(NMConnection *connection)
|
||||
{
|
||||
gs_unref_hashtable GHashTable *result = NULL;
|
||||
NMSettingIPConfig *s_ip;
|
||||
guint len;
|
||||
const char **strv;
|
||||
|
||||
if (!connection)
|
||||
return NULL;
|
||||
|
||||
s_ip = nm_connection_get_setting_ip4_config(connection);
|
||||
if (s_ip
|
||||
&& nm_streq0(nm_setting_ip_config_get_method(s_ip), NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) {
|
||||
_setting_ip_config_collect_unreachable_gateways(s_ip, &result);
|
||||
}
|
||||
|
||||
s_ip = nm_connection_get_setting_ip6_config(connection);
|
||||
if (s_ip
|
||||
&& nm_streq0(nm_setting_ip_config_get_method(s_ip), NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
|
||||
_setting_ip_config_collect_unreachable_gateways(s_ip, &result);
|
||||
}
|
||||
|
||||
if (result) {
|
||||
strv = (const char **) g_hash_table_get_keys_as_array(result, &len);
|
||||
nm_strv_sort(strv, len);
|
||||
return strv;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_connection_get_unreachable_gateways_warning:
|
||||
* @connection: the #NMConnection
|
||||
* @translate: whether to translate the message (use %TRUE for user-facing
|
||||
* tools like nmcli, %FALSE for daemon logs)
|
||||
*
|
||||
* Checks whether there are unreachable gateways in the connection and returns
|
||||
* a formatted warning message if so.
|
||||
*
|
||||
* Returns: a warning message string, or %NULL if all gateways are reachable.
|
||||
* Free with g_free().
|
||||
*/
|
||||
char *
|
||||
nm_connection_get_unreachable_gateways_warning(NMConnection *connection, gboolean translate)
|
||||
{
|
||||
gs_free const char **gateways = NULL;
|
||||
gs_free char *gw_list = NULL;
|
||||
|
||||
gateways = nm_connection_get_unreachable_gateways(connection);
|
||||
if (!gateways)
|
||||
return NULL;
|
||||
|
||||
gw_list = g_strjoinv(", ", (char **) gateways);
|
||||
|
||||
/* Keep the following two strings in sync. */
|
||||
if (translate) {
|
||||
return g_strdup_printf(
|
||||
_("the following gateways are not directly reachable from any configured address or "
|
||||
"route: %s. NetworkManager currently adds on-link routes for them automatically, "
|
||||
"but this will change in the future. Consider adding addresses or routes whose "
|
||||
"subnets cover these gateways"),
|
||||
gw_list);
|
||||
}
|
||||
|
||||
return g_strdup_printf(
|
||||
"the following gateways are not directly reachable from any configured address or "
|
||||
"route: %s. NetworkManager currently adds on-link routes for them automatically, "
|
||||
"but this will change in the future. Consider adding addresses or routes whose "
|
||||
"subnets cover these gateways",
|
||||
gw_list);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -344,6 +344,12 @@ gboolean nm_setting_ovs_other_config_check_val(const char *val, GError **error);
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
const char **nm_connection_get_unreachable_gateways(NMConnection *connection);
|
||||
|
||||
char *nm_connection_get_unreachable_gateways_warning(NMConnection *connection, gboolean translate);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Wi-Fi frequencies range for each band */
|
||||
#define _NM_WIFI_FREQ_MIN_2GHZ 2412
|
||||
#define _NM_WIFI_FREQ_MAX_2GHZ 2484
|
||||
|
|
|
|||
|
|
@ -11613,6 +11613,328 @@ test_dhcp_iaid_hexstr(void)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
test_unreachable_gateways(void)
|
||||
{
|
||||
NMConnection *conn;
|
||||
NMSettingIPConfig *s_ip4;
|
||||
NMSettingIPConfig *s_ip6;
|
||||
gs_free const char **result = NULL;
|
||||
|
||||
/* IPv4 gateway reachable via address prefix route */
|
||||
{
|
||||
conn =
|
||||
nmtst_create_minimal_connection("test-ugw", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
|
||||
s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new();
|
||||
g_object_set(s_ip4,
|
||||
NM_SETTING_IP_CONFIG_METHOD,
|
||||
NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
|
||||
NM_SETTING_IP_CONFIG_GATEWAY,
|
||||
"192.168.1.1",
|
||||
NULL);
|
||||
nmtst_setting_ip_config_add_address(s_ip4, "192.168.1.5", 24);
|
||||
nm_connection_add_setting(conn, NM_SETTING(s_ip4));
|
||||
|
||||
result = nm_connection_get_unreachable_gateways(conn);
|
||||
g_assert(!result);
|
||||
g_object_unref(conn);
|
||||
}
|
||||
|
||||
/* IPv4 gateway NOT reachable */
|
||||
{
|
||||
conn =
|
||||
nmtst_create_minimal_connection("test-ugw", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
|
||||
s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new();
|
||||
g_object_set(s_ip4,
|
||||
NM_SETTING_IP_CONFIG_METHOD,
|
||||
NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
|
||||
NM_SETTING_IP_CONFIG_GATEWAY,
|
||||
"10.0.0.1",
|
||||
NULL);
|
||||
nmtst_setting_ip_config_add_address(s_ip4, "192.168.1.5", 24);
|
||||
nmtst_setting_ip_config_add_address(s_ip4, "172.16.1.1", 16);
|
||||
nm_connection_add_setting(conn, NM_SETTING(s_ip4));
|
||||
|
||||
result = nm_connection_get_unreachable_gateways(conn);
|
||||
g_assert(result);
|
||||
g_assert_cmpint(g_strv_length((char **) result), ==, 1);
|
||||
g_assert_cmpstr(result[0], ==, "10.0.0.1");
|
||||
nm_clear_g_free(&result);
|
||||
g_object_unref(conn);
|
||||
}
|
||||
|
||||
/* IPv4 gateway NOT reachable. It's ignored because of method "auto" */
|
||||
{
|
||||
conn =
|
||||
nmtst_create_minimal_connection("test-ugw", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
|
||||
s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new();
|
||||
g_object_set(s_ip4,
|
||||
NM_SETTING_IP_CONFIG_METHOD,
|
||||
NM_SETTING_IP4_CONFIG_METHOD_AUTO,
|
||||
NM_SETTING_IP_CONFIG_GATEWAY,
|
||||
"10.0.0.1",
|
||||
NULL);
|
||||
nmtst_setting_ip_config_add_address(s_ip4, "192.168.1.5", 24);
|
||||
nmtst_setting_ip_config_add_address(s_ip4, "172.16.1.1", 16);
|
||||
nm_connection_add_setting(conn, NM_SETTING(s_ip4));
|
||||
|
||||
result = nm_connection_get_unreachable_gateways(conn);
|
||||
g_assert(!result);
|
||||
g_object_unref(conn);
|
||||
}
|
||||
|
||||
/* Route gateway reachable via address prefix route */
|
||||
{
|
||||
conn =
|
||||
nmtst_create_minimal_connection("test-ugw", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
|
||||
s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new();
|
||||
g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, NULL);
|
||||
nmtst_setting_ip_config_add_address(s_ip4, "192.168.1.5", 24);
|
||||
nmtst_setting_ip_config_add_route(s_ip4, "10.0.0.0", 8, "192.168.1.254", 100);
|
||||
nm_connection_add_setting(conn, NM_SETTING(s_ip4));
|
||||
|
||||
result = nm_connection_get_unreachable_gateways(conn);
|
||||
g_assert(!result);
|
||||
g_object_unref(conn);
|
||||
}
|
||||
|
||||
/* Route gateway NOT reachable, check sorting */
|
||||
{
|
||||
conn =
|
||||
nmtst_create_minimal_connection("test-ugw", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
|
||||
s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new();
|
||||
g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, NULL);
|
||||
nmtst_setting_ip_config_add_address(s_ip4, "192.168.1.5", 24);
|
||||
nmtst_setting_ip_config_add_route(s_ip4, "10.0.0.0", 16, "172.16.0.2", 100);
|
||||
nmtst_setting_ip_config_add_route(s_ip4, "10.1.0.0", 16, "172.16.0.4", 100);
|
||||
nmtst_setting_ip_config_add_route(s_ip4, "10.2.0.0", 16, "172.16.0.3", 100);
|
||||
nmtst_setting_ip_config_add_route(s_ip4, "10.3.0.0", 16, "172.16.0.1", 100);
|
||||
nm_connection_add_setting(conn, NM_SETTING(s_ip4));
|
||||
|
||||
result = nm_connection_get_unreachable_gateways(conn);
|
||||
g_assert(result);
|
||||
g_assert_cmpint(g_strv_length((char **) result), ==, 4);
|
||||
g_assert_cmpstr(result[0], ==, "172.16.0.1");
|
||||
g_assert_cmpstr(result[1], ==, "172.16.0.2");
|
||||
g_assert_cmpstr(result[2], ==, "172.16.0.3");
|
||||
g_assert_cmpstr(result[3], ==, "172.16.0.4");
|
||||
nm_clear_g_free(&result);
|
||||
g_object_unref(conn);
|
||||
}
|
||||
|
||||
/* Route gateway reachable via a direct route in the setting */
|
||||
{
|
||||
conn =
|
||||
nmtst_create_minimal_connection("test-ugw", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
|
||||
s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new();
|
||||
g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, NULL);
|
||||
nmtst_setting_ip_config_add_address(s_ip4, "192.168.1.5", 24);
|
||||
nmtst_setting_ip_config_add_route(s_ip4, "172.16.0.0", 16, NULL, 100);
|
||||
nmtst_setting_ip_config_add_route(s_ip4, "10.0.0.0", 8, "172.16.0.1", 100);
|
||||
nm_connection_add_setting(conn, NM_SETTING(s_ip4));
|
||||
|
||||
result = nm_connection_get_unreachable_gateways(conn);
|
||||
g_assert(!result);
|
||||
g_object_unref(conn);
|
||||
}
|
||||
|
||||
/* No gateways */
|
||||
{
|
||||
conn =
|
||||
nmtst_create_minimal_connection("test-ugw", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
|
||||
s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new();
|
||||
g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, NULL);
|
||||
nmtst_setting_ip_config_add_address(s_ip4, "192.168.1.5", 24);
|
||||
nm_connection_add_setting(conn, NM_SETTING(s_ip4));
|
||||
|
||||
result = nm_connection_get_unreachable_gateways(conn);
|
||||
g_assert(!result);
|
||||
g_object_unref(conn);
|
||||
}
|
||||
|
||||
/* Both default gateway and route gateway unreachable */
|
||||
{
|
||||
conn =
|
||||
nmtst_create_minimal_connection("test-ugw", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
|
||||
s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new();
|
||||
g_object_set(s_ip4,
|
||||
NM_SETTING_IP_CONFIG_METHOD,
|
||||
NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
|
||||
NM_SETTING_IP_CONFIG_GATEWAY,
|
||||
"10.0.0.1",
|
||||
NULL);
|
||||
nmtst_setting_ip_config_add_address(s_ip4, "192.168.1.5", 24);
|
||||
nmtst_setting_ip_config_add_route(s_ip4, "10.0.0.0", 8, "172.16.0.1", 100);
|
||||
nm_connection_add_setting(conn, NM_SETTING(s_ip4));
|
||||
|
||||
result = nm_connection_get_unreachable_gateways(conn);
|
||||
g_assert(result);
|
||||
g_assert_cmpint(g_strv_length((char **) result), ==, 2);
|
||||
g_assert_cmpstr(result[0], ==, "10.0.0.1");
|
||||
g_assert_cmpstr(result[1], ==, "172.16.0.1");
|
||||
nm_clear_g_free(&result);
|
||||
g_object_unref(conn);
|
||||
}
|
||||
|
||||
/* Test deduplication */
|
||||
{
|
||||
conn =
|
||||
nmtst_create_minimal_connection("test-ugw", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
|
||||
s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new();
|
||||
g_object_set(s_ip4,
|
||||
NM_SETTING_IP_CONFIG_METHOD,
|
||||
NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
|
||||
NM_SETTING_IP_CONFIG_GATEWAY,
|
||||
"192.168.1.1",
|
||||
NULL);
|
||||
nmtst_setting_ip_config_add_address(s_ip4, "192.168.1.5", 24);
|
||||
nmtst_setting_ip_config_add_route(s_ip4, "10.0.0.0", 16, "172.16.0.1", 100);
|
||||
nmtst_setting_ip_config_add_route(s_ip4, "10.1.0.0", 16, "172.16.0.1", 100);
|
||||
nmtst_setting_ip_config_add_route(s_ip4, "10.2.0.0", 16, "172.16.0.1", 100);
|
||||
nm_connection_add_setting(conn, NM_SETTING(s_ip4));
|
||||
|
||||
result = nm_connection_get_unreachable_gateways(conn);
|
||||
g_assert(result);
|
||||
g_assert_cmpint(g_strv_length((char **) result), ==, 1);
|
||||
g_assert_cmpstr(result[0], ==, "172.16.0.1");
|
||||
nm_clear_g_free(&result);
|
||||
g_object_unref(conn);
|
||||
}
|
||||
|
||||
/* IPv6 gateway reachable via address prefix route */
|
||||
{
|
||||
conn =
|
||||
nmtst_create_minimal_connection("test-ugw", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
|
||||
s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new();
|
||||
g_object_set(s_ip6,
|
||||
NM_SETTING_IP_CONFIG_METHOD,
|
||||
NM_SETTING_IP6_CONFIG_METHOD_MANUAL,
|
||||
NM_SETTING_IP_CONFIG_GATEWAY,
|
||||
"fd01::1",
|
||||
NULL);
|
||||
nmtst_setting_ip_config_add_address(s_ip6, "fd01::10", 64);
|
||||
nm_connection_add_setting(conn, NM_SETTING(s_ip6));
|
||||
|
||||
result = nm_connection_get_unreachable_gateways(conn);
|
||||
g_assert(!result);
|
||||
g_object_unref(conn);
|
||||
}
|
||||
|
||||
/* IPv6 gateway NOT reachable */
|
||||
{
|
||||
conn =
|
||||
nmtst_create_minimal_connection("test-ugw", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
|
||||
s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new();
|
||||
g_object_set(s_ip6,
|
||||
NM_SETTING_IP_CONFIG_METHOD,
|
||||
NM_SETTING_IP6_CONFIG_METHOD_MANUAL,
|
||||
NM_SETTING_IP_CONFIG_GATEWAY,
|
||||
"fd02::1",
|
||||
NULL);
|
||||
nmtst_setting_ip_config_add_address(s_ip6, "fd01::10", 64);
|
||||
nm_connection_add_setting(conn, NM_SETTING(s_ip6));
|
||||
|
||||
result = nm_connection_get_unreachable_gateways(conn);
|
||||
g_assert(result);
|
||||
g_assert_cmpint(g_strv_length((char **) result), ==, 1);
|
||||
g_assert_cmpstr(result[0], ==, "fd02::1");
|
||||
nm_clear_g_free(&result);
|
||||
g_object_unref(conn);
|
||||
}
|
||||
|
||||
/* Multiple addresses, gateway reachable via second address */
|
||||
{
|
||||
conn =
|
||||
nmtst_create_minimal_connection("test-ugw", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
|
||||
s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new();
|
||||
g_object_set(s_ip4,
|
||||
NM_SETTING_IP_CONFIG_METHOD,
|
||||
NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
|
||||
NM_SETTING_IP_CONFIG_GATEWAY,
|
||||
"10.0.0.1",
|
||||
NULL);
|
||||
nmtst_setting_ip_config_add_address(s_ip4, "192.168.1.5", 24);
|
||||
nmtst_setting_ip_config_add_address(s_ip4, "10.0.0.5", 24);
|
||||
nm_connection_add_setting(conn, NM_SETTING(s_ip4));
|
||||
|
||||
result = nm_connection_get_unreachable_gateways(conn);
|
||||
g_assert(!result);
|
||||
g_object_unref(conn);
|
||||
}
|
||||
|
||||
/* Unreachable gateways in both IPv4 and IPv6 */
|
||||
{
|
||||
conn =
|
||||
nmtst_create_minimal_connection("test-ugw", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
|
||||
s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new();
|
||||
g_object_set(s_ip4,
|
||||
NM_SETTING_IP_CONFIG_METHOD,
|
||||
NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
|
||||
NM_SETTING_IP_CONFIG_GATEWAY,
|
||||
"10.0.0.1",
|
||||
NULL);
|
||||
nmtst_setting_ip_config_add_address(s_ip4, "192.168.1.5", 24);
|
||||
nm_connection_add_setting(conn, NM_SETTING(s_ip4));
|
||||
|
||||
s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new();
|
||||
g_object_set(s_ip6,
|
||||
NM_SETTING_IP_CONFIG_METHOD,
|
||||
NM_SETTING_IP6_CONFIG_METHOD_MANUAL,
|
||||
NM_SETTING_IP_CONFIG_GATEWAY,
|
||||
"fd02::1",
|
||||
NULL);
|
||||
nmtst_setting_ip_config_add_address(s_ip6, "fd01::10", 64);
|
||||
nm_connection_add_setting(conn, NM_SETTING(s_ip6));
|
||||
|
||||
result = nm_connection_get_unreachable_gateways(conn);
|
||||
g_assert(result);
|
||||
g_assert_cmpint(g_strv_length((char **) result), ==, 2);
|
||||
g_assert_cmpstr(result[0], ==, "10.0.0.1");
|
||||
g_assert_cmpstr(result[1], ==, "fd02::1");
|
||||
nm_clear_g_free(&result);
|
||||
g_object_unref(conn);
|
||||
}
|
||||
|
||||
/* Onlink and IPv6-link-local routes */
|
||||
{
|
||||
NMIPRoute *route;
|
||||
|
||||
conn =
|
||||
nmtst_create_minimal_connection("test-ugw", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
|
||||
|
||||
s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new();
|
||||
g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, NULL);
|
||||
nmtst_setting_ip_config_add_address(s_ip4, "192.168.1.5", 24);
|
||||
|
||||
route = nm_ip_route_new(AF_INET, "10.0.0.1", 8, "192.168.20.1", 100, NULL);
|
||||
g_assert(route);
|
||||
nm_ip_route_set_attribute(route, NM_IP_ROUTE_ATTRIBUTE_ONLINK, g_variant_new_boolean(TRUE));
|
||||
g_assert(nm_setting_ip_config_add_route(s_ip4, route));
|
||||
nm_ip_route_unref(route);
|
||||
|
||||
nm_connection_add_setting(conn, NM_SETTING(s_ip4));
|
||||
|
||||
s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new();
|
||||
g_object_set(s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_MANUAL, NULL);
|
||||
nmtst_setting_ip_config_add_address(s_ip6, "fd01::10", 64);
|
||||
nm_connection_add_setting(conn, NM_SETTING(s_ip6));
|
||||
|
||||
route = nm_ip_route_new(AF_INET6, "fd02::", 64, "fd03::1111", 100, NULL);
|
||||
g_assert(route);
|
||||
nm_ip_route_set_attribute(route, NM_IP_ROUTE_ATTRIBUTE_ONLINK, g_variant_new_boolean(TRUE));
|
||||
g_assert(nm_setting_ip_config_add_route(s_ip6, route));
|
||||
nm_ip_route_unref(route);
|
||||
|
||||
nmtst_setting_ip_config_add_route(s_ip6, "fd04::", 64, "fe80::1111", 100);
|
||||
|
||||
result = nm_connection_get_unreachable_gateways(conn);
|
||||
g_assert(!result);
|
||||
g_object_unref(conn);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMTST_DEFINE();
|
||||
|
||||
int
|
||||
|
|
@ -11963,6 +12285,7 @@ main(int argc, char **argv)
|
|||
g_test_add_func("/core/general/test_dns_uri_get_legacy", test_dns_uri_parse_plain);
|
||||
g_test_add_func("/core/general/test_dns_uri_normalize", test_dns_uri_normalize);
|
||||
g_test_add_func("/core/general/test_dhcp_iaid_hexstr", test_dhcp_iaid_hexstr);
|
||||
g_test_add_func("/core/general/test_unreachable_gateways", test_unreachable_gateways);
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5645,6 +5645,7 @@ connection_warnings(NmCli *nmc, NMConnection *connection)
|
|||
guint i, found;
|
||||
const char *id;
|
||||
const char *deprecated;
|
||||
gs_free char *gw_warning = NULL;
|
||||
|
||||
deprecated = nmc_connection_check_deprecated(NM_CONNECTION(connection));
|
||||
if (deprecated)
|
||||
|
|
@ -5673,6 +5674,10 @@ connection_warnings(NmCli *nmc, NMConnection *connection)
|
|||
nm_connection_get_uuid(NM_CONNECTION(connection)),
|
||||
found);
|
||||
}
|
||||
|
||||
gw_warning = nm_connection_get_unreachable_gateways_warning(connection, TRUE);
|
||||
if (gw_warning)
|
||||
nmc_printerr("Warning: %s.\n", gw_warning);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include "nmt-editor.h"
|
||||
|
||||
#include "libnm-core-aux-intern/nm-libnm-core-utils.h"
|
||||
#include "nm-utils.h"
|
||||
|
||||
#include "nmtui.h"
|
||||
|
|
@ -153,10 +154,16 @@ save_connection_and_exit(NmtNewtButton *button, gpointer user_data)
|
|||
NmtEditor *editor = user_data;
|
||||
NmtEditorPrivate *priv = NMT_EDITOR_GET_PRIVATE(editor);
|
||||
NmtSyncOp op;
|
||||
GError *error = NULL;
|
||||
GError *error = NULL;
|
||||
gs_free char *gw_warning = NULL;
|
||||
|
||||
nm_connection_replace_settings_from_connection(priv->orig_connection, priv->edit_connection);
|
||||
|
||||
gw_warning = nm_connection_get_unreachable_gateways_warning(priv->orig_connection, TRUE);
|
||||
if (gw_warning) {
|
||||
nmt_newt_message_dialog(_("Warning: %s"), gw_warning);
|
||||
}
|
||||
|
||||
nmt_sync_op_init(&op);
|
||||
if (NM_IS_REMOTE_CONNECTION(priv->orig_connection)) {
|
||||
nm_remote_connection_commit_changes_async(NM_REMOTE_CONNECTION(priv->orig_connection),
|
||||
|
|
|
|||
15
src/tests/client/test-client.check-on-disk/test_005.expected
Normal file
15
src/tests/client/test-client.check-on-disk/test_005.expected
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
size: 683
|
||||
location: src/tests/client/test-client.py:test_005()/1
|
||||
cmd: $NMCLI c add type ethernet ifname eth0 con-name con-xx1 ipv4.method manual ipv4.addresses 192.168.1.1/24 ipv4.gateway 192.168.2.1 ipv4.routes '192.168.4.4 192.168.4.1'
|
||||
lang: C
|
||||
returncode: 0
|
||||
stdout: 80 bytes
|
||||
>>>
|
||||
Connection 'con-xx1' (UUID-con-xx1-REPLACED-REPLACED-REPLA) successfully added.
|
||||
|
||||
<<<
|
||||
stderr: 300 bytes
|
||||
>>>
|
||||
Warning: the following gateways are not directly reachable from any configured address or route: 192.168.2.1, 192.168.4.1. NetworkManager currently adds on-link routes for them automatically, but this will change in the future. Consider adding addresses or routes whose subnets cover these gateways.
|
||||
|
||||
<<<
|
||||
|
|
@ -2222,6 +2222,41 @@ class TestNmcli(unittest.TestCase):
|
|||
replace_stdout=replace_uuids,
|
||||
)
|
||||
|
||||
@nm_test
|
||||
def test_005(self):
|
||||
self.init_001()
|
||||
|
||||
replace_uuids = []
|
||||
|
||||
replace_uuids.append(
|
||||
self.ctx.srv.ReplaceTextConUuid(
|
||||
"con-xx1", "UUID-con-xx1-REPLACED-REPLACED-REPLA"
|
||||
)
|
||||
)
|
||||
|
||||
# Check the warning about unreachable gateways
|
||||
self.call_nmcli(
|
||||
[
|
||||
"c",
|
||||
"add",
|
||||
"type",
|
||||
"ethernet",
|
||||
"ifname",
|
||||
"eth0",
|
||||
"con-name",
|
||||
"con-xx1",
|
||||
"ipv4.method",
|
||||
"manual",
|
||||
"ipv4.addresses",
|
||||
"192.168.1.1/24",
|
||||
"ipv4.gateway",
|
||||
"192.168.2.1",
|
||||
"ipv4.routes",
|
||||
"192.168.4.4 192.168.4.1",
|
||||
],
|
||||
replace_stdout=replace_uuids,
|
||||
)
|
||||
|
||||
@nm_test_no_dbus
|
||||
def test_offline(self):
|
||||
# Make sure we're not using D-Bus
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue