summary refs log tree commit diff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/devices/nm-device.c15
-rw-r--r--src/core/devices/wifi/nm-device-wifi.c23
-rw-r--r--src/core/devices/wwan/nm-modem-ofono.c17
-rw-r--r--src/core/dhcp/nm-dhcp-client.c1
-rw-r--r--src/core/ndisc/nm-ndisc.c19
-rw-r--r--src/core/nm-core-utils.c10
-rw-r--r--src/core/nm-l3-config-data.c54
-rw-r--r--src/core/nm-manager.c10
-rw-r--r--src/core/platform/nm-fake-platform.c2
-rw-r--r--src/core/platform/tests/test-common.c19
-rw-r--r--src/core/platform/tests/test-link.c133
-rw-r--r--src/core/settings/nm-settings-connection.c8
-rw-r--r--src/core/settings/nm-settings-connection.h2
-rw-r--r--src/core/supplicant/nm-supplicant-config.c7
-rw-r--r--src/core/supplicant/nm-supplicant-config.h6
-rw-r--r--src/core/supplicant/tests/test-supplicant-config.c2
16 files changed, 221 insertions, 107 deletions
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c
index 3565c04d..d080b540 100644
--- a/src/core/devices/nm-device.c
+++ b/src/core/devices/nm-device.c
@@ -10339,14 +10339,14 @@ _dev_ipdhcpx_notify(NMDhcpClient *client, const NMDhcpClientNotifyData *notify_d
 
         if (notify_data->lease_update.accepted) {
             nm_manager_write_device_state(priv->manager, self, NULL);
+            nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP_CHANGE_X(IS_IPv4),
+                                      self,
+                                      NULL,
+                                      NULL,
+                                      NULL,
+                                      NULL);
             if (priv->ipdhcp_data_x[IS_IPv4].state != NM_DEVICE_IP_STATE_READY) {
                 _dev_ipdhcpx_set_state(self, addr_family, NM_DEVICE_IP_STATE_READY);
-                nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP_CHANGE_X(IS_IPv4),
-                                          self,
-                                          NULL,
-                                          NULL,
-                                          NULL,
-                                          NULL);
                 _dev_ip_state_check_async(self, addr_family);
             }
         }
@@ -14542,6 +14542,9 @@ _set_unmanaged_flags(NMDevice           *self,
 
     if (transition_state) {
         new_state = was_managed ? NM_DEVICE_STATE_UNMANAGED : NM_DEVICE_STATE_UNAVAILABLE;
+        if (new_state == NM_DEVICE_STATE_UNMANAGED) {
+            _cancel_activation(self);
+        }
         if (now)
             nm_device_state_changed(self, new_state, reason);
         else
diff --git a/src/core/devices/wifi/nm-device-wifi.c b/src/core/devices/wifi/nm-device-wifi.c
index 171743d0..03625f8d 100644
--- a/src/core/devices/wifi/nm-device-wifi.c
+++ b/src/core/devices/wifi/nm-device-wifi.c
@@ -2912,10 +2912,11 @@ supplicant_connection_timeout_cb(gpointer user_data)
 }
 
 static NMSupplicantConfig *
-build_supplicant_config(NMDeviceWifi *self,
-                        NMConnection *connection,
-                        guint32       fixed_freq,
-                        GError      **error)
+build_supplicant_config(NMDeviceWifi         *self,
+                        NMSettingsConnection *sett_conn,
+                        NMConnection         *connection,
+                        guint32               fixed_freq,
+                        GError              **error)
 {
     NMDeviceWifiPrivate          *priv   = NM_DEVICE_WIFI_GET_PRIVATE(self);
     NMSupplicantConfig           *config = NULL;
@@ -2944,7 +2945,10 @@ build_supplicant_config(NMDeviceWifi *self,
         goto error;
     }
 
-    if (!nm_supplicant_config_add_bgscan(config, connection, error)) {
+    if (!nm_supplicant_config_add_bgscan(config,
+                                         connection,
+                                         nm_settings_connection_get_num_seen_bssids(sett_conn),
+                                         error)) {
         g_prefix_error(error, "bgscan: ");
         goto error;
     }
@@ -3227,7 +3231,8 @@ ensure_hotspot_frequency(NMDeviceWifi *self, NMSettingWireless *s_wifi, NMWifiAP
 
     freq = nm_platform_wifi_find_frequency(nm_device_get_platform(device),
                                            nm_device_get_ifindex(device),
-                                           rnd_freqs);
+                                           rnd_freqs,
+                                           TRUE);
     if (freq == 0)
         freq = rnd_freqs[0];
 
@@ -3278,6 +3283,7 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
     NMActRequest                       *req;
     NMWifiAP                           *ap;
     NMConnection                       *connection;
+    NMSettingsConnection               *sett_conn;
     const char                         *setting_name;
     NMSettingWireless                  *s_wireless;
     GError                             *error = NULL;
@@ -3301,6 +3307,9 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
 
     ap_mode = nm_wifi_ap_get_mode(ap);
 
+    sett_conn = nm_act_request_get_settings_connection(req);
+    nm_assert(sett_conn);
+
     connection = nm_act_request_get_applied_connection(req);
     s_wireless = nm_connection_get_setting_wireless(connection);
     nm_assert(s_wireless);
@@ -3349,7 +3358,7 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
         set_powersave(device);
 
     /* Build up the supplicant configuration */
-    config = build_supplicant_config(self, connection, nm_wifi_ap_get_freq(ap), &error);
+    config = build_supplicant_config(self, sett_conn, connection, nm_wifi_ap_get_freq(ap), &error);
     if (!config) {
         _LOGE(LOGD_DEVICE | LOGD_WIFI,
               "Activation: (wifi) couldn't build wireless configuration: %s",
diff --git a/src/core/devices/wwan/nm-modem-ofono.c b/src/core/devices/wwan/nm-modem-ofono.c
index 33a19e93..de105bbd 100644
--- a/src/core/devices/wwan/nm-modem-ofono.c
+++ b/src/core/devices/wwan/nm-modem-ofono.c
@@ -1320,9 +1320,18 @@ handle_settings(NMModemOfono *self, GVariant *v_dict)
         }
     }
 
-    if (g_variant_lookup(v_dict, "MessageProxy", "&s", &s)) {
-        _LOGI("MessageProxy: %s", s);
-        if (s && nm_inet_parse_bin(AF_INET, s, NULL, &address_network)) {
+    if (g_variant_lookup(v_dict, "Proxy", "&s", &s) && s) {
+        gs_free char *proxy = g_strdup(s);
+        char         *colon;
+
+        _LOGI("(MMS) Proxy: %s", s);
+
+        /* Strip the port out. We can do this as we know this is IPv4. */
+        colon = strchr(proxy, ':');
+        if (colon)
+            *colon = '\0';
+
+        if (nm_inet_parse_bin(AF_INET, proxy, NULL, &address_network)) {
             const NMPlatformIP4Route mms_route = {
                 .network       = address_network,
                 .plen          = 32,
@@ -1335,7 +1344,7 @@ handle_settings(NMModemOfono *self, GVariant *v_dict)
 
             nm_l3_config_data_add_route_4(priv->l3cd_4, &mms_route);
         } else
-            _LOGW("invalid MessageProxy: %s", s);
+            _LOGW("invalid (MMS) Proxy: %s", s);
     }
 
     ret = TRUE;
diff --git a/src/core/dhcp/nm-dhcp-client.c b/src/core/dhcp/nm-dhcp-client.c
index 1fc2d944..b10ce410 100644
--- a/src/core/dhcp/nm-dhcp-client.c
+++ b/src/core/dhcp/nm-dhcp-client.c
@@ -871,6 +871,7 @@ _nm_dhcp_client_notify(NMDhcpClient         *self,
         nm_clear_g_source_inst(&priv->previous_lease_timeout_source);
 
     nm_l3_config_data_reset(&priv->l3cd_curr, priv->l3cd_next);
+    priv->l3cfg_notify.wait_ipv6_dad = FALSE;
 
     if (client_event_type == NM_DHCP_CLIENT_EVENT_TYPE_BOUND && priv->l3cd_curr
         && nm_l3_config_data_get_num_addresses(priv->l3cd_curr, priv->config.addr_family) > 0)
diff --git a/src/core/ndisc/nm-ndisc.c b/src/core/ndisc/nm-ndisc.c
index 39a4df48..20dd2121 100644
--- a/src/core/ndisc/nm-ndisc.c
+++ b/src/core/ndisc/nm-ndisc.c
@@ -10,6 +10,7 @@
 #include <arpa/inet.h>
 #include <stdlib.h>
 
+#include "libnm-glib-aux/nm-random-utils.h"
 #include "libnm-platform/nm-platform-utils.h"
 #include "libnm-platform/nm-platform.h"
 #include "libnm-platform/nmp-netns.h"
@@ -858,7 +859,7 @@ solicit_retransmit_time_jitter(gint32 solicit_retransmit_time_msec)
     ten_percent = NM_MAX(1, solicit_retransmit_time_msec / 10);
 
     return solicit_retransmit_time_msec - ten_percent
-           + ((gint32) (g_random_int() % (2u * ((guint32) ten_percent))));
+           + ((gint32) (nm_random_u32() % (2u * ((guint32) ten_percent))));
 }
 
 static gboolean
@@ -936,7 +937,7 @@ solicit_timer_start(NMNDisc *ndisc)
      * a suitable delay in 2021. Wait only up to 250 msec instead. */
 
     delay_msec =
-        g_random_int() % ((guint32) (NM_NDISC_RFC4861_MAX_RTR_SOLICITATION_DELAY * 1000 / 4));
+        nm_random_u32() % ((guint32) (NM_NDISC_RFC4861_MAX_RTR_SOLICITATION_DELAY * 1000 / 4));
 
     _LOGD("solicit: schedule sending first solicitation (of %d) in %.3f seconds",
           priv->config.router_solicitations,
@@ -974,8 +975,9 @@ announce_router(NMNDisc *ndisc)
 
         /* Schedule next initial announcement retransmit. */
         priv->send_ra_id =
-            g_timeout_add_seconds(g_random_int_range(NM_NDISC_ROUTER_ADVERT_DELAY,
-                                                     NM_NDISC_ROUTER_ADVERT_INITIAL_INTERVAL),
+            g_timeout_add_seconds(nm_random_u64_range_full(NM_NDISC_ROUTER_ADVERT_DELAY,
+                                                           NM_NDISC_ROUTER_ADVERT_INITIAL_INTERVAL,
+                                                           FALSE),
                                   (GSourceFunc) announce_router,
                                   ndisc);
     } else {
@@ -1009,10 +1011,9 @@ announce_router_initial(NMNDisc *ndisc)
     /* Schedule the initial send rather early. Clamp the delay by minimal
      * delay and not the initial advert internal so that we start fast. */
     if (G_LIKELY(!priv->send_ra_id)) {
-        priv->send_ra_id =
-            g_timeout_add_seconds(g_random_int_range(0, NM_NDISC_ROUTER_ADVERT_DELAY),
-                                  (GSourceFunc) announce_router,
-                                  ndisc);
+        priv->send_ra_id = g_timeout_add_seconds(nm_random_u64_range(NM_NDISC_ROUTER_ADVERT_DELAY),
+                                                 (GSourceFunc) announce_router,
+                                                 ndisc);
     }
 }
 
@@ -1028,7 +1029,7 @@ announce_router_solicited(NMNDisc *ndisc)
         nm_clear_g_source(&priv->send_ra_id);
 
     if (!priv->send_ra_id) {
-        priv->send_ra_id = g_timeout_add(g_random_int_range(0, NM_NDISC_ROUTER_ADVERT_DELAY_MS),
+        priv->send_ra_id = g_timeout_add(nm_random_u64_range(NM_NDISC_ROUTER_ADVERT_DELAY_MS),
                                          (GSourceFunc) announce_router,
                                          ndisc);
     }
diff --git a/src/core/nm-core-utils.c b/src/core/nm-core-utils.c
index 500bffb9..28d9a788 100644
--- a/src/core/nm-core-utils.c
+++ b/src/core/nm-core-utils.c
@@ -3673,9 +3673,7 @@ _hw_addr_eth_complete(struct ether_addr *addr,
 
     nm_assert((ouis == NULL) ^ (ouis_len != 0));
     if (ouis) {
-        /* g_random_int() is good enough here. It uses a static GRand instance
-         * that is seeded from /dev/urandom. */
-        oui = ouis[g_random_int() % ouis_len];
+        oui = ouis[nm_random_u64_range(ouis_len)];
         g_free(ouis);
     } else {
         if (!nm_utils_hwaddr_aton(current_mac_address, &oui, ETH_ALEN))
@@ -5156,11 +5154,11 @@ nm_utils_spawn_helper(const char *const  *args,
     g_source_attach(info->timeout_source, g_main_context_get_thread_default());
 
     /* Set file descriptors as non-blocking */
-    fd_flags = fcntl(info->child_stdin, F_GETFD, 0);
+    fd_flags = fcntl(info->child_stdin, F_GETFL, 0);
     fcntl(info->child_stdin, F_SETFL, fd_flags | O_NONBLOCK);
-    fd_flags = fcntl(info->child_stdout, F_GETFD, 0);
+    fd_flags = fcntl(info->child_stdout, F_GETFL, 0);
     fcntl(info->child_stdout, F_SETFL, fd_flags | O_NONBLOCK);
-    fd_flags = fcntl(info->child_stderr, F_GETFD, 0);
+    fd_flags = fcntl(info->child_stderr, F_GETFL, 0);
     fcntl(info->child_stderr, F_SETFL, fd_flags | O_NONBLOCK);
 
     /* Watch process stdin */
diff --git a/src/core/nm-l3-config-data.c b/src/core/nm-l3-config-data.c
index 17bb9db8..d5dedb9c 100644
--- a/src/core/nm-l3-config-data.c
+++ b/src/core/nm-l3-config-data.c
@@ -2297,35 +2297,37 @@ nm_l3_config_data_cmp_full(const NML3ConfigData *a,
         const NMPObject *def_route_a = a->best_default_route_x[IS_IPv4];
         const NMPObject *def_route_b = b->best_default_route_x[IS_IPv4];
 
-        NM_CMP_SELF(def_route_a, def_route_b);
-
-        if (NM_FLAGS_HAS(flags, NM_L3_CONFIG_CMP_FLAGS_ROUTES)) {
-            NM_CMP_RETURN(nmp_object_cmp_full(def_route_a,
-                                              def_route_b,
-                                              NM_FLAGS_HAS(flags, NM_L3_CONFIG_CMP_FLAGS_IFINDEX)
-                                                  ? NMP_OBJECT_CMP_FLAGS_NONE
-                                                  : NMP_OBJECT_CMP_FLAGS_IGNORE_IFINDEX));
-        } else if (NM_FLAGS_HAS(flags, NM_L3_CONFIG_CMP_FLAGS_ROUTES_ID)) {
-            if (NM_FLAGS_HAS(flags, NM_L3_CONFIG_CMP_FLAGS_IFINDEX)) {
-                NM_CMP_DIRECT(def_route_a->obj_with_ifindex.ifindex,
-                              def_route_b->obj_with_ifindex.ifindex);
-            }
+        if (def_route_a != def_route_b) {
+            if (NM_FLAGS_HAS(flags, NM_L3_CONFIG_CMP_FLAGS_ROUTES)) {
+                NM_CMP_RETURN(
+                    nmp_object_cmp_full(def_route_a,
+                                        def_route_b,
+                                        NM_FLAGS_HAS(flags, NM_L3_CONFIG_CMP_FLAGS_IFINDEX)
+                                            ? NMP_OBJECT_CMP_FLAGS_NONE
+                                            : NMP_OBJECT_CMP_FLAGS_IGNORE_IFINDEX));
+            } else if (NM_FLAGS_HAS(flags, NM_L3_CONFIG_CMP_FLAGS_ROUTES_ID)) {
+                if (NM_FLAGS_HAS(flags, NM_L3_CONFIG_CMP_FLAGS_IFINDEX)) {
+                    NM_CMP_DIRECT(def_route_a->obj_with_ifindex.ifindex,
+                                  def_route_b->obj_with_ifindex.ifindex);
+                }
 
-            if (IS_IPv4) {
-                NMPlatformIP4Route ra = def_route_a->ip4_route;
-                NMPlatformIP4Route rb = def_route_b->ip4_route;
+                if (IS_IPv4) {
+                    NMPlatformIP4Route ra = def_route_a->ip4_route;
+                    NMPlatformIP4Route rb = def_route_b->ip4_route;
 
-                NM_CMP_DIRECT(ra.metric, rb.metric);
-                NM_CMP_DIRECT(ra.plen, rb.plen);
-                NM_CMP_RETURN_DIRECT(nm_ip4_addr_same_prefix_cmp(ra.network, rb.network, ra.plen));
-            } else {
-                NMPlatformIP6Route ra = def_route_a->ip6_route;
-                NMPlatformIP6Route rb = def_route_b->ip6_route;
+                    NM_CMP_DIRECT(ra.metric, rb.metric);
+                    NM_CMP_DIRECT(ra.plen, rb.plen);
+                    NM_CMP_RETURN_DIRECT(
+                        nm_ip4_addr_same_prefix_cmp(ra.network, rb.network, ra.plen));
+                } else {
+                    NMPlatformIP6Route ra = def_route_a->ip6_route;
+                    NMPlatformIP6Route rb = def_route_b->ip6_route;
 
-                NM_CMP_DIRECT(ra.metric, rb.metric);
-                NM_CMP_DIRECT(ra.plen, rb.plen);
-                NM_CMP_RETURN_DIRECT(
-                    nm_ip6_addr_same_prefix_cmp(&ra.network, &rb.network, ra.plen));
+                    NM_CMP_DIRECT(ra.metric, rb.metric);
+                    NM_CMP_DIRECT(ra.plen, rb.plen);
+                    NM_CMP_RETURN_DIRECT(
+                        nm_ip6_addr_same_prefix_cmp(&ra.network, &rb.network, ra.plen));
+                }
             }
         }
 
diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c
index 66547294..19ca1d1e 100644
--- a/src/core/nm-manager.c
+++ b/src/core/nm-manager.c
@@ -2582,7 +2582,7 @@ _rfkill_update_system(NMManager *self, NMRfkillType rtype, gboolean enabled)
 
     nm_assert(NM_IN_SET(rtype, NM_RFKILL_TYPE_WLAN, NM_RFKILL_TYPE_WWAN));
 
-    fd = open("/dev/rfkill", O_RDWR | O_CLOEXEC);
+    fd = open("/dev/rfkill", O_RDWR | O_NONBLOCK | O_CLOEXEC);
     if (fd < 0) {
         if (errno == EACCES)
             _LOGW(LOGD_RFKILL,
@@ -2591,14 +2591,6 @@ _rfkill_update_system(NMManager *self, NMRfkillType rtype, gboolean enabled)
         return;
     }
 
-    if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
-        _LOGW(LOGD_RFKILL,
-              "rfkill: (%s): failed to set killswitch device for "
-              "non-blocking operation",
-              nm_rfkill_type_to_string(rtype));
-        return;
-    }
-
     memset(&event, 0, sizeof(event));
     event.op = KERN_RFKILL_OP_CHANGE_ALL;
     switch (rtype) {
diff --git a/src/core/platform/nm-fake-platform.c b/src/core/platform/nm-fake-platform.c
index c92d9aef..86d6bc5f 100644
--- a/src/core/platform/nm-fake-platform.c
+++ b/src/core/platform/nm-fake-platform.c
@@ -835,7 +835,7 @@ wifi_set_mode(NMPlatform *platform, int ifindex, _NM80211Mode mode)
 }
 
 static guint32
-wifi_find_frequency(NMPlatform *platform, int ifindex, const guint32 *freqs)
+wifi_find_frequency(NMPlatform *platform, int ifindex, const guint32 *freqs, gboolean ap)
 {
     return freqs[0];
 }
diff --git a/src/core/platform/tests/test-common.c b/src/core/platform/tests/test-common.c
index 571fedfe..65bdfeae 100644
--- a/src/core/platform/tests/test-common.c
+++ b/src/core/platform/tests/test-common.c
@@ -2520,7 +2520,9 @@ nmtstp_link_ip6gre_add(NMPlatform                *platform,
     gboolean              success;
     char                  b1[NM_INET_ADDRSTRLEN];
     char                  b2[NM_INET_ADDRSTRLEN];
+    char                  encap[100];
     char                  tclass[20];
+    gboolean              encap_ignore;
     gboolean              tclass_inherit;
 
     g_assert(nm_utils_ifname_valid_kernel(name, NULL));
@@ -2530,6 +2532,7 @@ nmtstp_link_ip6gre_add(NMPlatform                *platform,
 
     _init_platform(&platform, external_command);
 
+again:
     if (external_command) {
         gs_free char *dev = NULL;
 
@@ -2538,9 +2541,11 @@ nmtstp_link_ip6gre_add(NMPlatform                *platform,
                 g_strdup_printf("dev %s", nm_platform_link_get_name(platform, lnk->parent_ifindex));
 
         tclass_inherit = NM_FLAGS_HAS(lnk->flags, IP6_TNL_F_USE_ORIG_TCLASS);
+        encap_ignore   = NM_FLAGS_HAS(lnk->flags, IP6_TNL_F_IGN_ENCAP_LIMIT);
 
         success = !nmtstp_run_command(
-            "ip link add %s type %s%s%s local %s remote %s ttl %u tclass %s flowlabel %x",
+            "ip link add %s type %s%s%s local %s remote %s ttl %u tclass %s%s "
+            "flowlabel %x",
             name,
             lnk->is_tap ? "ip6gretap" : "ip6gre",
             NM_PRINT_FMT_QUOTED2(dev, " ", dev, ""),
@@ -2548,7 +2553,19 @@ nmtstp_link_ip6gre_add(NMPlatform                *platform,
             nm_inet6_ntop(&lnk->remote, b2),
             lnk->ttl,
             tclass_inherit ? "inherit" : nm_sprintf_buf(tclass, "%02x", lnk->tclass),
+            encap_ignore
+                ? "encaplimit none"
+                : (lnk->encap_limit != 4 ? nm_sprintf_buf(encap, "encaplimit %u", lnk->encap_limit)
+                                         : ""),
             lnk->flow_label);
+
+        if (!success && (encap_ignore || lnk->encap_limit != 4)) {
+            /* The command failed. That might be because iproute2 does not support the
+             * encaplimit parameter yet. Retry, now with platform code. */
+            external_command = FALSE;
+            goto again;
+        }
+
         if (success) {
             pllink = nmtstp_assert_wait_for_link(platform,
                                                  name,
diff --git a/src/core/platform/tests/test-link.c b/src/core/platform/tests/test-link.c
index cc1ec6d1..9a1eaf89 100644
--- a/src/core/platform/tests/test-link.c
+++ b/src/core/platform/tests/test-link.c
@@ -1439,12 +1439,25 @@ test_software_detect(gconstpointer user_data)
 
         module_loaded = nmtstp_ensure_module("ip6_gre");
 
-        lnk_ip6tnl.local          = nmtst_inet6_from_string("fd01::42");
-        lnk_ip6tnl.remote         = nmtst_inet6_from_string("fd01::aaaa");
-        lnk_ip6tnl.parent_ifindex = ifindex_parent;
-        lnk_ip6tnl.tclass         = 21;
-        lnk_ip6tnl.flow_label     = 1338;
-        lnk_ip6tnl.is_gre         = TRUE;
+        switch (test_data->test_mode) {
+        case 0:
+            lnk_ip6tnl.local          = nmtst_inet6_from_string("fd01::43");
+            lnk_ip6tnl.remote         = nmtst_inet6_from_string("fd01::aaaa");
+            lnk_ip6tnl.parent_ifindex = ifindex_parent;
+            lnk_ip6tnl.tclass         = 21;
+            lnk_ip6tnl.flow_label     = 1338;
+            lnk_ip6tnl.is_gre         = TRUE;
+            break;
+        case 1:
+            lnk_ip6tnl.local          = nmtst_inet6_from_string("fd01::44");
+            lnk_ip6tnl.remote         = nmtst_inet6_from_string("fd01::aaab");
+            lnk_ip6tnl.parent_ifindex = ifindex_parent;
+            lnk_ip6tnl.tclass         = 0;
+            lnk_ip6tnl.flow_label     = 1339;
+            lnk_ip6tnl.is_gre         = TRUE;
+            lnk_ip6tnl.flags          = IP6_TNL_F_IGN_ENCAP_LIMIT | IP6_TNL_F_USE_ORIG_TCLASS;
+            break;
+        }
 
         if (!nmtstp_link_ip6gre_add(NULL, ext, DEVICE_NAME, &lnk_ip6tnl)) {
             if (!module_loaded) {
@@ -1463,14 +1476,30 @@ test_software_detect(gconstpointer user_data)
 
         module_loaded = nmtstp_ensure_module("ip6_gre");
 
-        lnk_ip6tnl.local          = nmtst_inet6_from_string("fe80::abcd");
-        lnk_ip6tnl.remote         = nmtst_inet6_from_string("fc01::bbbb");
-        lnk_ip6tnl.parent_ifindex = ifindex_parent;
-        lnk_ip6tnl.ttl            = 10;
-        lnk_ip6tnl.tclass         = 22;
-        lnk_ip6tnl.flow_label     = 1339;
-        lnk_ip6tnl.is_gre         = TRUE;
-        lnk_ip6tnl.is_tap         = TRUE;
+        switch (test_data->test_mode) {
+        case 0:
+            lnk_ip6tnl.local          = nmtst_inet6_from_string("fe80::abcd");
+            lnk_ip6tnl.remote         = nmtst_inet6_from_string("fc01::bbbb");
+            lnk_ip6tnl.parent_ifindex = ifindex_parent;
+            lnk_ip6tnl.ttl            = 10;
+            lnk_ip6tnl.tclass         = 23;
+            lnk_ip6tnl.flow_label     = 1340;
+            lnk_ip6tnl.is_gre         = TRUE;
+            lnk_ip6tnl.is_tap         = TRUE;
+            break;
+        case 1:
+            lnk_ip6tnl.local          = nmtst_inet6_from_string("fe80::abce");
+            lnk_ip6tnl.remote         = nmtst_inet6_from_string("fc01::bbbc");
+            lnk_ip6tnl.parent_ifindex = ifindex_parent;
+            lnk_ip6tnl.ttl            = 10;
+            lnk_ip6tnl.tclass         = 0;
+            lnk_ip6tnl.flow_label     = 1341;
+            lnk_ip6tnl.is_gre         = TRUE;
+            lnk_ip6tnl.is_tap         = TRUE;
+            lnk_ip6tnl.encap_limit    = 4;
+            lnk_ip6tnl.flags          = IP6_TNL_F_IGN_ENCAP_LIMIT | IP6_TNL_F_USE_ORIG_TCLASS;
+            break;
+        }
 
         if (!nmtstp_link_ip6gre_add(NULL, ext, DEVICE_NAME, &lnk_ip6tnl)) {
             if (!module_loaded) {
@@ -1851,29 +1880,65 @@ test_software_detect(gconstpointer user_data)
         {
             const NMPlatformLnkIp6Tnl *plnk = &lnk->lnk_ip6tnl;
 
-            g_assert(plnk == nm_platform_link_get_lnk_ip6gre(NM_PLATFORM_GET, ifindex, NULL));
-            g_assert_cmpint(plnk->parent_ifindex, ==, ifindex_parent);
-            nmtst_assert_ip6_address(&plnk->local, "fd01::42");
-            nmtst_assert_ip6_address(&plnk->remote, "fd01::aaaa");
-            g_assert_cmpint(plnk->tclass, ==, 21);
-            g_assert_cmpint(plnk->flow_label, ==, 1338);
-            g_assert_cmpint(plnk->is_gre, ==, TRUE);
-            g_assert_cmpint(plnk->is_tap, ==, FALSE);
+            switch (test_data->test_mode) {
+            case 0:
+                g_assert(plnk == nm_platform_link_get_lnk_ip6gre(NM_PLATFORM_GET, ifindex, NULL));
+                g_assert_cmpint(plnk->parent_ifindex, ==, ifindex_parent);
+                nmtst_assert_ip6_address(&plnk->local, "fd01::43");
+                nmtst_assert_ip6_address(&plnk->remote, "fd01::aaaa");
+                g_assert_cmpint(plnk->tclass, ==, 21);
+                g_assert_cmpint(plnk->flow_label, ==, 1338);
+                g_assert_cmpint(plnk->is_gre, ==, TRUE);
+                g_assert_cmpint(plnk->is_tap, ==, FALSE);
+                break;
+            case 1:
+                g_assert(plnk == nm_platform_link_get_lnk_ip6gre(NM_PLATFORM_GET, ifindex, NULL));
+                g_assert_cmpint(plnk->parent_ifindex, ==, ifindex_parent);
+                nmtst_assert_ip6_address(&plnk->local, "fd01::44");
+                nmtst_assert_ip6_address(&plnk->remote, "fd01::aaab");
+                g_assert_cmpint(plnk->flow_label, ==, 1339);
+                g_assert_cmpint(plnk->is_gre, ==, TRUE);
+                g_assert_cmpint(plnk->is_tap, ==, FALSE);
+                g_assert_cmpint(plnk->flags & 0xFFFF, /* ignore kernel internal flags */
+                                ==,
+                                IP6_TNL_F_IGN_ENCAP_LIMIT | IP6_TNL_F_USE_ORIG_TCLASS);
+                break;
+            }
+
             break;
         }
         case NM_LINK_TYPE_IP6GRETAP:
         {
             const NMPlatformLnkIp6Tnl *plnk = &lnk->lnk_ip6tnl;
 
-            g_assert(plnk == nm_platform_link_get_lnk_ip6gretap(NM_PLATFORM_GET, ifindex, NULL));
-            g_assert_cmpint(plnk->parent_ifindex, ==, ifindex_parent);
-            nmtst_assert_ip6_address(&plnk->local, "fe80::abcd");
-            nmtst_assert_ip6_address(&plnk->remote, "fc01::bbbb");
-            g_assert_cmpint(plnk->ttl, ==, 10);
-            g_assert_cmpint(plnk->tclass, ==, 22);
-            g_assert_cmpint(plnk->flow_label, ==, 1339);
-            g_assert_cmpint(plnk->is_gre, ==, TRUE);
-            g_assert_cmpint(plnk->is_tap, ==, TRUE);
+            switch (test_data->test_mode) {
+            case 0:
+                g_assert(plnk
+                         == nm_platform_link_get_lnk_ip6gretap(NM_PLATFORM_GET, ifindex, NULL));
+                g_assert_cmpint(plnk->parent_ifindex, ==, ifindex_parent);
+                nmtst_assert_ip6_address(&plnk->local, "fe80::abcd");
+                nmtst_assert_ip6_address(&plnk->remote, "fc01::bbbb");
+                g_assert_cmpint(plnk->ttl, ==, 10);
+                g_assert_cmpint(plnk->tclass, ==, 23);
+                g_assert_cmpint(plnk->flow_label, ==, 1340);
+                g_assert_cmpint(plnk->is_gre, ==, TRUE);
+                g_assert_cmpint(plnk->is_tap, ==, TRUE);
+                break;
+            case 1:
+                g_assert(plnk
+                         == nm_platform_link_get_lnk_ip6gretap(NM_PLATFORM_GET, ifindex, NULL));
+                g_assert_cmpint(plnk->parent_ifindex, ==, ifindex_parent);
+                nmtst_assert_ip6_address(&plnk->local, "fe80::abce");
+                nmtst_assert_ip6_address(&plnk->remote, "fc01::bbbc");
+                g_assert_cmpint(plnk->ttl, ==, 10);
+                g_assert_cmpint(plnk->flow_label, ==, 1341);
+                g_assert_cmpint(plnk->is_gre, ==, TRUE);
+                g_assert_cmpint(plnk->is_tap, ==, TRUE);
+                g_assert_cmpint(plnk->flags & 0xFFFF, /* ignore kernel internal flags */
+                                ==,
+                                IP6_TNL_F_IGN_ENCAP_LIMIT | IP6_TNL_F_USE_ORIG_TCLASS);
+                break;
+            }
             break;
         }
         case NM_LINK_TYPE_IPIP:
@@ -3888,8 +3953,10 @@ _nmtstp_setup_tests(void)
         test_software_detect_add("/link/software/detect/gretap", NM_LINK_TYPE_GRETAP, 0);
         test_software_detect_add("/link/software/detect/ip6tnl/0", NM_LINK_TYPE_IP6TNL, 0);
         test_software_detect_add("/link/software/detect/ip6tnl/1", NM_LINK_TYPE_IP6TNL, 1);
-        test_software_detect_add("/link/software/detect/ip6gre", NM_LINK_TYPE_IP6GRE, 0);
-        test_software_detect_add("/link/software/detect/ip6gretap", NM_LINK_TYPE_IP6GRETAP, 0);
+        test_software_detect_add("/link/software/detect/ip6gre/0", NM_LINK_TYPE_IP6GRE, 0);
+        test_software_detect_add("/link/software/detect/ip6gre/1", NM_LINK_TYPE_IP6GRE, 1);
+        test_software_detect_add("/link/software/detect/ip6gretap/0", NM_LINK_TYPE_IP6GRETAP, 0);
+        test_software_detect_add("/link/software/detect/ip6gretap/1", NM_LINK_TYPE_IP6GRETAP, 1);
         test_software_detect_add("/link/software/detect/ipip", NM_LINK_TYPE_IPIP, 0);
         test_software_detect_add("/link/software/detect/macvlan", NM_LINK_TYPE_MACVLAN, 0);
         test_software_detect_add("/link/software/detect/macvtap", NM_LINK_TYPE_MACVTAP, 0);
diff --git a/src/core/settings/nm-settings-connection.c b/src/core/settings/nm-settings-connection.c
index 1638efcd..024c0009 100644
--- a/src/core/settings/nm-settings-connection.c
+++ b/src/core/settings/nm-settings-connection.c
@@ -2532,6 +2532,14 @@ nm_settings_connection_add_seen_bssid(NMSettingsConnection *self, const char *se
     nm_key_file_db_set_string_list(priv->kf_db_seen_bssids, connection_uuid, seen_bssids_strv, i);
 }
 
+guint
+nm_settings_connection_get_num_seen_bssids(NMSettingsConnection *self)
+{
+    g_return_val_if_fail(NM_IS_SETTINGS_CONNECTION(self), 0);
+
+    return nm_g_hash_table_size(NM_SETTINGS_CONNECTION_GET_PRIVATE(self)->seen_bssids_hash);
+}
+
 /*****************************************************************************/
 
 /**
diff --git a/src/core/settings/nm-settings-connection.h b/src/core/settings/nm-settings-connection.h
index 47599c3d..fce7497c 100644
--- a/src/core/settings/nm-settings-connection.h
+++ b/src/core/settings/nm-settings-connection.h
@@ -345,6 +345,8 @@ gboolean nm_settings_connection_has_seen_bssid(NMSettingsConnection *self, const
 
 void nm_settings_connection_add_seen_bssid(NMSettingsConnection *self, const char *seen_bssid);
 
+guint nm_settings_connection_get_num_seen_bssids(NMSettingsConnection *self);
+
 int  nm_settings_connection_autoconnect_retries_get(NMSettingsConnection *self);
 void nm_settings_connection_autoconnect_retries_set(NMSettingsConnection *self, int retries);
 void nm_settings_connection_autoconnect_retries_reset(NMSettingsConnection *self);
diff --git a/src/core/supplicant/nm-supplicant-config.c b/src/core/supplicant/nm-supplicant-config.c
index c63a0058..1d9372e0 100644
--- a/src/core/supplicant/nm-supplicant-config.c
+++ b/src/core/supplicant/nm-supplicant-config.c
@@ -592,7 +592,10 @@ nm_supplicant_config_add_setting_wireless(NMSupplicantConfig *self,
 }
 
 gboolean
-nm_supplicant_config_add_bgscan(NMSupplicantConfig *self, NMConnection *connection, GError **error)
+nm_supplicant_config_add_bgscan(NMSupplicantConfig *self,
+                                NMConnection       *connection,
+                                guint               num_seen_bssids,
+                                GError            **error)
 {
     NMSettingWireless         *s_wifi;
     NMSettingWirelessSecurity *s_wsec;
@@ -629,7 +632,7 @@ nm_supplicant_config_add_bgscan(NMSupplicantConfig *self, NMConnection *connecti
      * when the signal is still somewhat OK so we have an up-to-date roam
      * candidate list when the signal gets bad.
      */
-    if (nm_setting_wireless_get_num_seen_bssids(s_wifi) > 1
+    if (num_seen_bssids > 1u
         || ((s_wsec = nm_connection_get_setting_wireless_security(connection))
             && NM_IN_STRSET(nm_setting_wireless_security_get_key_mgmt(s_wsec),
                             "ieee8021x",
diff --git a/src/core/supplicant/nm-supplicant-config.h b/src/core/supplicant/nm-supplicant-config.h
index 063f7f55..585cf958 100644
--- a/src/core/supplicant/nm-supplicant-config.h
+++ b/src/core/supplicant/nm-supplicant-config.h
@@ -44,8 +44,10 @@ gboolean nm_supplicant_config_add_setting_wireless(NMSupplicantConfig *self,
                                                    guint32             fixed_freq,
                                                    GError            **error);
 
-gboolean
-nm_supplicant_config_add_bgscan(NMSupplicantConfig *self, NMConnection *connection, GError **error);
+gboolean nm_supplicant_config_add_bgscan(NMSupplicantConfig *self,
+                                         NMConnection       *connection,
+                                         guint               num_seen_bssids,
+                                         GError            **error);
 
 gboolean nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig        *self,
                                                             NMSettingWirelessSecurity *setting,
diff --git a/src/core/supplicant/tests/test-supplicant-config.c b/src/core/supplicant/tests/test-supplicant-config.c
index 237b1a96..1ca5b26e 100644
--- a/src/core/supplicant/tests/test-supplicant-config.c
+++ b/src/core/supplicant/tests/test-supplicant-config.c
@@ -127,7 +127,7 @@ build_supplicant_config(NMConnection  *connection,
     g_assert_no_error(error);
     g_assert(success);
 
-    success = nm_supplicant_config_add_bgscan(config, connection, &error);
+    success = nm_supplicant_config_add_bgscan(config, connection, 0, &error);
     g_assert_no_error(error);
     g_assert(success);