diff --git a/NEWS b/NEWS index 9280a71c45..403c4e2b90 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,10 @@ the later release. USE AT YOUR OWN RISK. NOT RECOMMENDED FOR PRODUCTION USE! * Add support for route type "throw". +* Static IPv6 addresses from "ipv6.addresses" are now preferred over + addresses from DHCPv6, which are preferred over addresses from autoconf. + This affects IPv6 source address selection, if the rules from + RFC 6724, section 5 don't give a exhaustive match. * Wi-Fi hotspots will use a (stable) random channel number unless one is chosen manually. * Don't use unsupported SAE/WPA3 mode for AP mode. diff --git a/src/core/nm-l3-config-data.c b/src/core/nm-l3-config-data.c index 5ab2f6b8d0..2567a878c5 100644 --- a/src/core/nm-l3-config-data.c +++ b/src/core/nm-l3-config-data.c @@ -2755,7 +2755,7 @@ _init_from_connection_ip(NML3ConfigData *self, int addr_family, NMConnection *co nroutes = nm_setting_ip_config_get_num_routes(s_ip); for (i = 0; i < nroutes; i++) { - NMIPRoute *s_route = nm_setting_ip_config_get_route(s_ip, i); + NMIPRoute *s_route; NMPlatformIPXRoute r; NMIPAddr network_bin; NMIPAddr next_hop_bin; @@ -2763,6 +2763,12 @@ _init_from_connection_ip(NML3ConfigData *self, int addr_family, NMConnection *co guint32 metric; gboolean metric_any; guint plen; + guint i_idx; + + /* Routes in ipv6.addresses are in reversed priority order. */ + i_idx = IS_IPv4 ? i : (nroutes - i - 1); + + s_route = nm_setting_ip_config_get_route(s_ip, i_idx); nm_assert(nm_ip_route_get_family(s_route) == addr_family); diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c index 9f01004720..b29c07de84 100644 --- a/src/libnm-platform/nm-platform.c +++ b/src/libnm-platform/nm-platform.c @@ -4073,8 +4073,7 @@ nm_platform_ip_address_sync(NMPlatform *self, } } - /* @known_addresses (IPv4) are in decreasing priority order (highest priority addresses first). - * @known_addresses (IPv6) are in increasing priority order (highest priority addresses last) (we will sort them by scope next). */ + /* @known_addresses are in decreasing priority order (highest priority addresses first). */ /* The order we want to enforce is only among addresses with the same * scope, as the kernel keeps addresses sorted by scope. Therefore, @@ -4082,7 +4081,7 @@ nm_platform_ip_address_sync(NMPlatform *self, * unnecessary change the order of addresses with different scopes. */ if (!IS_IPv4) { if (known_addresses) - g_ptr_array_sort_with_data(known_addresses, ip6_address_scope_cmp_ascending, NULL); + g_ptr_array_sort_with_data(known_addresses, ip6_address_scope_cmp_descending, NULL); } if (!_addr_array_clean_expired(addr_family, @@ -4244,7 +4243,6 @@ nm_platform_ip_address_sync(NMPlatform *self, ip4_addr_subnets_destroy_index(plat_subnets, plat_addresses); ip4_addr_subnets_destroy_index(known_subnets, known_addresses); } else { - guint known_addresses_len; IP6AddrScope cur_scope; gboolean delete_remaining_addrs; @@ -4253,8 +4251,6 @@ nm_platform_ip_address_sync(NMPlatform *self, g_ptr_array_sort_with_data(plat_addresses, ip6_address_scope_cmp_descending, NULL); - known_addresses_len = nm_g_ptr_array_len(known_addresses); - /* First, check that existing addresses have a matching plen as the ones * we are about to configure (@known_addresses). If not, delete them. */ for (i_plat = 0; i_plat < plat_addresses->len; i_plat++) { @@ -4299,7 +4295,8 @@ nm_platform_ip_address_sync(NMPlatform *self, cur_scope = IP6_ADDR_SCOPE_LOOPBACK; delete_remaining_addrs = FALSE; i_plat = plat_addresses->len; - i_know = 0; + i_know = nm_g_ptr_array_len(known_addresses); + while (i_plat > 0) { const NMPlatformIP6Address *plat_addr = NMP_OBJECT_CAST_IP6_ADDRESS(plat_addresses->pdata[--i_plat]); @@ -4317,9 +4314,9 @@ nm_platform_ip_address_sync(NMPlatform *self, if (!delete_remaining_addrs) { delete_remaining_addrs = TRUE; - for (; i_know < known_addresses_len; i_know++) { + while (i_know > 0) { const NMPlatformIP6Address *know_addr = - NMP_OBJECT_CAST_IP6_ADDRESS(known_addresses->pdata[i_know]); + NMP_OBJECT_CAST_IP6_ADDRESS(known_addresses->pdata[--i_know]); IP6AddrScope know_scope; if (!know_addr) @@ -4356,13 +4353,21 @@ next_plat:; /* Add missing addresses. New addresses are added by kernel with top * priority. */ - for (i_know = 0; i_know < known_addresses->len; i_know++) { + for (i = 0; i < known_addresses->len; i++) { const NMPObject *plat_obj; const NMPObject *known_obj; const NMPlatformIPXAddress *known_address; guint32 lifetime; guint32 preferred; + /* IPv4 addresses we need to add in the order most important first. + * IPv6 addresses we need to add in the reverse order with least + * important first. Kernel will interpret the last address as most + * important. + * + * @known_addresses is always in the order most-important-first. */ + i_know = IS_IPv4 ? i : (known_addresses->len - i - 1u); + known_obj = known_addresses->pdata[i_know]; if (!known_obj) continue;