diff --git a/src/nm-cloud-setup/main.c b/src/nm-cloud-setup/main.c index d2a5a1cf5e..f27226a8bf 100644 --- a/src/nm-cloud-setup/main.c +++ b/src/nm-cloud-setup/main.c @@ -396,14 +396,18 @@ _nmc_mangle_connection(NMDevice *device, gboolean *out_changed) { NMSettingIPConfig *s_ip; + NMSettingIPConfig *s_ip6; NMActiveConnection *ac; NMConnection *remote_connection; - NMSettingIPConfig *remote_s_ip = NULL; + NMSettingIPConfig *remote_s_ip = NULL; + NMSettingIPConfig *remote_s_ip6 = NULL; gsize i; gboolean addrs_changed = FALSE; + gboolean addr6s_changed = FALSE; gboolean rules_changed = FALSE; gboolean routes_changed = FALSE; gs_unref_ptrarray GPtrArray *addrs_new = NULL; + gs_unref_ptrarray GPtrArray *addr6s_new = NULL; gs_unref_ptrarray GPtrArray *rules_new = NULL; gs_unref_ptrarray GPtrArray *routes_new = NULL; @@ -418,15 +422,19 @@ _nmc_mangle_connection(NMDevice *device, /* Preserve existing L3 configuration if not a VLAN */ if (device) { if ((ac = nm_device_get_active_connection(device)) - && (remote_connection = NM_CONNECTION(nm_active_connection_get_connection(ac)))) - remote_s_ip = nm_connection_get_setting_ip4_config(remote_connection); + && (remote_connection = NM_CONNECTION(nm_active_connection_get_connection(ac)))) { + remote_s_ip = nm_connection_get_setting_ip4_config(remote_connection); + remote_s_ip6 = nm_connection_get_setting_ip6_config(remote_connection); + } } } - s_ip = nm_connection_get_setting_ip4_config(connection); - nm_assert(NM_IS_SETTING_IP4_CONFIG(s_ip)); + s_ip = nm_connection_get_setting_ip4_config(connection); + s_ip6 = nm_connection_get_setting_ip6_config(connection); + + addrs_new = g_ptr_array_new_full(config_data->ipv4s_len, (GDestroyNotify) nm_ip_address_unref); + addr6s_new = g_ptr_array_new_full(config_data->ipv6s_len, (GDestroyNotify) nm_ip_address_unref); - addrs_new = g_ptr_array_new_full(config_data->ipv4s_len, (GDestroyNotify) nm_ip_address_unref); rules_new = g_ptr_array_new_full(config_data->ipv4s_len, (GDestroyNotify) nm_ip_routing_rule_unref); routes_new = @@ -457,8 +465,16 @@ _nmc_mangle_connection(NMDevice *device, } } - if (result->num_valid_ifaces <= 1 && result->num_ipv4s <= 1) { - /* this setup only has one interface and one IPv4 address (or less). + if (remote_s_ip6) { + guint len = nm_setting_ip_config_get_num_addresses(remote_s_ip6); + for (int j = 0; j < len; j++) { + g_ptr_array_add(addr6s_new, + nm_ip_address_dup(nm_setting_ip_config_get_address(remote_s_ip6, j))); + } + } + + if (result->num_valid_ifaces <= 1 && (result->num_ipv4s + result->num_ipv6s) <= 1) { + /* this setup only has one interface and one IP address (or less). * We don't need to configure policy routing in this case. */ NM_SET_OUT(out_skipped_single_addr, TRUE); } else if (config_data->has_ipv4s && config_data->has_cidr) { @@ -537,22 +553,50 @@ _nmc_mangle_connection(NMDevice *device, } } + if (config_data->has_ipv6s) { + NMIPAddress *addr_entry; + + for (i = 0; i < config_data->ipv6s_len; i++) { + addr_entry = nm_ip_address_new_binary(AF_INET6, &config_data->ipv6s_arr[i], 128, NULL); + nm_assert(addr_entry); + g_ptr_array_add(addr6s_new, addr_entry); + } + } + for (i = 0; i < nm_g_ptr_array_len(config_data->iproutes); i++) g_ptr_array_add(routes_new, _nm_ip_route_ref(config_data->iproutes->pdata[i])); - addrs_changed = nmcs_setting_ip_replace_ipv4_addresses(s_ip, - (NMIPAddress **) addrs_new->pdata, - addrs_new->len); + if (s_ip) { + addrs_changed = nmcs_setting_ip_replace_ip_addresses(s_ip, + (NMIPAddress **) addrs_new->pdata, + addrs_new->len); - routes_changed = nmcs_setting_ip_replace_ipv4_routes(s_ip, - (NMIPRoute **) routes_new->pdata, - routes_new->len); + routes_changed = nmcs_setting_ip_replace_ipv4_routes(s_ip, + (NMIPRoute **) routes_new->pdata, + routes_new->len); - rules_changed = nmcs_setting_ip_replace_ipv4_rules(s_ip, - (NMIPRoutingRule **) rules_new->pdata, - rules_new->len); + rules_changed = nmcs_setting_ip_replace_ipv4_rules(s_ip, + (NMIPRoutingRule **) rules_new->pdata, + rules_new->len); + } - NM_SET_OUT(out_changed, addrs_changed || routes_changed || rules_changed); + if (s_ip6) { + const char *method = nm_setting_ip_config_get_method(s_ip6); + if (NM_IN_STRSET(method, + NM_SETTING_IP6_CONFIG_METHOD_IGNORE, + NM_SETTING_IP6_CONFIG_METHOD_DISABLED)) { + g_object_set(s_ip6, + NM_SETTING_IP_CONFIG_METHOD, + NM_SETTING_IP6_CONFIG_METHOD_MANUAL, + NULL); + } + + addr6s_changed = nmcs_setting_ip_replace_ip_addresses(s_ip6, + (NMIPAddress **) addr6s_new->pdata, + addr6s_new->len); + } + + NM_SET_OUT(out_changed, addrs_changed || addr6s_changed || routes_changed || rules_changed); } /*****************************************************************************/ @@ -612,9 +656,9 @@ try_again: return any_changes; } - if (!nm_connection_get_setting_ip4_config(applied_connection)) { - _LOGD("config device %s: skip applied connection due to missing IPv4 configuration", - hwaddr); + if (!nm_connection_get_setting_ip4_config(applied_connection) + && !nm_connection_get_setting_ip6_config(applied_connection)) { + _LOGD("config device %s: skip applied connection due to missing IP configuration", hwaddr); return any_changes; } @@ -739,7 +783,11 @@ _config_ethernet(SigTermData *sigterm_data, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, NULL)); - + nm_connection_add_setting(connection, + g_object_new(NM_TYPE_SETTING_IP6_CONFIG, + NM_SETTING_IP_CONFIG_METHOD, + NM_SETTING_IP6_CONFIG_METHOD_MANUAL, + NULL)); nm_connection_add_setting(connection, g_object_new(NM_TYPE_SETTING_WIRED, NM_SETTING_WIRED_MAC_ADDRESS, diff --git a/src/nm-cloud-setup/nm-cloud-setup-utils.c b/src/nm-cloud-setup/nm-cloud-setup-utils.c index 3889cff29a..df6dab1e3a 100644 --- a/src/nm-cloud-setup/nm-cloud-setup-utils.c +++ b/src/nm-cloud-setup/nm-cloud-setup-utils.c @@ -367,9 +367,9 @@ nmcs_utils_uri_complete_interned(const char *uri) /*****************************************************************************/ gboolean -nmcs_setting_ip_replace_ipv4_addresses(NMSettingIPConfig *s_ip, - NMIPAddress **entries_arr, - guint entries_len) +nmcs_setting_ip_replace_ip_addresses(NMSettingIPConfig *s_ip, + NMIPAddress **entries_arr, + guint entries_len) { gboolean any_changes = FALSE; guint i_next; diff --git a/src/nm-cloud-setup/nm-cloud-setup-utils.h b/src/nm-cloud-setup/nm-cloud-setup-utils.h index 6b3be11f1c..7ebaa392ed 100644 --- a/src/nm-cloud-setup/nm-cloud-setup-utils.h +++ b/src/nm-cloud-setup/nm-cloud-setup-utils.h @@ -135,9 +135,9 @@ const char *nmcs_utils_uri_complete_interned(const char *uri); /*****************************************************************************/ -gboolean nmcs_setting_ip_replace_ipv4_addresses(NMSettingIPConfig *s_ip, - NMIPAddress **entries_arr, - guint entries_len); +gboolean nmcs_setting_ip_replace_ip_addresses(NMSettingIPConfig *s_ip, + NMIPAddress **entries_arr, + guint entries_len); gboolean nmcs_setting_ip_replace_ipv4_routes(NMSettingIPConfig *s_ip, NMIPRoute **entries_arr, diff --git a/src/nm-cloud-setup/nmcs-provider.c b/src/nm-cloud-setup/nmcs-provider.c index 251749ba79..ff6e067f17 100644 --- a/src/nm-cloud-setup/nmcs-provider.c +++ b/src/nm-cloud-setup/nmcs-provider.c @@ -74,6 +74,7 @@ nmcs_provider_get_config_result_new(GHashTable *iface_datas) GHashTableIter h_iter; guint num_valid_ifaces = 0; guint num_ipv4s = 0; + guint num_ipv6s = 0; GPtrArray *ptrarr; guint n_iface_datas; @@ -86,6 +87,7 @@ nmcs_provider_get_config_result_new(GHashTable *iface_datas) if (nmcs_provider_get_config_iface_data_is_valid(iface_data)) { num_valid_ifaces++; num_ipv4s += iface_data->ipv4s_len; + num_ipv6s += iface_data->ipv6s_len; } g_ptr_array_add(ptrarr, (gpointer) iface_data); } @@ -104,6 +106,7 @@ nmcs_provider_get_config_result_new(GHashTable *iface_datas) (const NMCSProviderGetConfigIfaceData **) g_ptr_array_free(ptrarr, FALSE), .num_valid_ifaces = num_valid_ifaces, .num_ipv4s = num_ipv4s, + .num_ipv6s = num_ipv6s, }; #if NM_MORE_ASSERTS > 5 diff --git a/src/nm-cloud-setup/nmcs-provider.h b/src/nm-cloud-setup/nmcs-provider.h index 95a591c651..c65e568f53 100644 --- a/src/nm-cloud-setup/nmcs-provider.h +++ b/src/nm-cloud-setup/nmcs-provider.h @@ -24,6 +24,9 @@ typedef struct { in_addr_t *ipv4s_arr; gsize ipv4s_len; + struct in6_addr *ipv6s_arr; + gsize ipv6s_len; + /* If the interface was seen, get_config() should set this to a * unique, increasing, positive index. If the interface is requested, * it is initialized to -1. */ @@ -33,6 +36,7 @@ typedef struct { in_addr_t gateway; guint8 cidr_prefix; bool has_ipv4s : 1; + bool has_ipv6s : 1; bool has_cidr : 1; bool has_gateway : 1; @@ -65,7 +69,7 @@ static inline gboolean nmcs_provider_get_config_iface_data_is_valid(const NMCSProviderGetConfigIfaceData *config_data) { return config_data && config_data->iface_idx >= 0 - && ((config_data->has_ipv4s && config_data->has_cidr) + && ((config_data->has_ipv4s && config_data->has_cidr) || config_data->has_ipv6s || nm_g_ptr_array_len(config_data->iproutes) > 0); } @@ -83,6 +87,7 @@ typedef struct { /* the number of IPv4 addresses over all valid iface_datas. */ guint num_ipv4s; + guint num_ipv6s; guint n_iface_datas; diff --git a/src/nm-cloud-setup/tests/test-cloud-setup-general.c b/src/nm-cloud-setup/tests/test-cloud-setup-general.c index c863500931..9524b054c1 100644 --- a/src/nm-cloud-setup/tests/test-cloud-setup-general.c +++ b/src/nm-cloud-setup/tests/test-cloud-setup-general.c @@ -54,7 +54,7 @@ _test_ri4a(const char *const *addrs_before, const char *const *addrs_new) NM_PTRARRAY_LEN(addrs_before)); g_assert_cmpint(arr->len, ==, n); - changed = nmcs_setting_ip_replace_ipv4_addresses(s_ip, (NMIPAddress **) arr->pdata, arr->len); + changed = nmcs_setting_ip_replace_ip_addresses(s_ip, (NMIPAddress **) arr->pdata, arr->len); g_assert_cmpint(changed, !=, nm_strv_equal(addrs_before, addrs_new)); g_assert_cmpint(nm_setting_ip_config_get_num_addresses(s_ip), ==, n); diff --git a/src/tests/client/test-client.py b/src/tests/client/test-client.py index 62b72b795f..a534d2710d 100755 --- a/src/tests/client/test-client.py +++ b/src/tests/client/test-client.py @@ -2382,6 +2382,9 @@ class TestNmCloudSetup(unittest.TestCase): _ip1 = "172.31.26.249" _ip2 = "172.31.176.249" + _ip6_1 = "2001:db8:abab:abab:abab::" + _ip6_2 = "2001:db8:cdcd:cdcd:cdcd::" + def cloud_setup_test(func): """ Runs the mock NetworkManager along with a mock cloud metadata service. @@ -2449,11 +2452,12 @@ class TestNmCloudSetup(unittest.TestCase): self.ctx.srv.op_AddObj("WiredDevice", iface="eth1", mac=self._mac2) def _mock_connection1(self): - # Active connection that has IPv4 configured for device1 + # Active connection that has IPv4 and IPv6 configured for device1 self.ctx.srv.addAndActivateConnection( { "connection": {"type": "802-3-ethernet", "id": "con-eth0"}, "ipv4": {"method": "auto"}, + "ipv6": {"method": "auto"}, }, "/org/freedesktop/NetworkManager/Devices/1", delay=0,