about summary refs log tree commit diff
path: root/src/core/devices/nm-device.c
diff options
context:
space:
mode:
authorSebastien Bacher <seb128@ubuntu.com>2021-07-05 20:35:03 +0200
committerSebastien Bacher <seb128@ubuntu.com>2021-07-05 20:35:03 +0200
commit35779c6675728fa6f0fd0a21cefb904408509c23 (patch)
tree553e7239e0ba182b4f9b29b1e7a9d66a595d08bc /src/core/devices/nm-device.c
parentd92aa7f298fe84d4cf686c5ad64b73438e00d377 (diff)
New upstream version 1.32.2
Diffstat (limited to 'src/core/devices/nm-device.c')
-rw-r--r--src/core/devices/nm-device.c1295
1 files changed, 659 insertions, 636 deletions
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c
index 040dd0b4..1c70ecb3 100644
--- a/src/core/devices/nm-device.c
+++ b/src/core/devices/nm-device.c
@@ -23,22 +23,23 @@
 #include <linux/if_ether.h>
 #include <linux/if_infiniband.h>
 
-#include "nm-std-aux/unaligned.h"
-#include "nm-glib-aux/nm-dedup-multi.h"
-#include "nm-glib-aux/nm-random-utils.h"
-#include "systemd/nm-sd-utils-shared.h"
-
-#include "nm-base/nm-ethtool-base.h"
-#include "nm-libnm-core-intern/nm-common-macros.h"
+#include "libnm-std-aux/unaligned.h"
+#include "libnm-glib-aux/nm-uuid.h"
+#include "libnm-glib-aux/nm-dedup-multi.h"
+#include "libnm-glib-aux/nm-random-utils.h"
+#include "libnm-systemd-shared/nm-sd-utils-shared.h"
+
+#include "libnm-base/nm-ethtool-base.h"
+#include "libnm-core-aux-intern/nm-common-macros.h"
 #include "nm-device-private.h"
 #include "nm-l3cfg.h"
 #include "nm-l3-config-data.h"
 #include "NetworkManagerUtils.h"
 #include "nm-manager.h"
-#include "platform/nm-platform.h"
-#include "nm-platform/nm-platform-utils.h"
-#include "platform/nmp-object.h"
-#include "platform/nmp-rules-manager.h"
+#include "libnm-platform/nm-platform.h"
+#include "libnm-platform/nm-platform-utils.h"
+#include "libnm-platform/nmp-object.h"
+#include "libnm-platform/nmp-rules-manager.h"
 #include "ndisc/nm-ndisc.h"
 #include "ndisc/nm-lndp-ndisc.h"
 #include "dhcp/nm-dhcp-manager.h"
@@ -51,7 +52,8 @@
 #include "dnsmasq/nm-dnsmasq-manager.h"
 #include "nm-dhcp-config.h"
 #include "nm-rfkill-manager.h"
-#include "nm-firewall-manager.h"
+#include "nm-firewall-utils.h"
+#include "nm-firewalld-manager.h"
 #include "settings/nm-settings-connection.h"
 #include "settings/nm-settings.h"
 #include "nm-setting-ethtool.h"
@@ -65,12 +67,13 @@
 #include "c-list/src/c-list.h"
 #include "dns/nm-dns-manager.h"
 #include "nm-acd-manager.h"
-#include "nm-core-internal.h"
-#include "systemd/nm-sd.h"
+#include "libnm-core-intern/nm-core-internal.h"
+#include "libnm-systemd-core/nm-sd.h"
 #include "nm-lldp-listener.h"
 #include "nm-audit-manager.h"
 #include "nm-connectivity.h"
 #include "nm-dbus-interface.h"
+#include "nm-hostname-manager.h"
 
 #include "nm-device-generic.h"
 #include "nm-device-vlan.h"
@@ -125,7 +128,6 @@ typedef struct {
 typedef struct {
     NMDevice *device;
     guint     idle_add_id;
-    int       ifindex;
 } DeleteOnDeactivateData;
 
 typedef struct {
@@ -208,6 +210,7 @@ typedef struct {
     NMOptionBool            requested[_NM_ETHTOOL_ID_FEATURE_NUM];
     NMEthtoolCoalesceState *coalesce;
     NMEthtoolRingState *    ring;
+    NMEthtoolPauseState *   pause;
 } EthtoolState;
 
 typedef enum {
@@ -218,7 +221,6 @@ typedef enum {
 
 typedef struct {
     ResolverState state;
-    GResolver *   resolver;
     GInetAddress *address;
     GCancellable *cancellable;
     char *        hostname;
@@ -497,9 +499,6 @@ typedef struct _NMDevicePrivate {
 
     NMDeviceStageState stage1_sriov_state : 3;
 
-    /* Generic DHCP stuff */
-    char *dhcp_anycast_address;
-
     char *current_stable_id;
 
     /* Proxy Configuration */
@@ -593,9 +592,9 @@ typedef struct _NMDevicePrivate {
     gulong            dnsmasq_state_id;
 
     /* Firewall */
-    FirewallState            fw_state : 4;
-    NMFirewallManager *      fw_mgr;
-    NMFirewallManagerCallId *fw_call;
+    FirewallState             fw_state : 4;
+    NMFirewalldManager *      fw_mgr;
+    NMFirewalldManagerCallId *fw_call;
 
     /* IPv4LL stuff */
     sd_ipv4ll *ipv4ll;
@@ -694,6 +693,8 @@ typedef struct _NMDevicePrivate {
     } stats;
 
     bool mtu_force_set_done : 1;
+
+    NMOptionBool promisc_reset;
 } NMDevicePrivate;
 
 G_DEFINE_ABSTRACT_TYPE(NMDevice, nm_device, NM_TYPE_DBUS_OBJECT)
@@ -768,139 +769,6 @@ static gboolean device_link_changed(NMDevice *self);
 
 /*****************************************************************************/
 
-static NM_UTILS_LOOKUP_STR_DEFINE(
-    queued_state_to_string,
-    NMDeviceState,
-    NM_UTILS_LOOKUP_DEFAULT(NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "???"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_UNKNOWN,
-                             NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "unknown"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_UNMANAGED,
-                             NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "unmanaged"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_UNAVAILABLE,
-                             NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "unavailable"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_DISCONNECTED,
-                             NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "disconnected"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_PREPARE,
-                             NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "prepare"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_CONFIG,
-                             NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "config"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_NEED_AUTH,
-                             NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "need-auth"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_IP_CONFIG,
-                             NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "ip-config"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_IP_CHECK,
-                             NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "ip-check"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_SECONDARIES,
-                             NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "secondaries"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_ACTIVATED,
-                             NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "activated"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_DEACTIVATING,
-                             NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "deactivating"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_FAILED,
-                             NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "failed"), );
-
-const char *
-nm_device_state_to_str(NMDeviceState state)
-{
-    return queued_state_to_string(state) + NM_STRLEN(NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE);
-}
-
-NM_UTILS_LOOKUP_STR_DEFINE(
-    nm_device_state_reason_to_str,
-    NMDeviceStateReason,
-    NM_UTILS_LOOKUP_DEFAULT(NULL),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_UNKNOWN, "unknown"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_NONE, "none"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_NOW_MANAGED, "managed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_NOW_UNMANAGED, "unmanaged"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_CONFIG_FAILED, "config-failed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE, "ip-config-unavailable"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED, "ip-config-expired"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_NO_SECRETS, "no-secrets"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT, "supplicant-disconnect"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED,
-                             "supplicant-config-failed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED, "supplicant-failed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT, "supplicant-timeout"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_PPP_START_FAILED, "ppp-start-failed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_PPP_DISCONNECT, "ppp-disconnect"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_PPP_FAILED, "ppp-failed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_DHCP_START_FAILED, "dhcp-start-failed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_DHCP_ERROR, "dhcp-error"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_DHCP_FAILED, "dhcp-failed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SHARED_START_FAILED, "sharing-start-failed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SHARED_FAILED, "sharing-failed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED, "autoip-start-failed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_AUTOIP_ERROR, "autoip-error"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_AUTOIP_FAILED, "autoip-failed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_MODEM_BUSY, "modem-busy"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE, "modem-no-dialtone"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER, "modem-no-carrier"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT, "modem-dial-timeout"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED, "modem-dial-failed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED, "modem-init-failed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_GSM_APN_FAILED, "gsm-apn-failed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING,
-                             "gsm-registration-idle"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED,
-                             "gsm-registration-denied"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT,
-                             "gsm-registration-timeout"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED,
-                             "gsm-registration-failed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED, "gsm-pin-check-failed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_FIRMWARE_MISSING, "firmware-missing"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_REMOVED, "removed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SLEEPING, "sleeping"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_CONNECTION_REMOVED, "connection-removed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_USER_REQUESTED, "user-requested"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_CARRIER, "carrier-changed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED, "connection-assumed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE, "supplicant-available"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND, "modem-not-found"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_BT_FAILED, "bluetooth-failed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED, "gsm-sim-not-inserted"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED, "gsm-sim-pin-required"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED, "gsm-sim-puk-required"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_GSM_SIM_WRONG, "gsm-sim-wrong"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_INFINIBAND_MODE, "infiniband-mode"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED, "dependency-failed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_BR2684_FAILED, "br2684-bridge-failed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE,
-                             "modem-manager-unavailable"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SSID_NOT_FOUND, "ssid-not-found"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED,
-                             "secondary-connection-failed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED, "dcb-fcoe-failed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED, "teamd-control-failed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_MODEM_FAILED, "modem-failed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_MODEM_AVAILABLE, "modem-available"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT, "sim-pin-incorrect"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_NEW_ACTIVATION, "new-activation"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_PARENT_CHANGED, "parent-changed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED,
-                             "parent-managed-changed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_OVSDB_FAILED, "ovsdb-failed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE, "ip-address-duplicate"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED, "ip-method-unsupported"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED,
-                             "sriov-configuration-failed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_PEER_NOT_FOUND, "peer-not-found"), );
-
-#define reason_to_string_a(reason) NM_UTILS_LOOKUP_STR_A(nm_device_state_reason_to_str, reason)
-
-static NM_UTILS_LOOKUP_STR_DEFINE(mtu_source_to_str,
-                                  NMDeviceMtuSource,
-                                  NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT("unknown"),
-                                  NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_MTU_SOURCE_NONE, "none"),
-                                  NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_MTU_SOURCE_PARENT, "parent"),
-                                  NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_MTU_SOURCE_IP_CONFIG,
-                                                           "ip-config"),
-                                  NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_MTU_SOURCE_CONNECTION,
-                                                           "connection"), );
-
-/*****************************************************************************/
-
 static void
 _hostname_resolver_free(HostnameResolver *resolver)
 {
@@ -909,7 +777,6 @@ _hostname_resolver_free(HostnameResolver *resolver)
 
     nm_clear_g_source(&resolver->timeout_id);
     nm_clear_g_cancellable(&resolver->cancellable);
-    nm_g_object_unref(resolver->resolver);
     nm_g_object_unref(resolver->address);
     g_free(resolver->hostname);
     nm_g_slice_free(resolver);
@@ -953,8 +820,7 @@ _prop_get_connection_stable_id(NMDevice *         self,
      * Especially with ${RANDOM} stable-id we want to generate *one* configuration
      * for each activation. */
     if (G_UNLIKELY(!priv->current_stable_id)) {
-        gs_free char *       default_id = NULL;
-        gs_free char *       generated  = NULL;
+        gs_free char *       generated = NULL;
         NMUtilsStableType    stable_type;
         NMSettingConnection *s_con;
         gboolean             hwaddr_is_fake;
@@ -967,11 +833,10 @@ _prop_get_connection_stable_id(NMDevice *         self,
         stable_id = nm_setting_connection_get_stable_id(s_con);
 
         if (!stable_id) {
-            default_id =
+            stable_id =
                 nm_config_data_get_connection_default(NM_CONFIG_GET_DATA,
                                                       NM_CON_DEFAULT("connection.stable-id"),
                                                       self);
-            stable_id = default_id;
         }
 
         uuid = nm_connection_get_uuid(connection);
@@ -1030,7 +895,6 @@ _prop_get_ipv6_dhcp_duid(NMDevice *    self,
 {
     NMSettingIPConfig *s_ip6;
     const char *       duid;
-    gs_free char *     duid_default = NULL;
     const char *       duid_error;
     GBytes *           duid_out;
     gboolean           duid_enforce = TRUE;
@@ -1043,10 +907,9 @@ _prop_get_ipv6_dhcp_duid(NMDevice *    self,
     duid  = nm_setting_ip6_config_get_dhcp_duid(NM_SETTING_IP6_CONFIG(s_ip6));
 
     if (!duid) {
-        duid_default = nm_config_data_get_connection_default(NM_CONFIG_GET_DATA,
-                                                             NM_CON_DEFAULT("ipv6.dhcp-duid"),
-                                                             self);
-        duid         = duid_default;
+        duid = nm_config_data_get_connection_default(NM_CONFIG_GET_DATA,
+                                                     NM_CON_DEFAULT("ipv6.dhcp-duid"),
+                                                     self);
         if (!duid)
             duid = "lease";
     }
@@ -1397,7 +1260,7 @@ _prop_get_ipvx_route_table(NMDevice *self, int addr_family)
     _LOGT(LOGD_DEVICE,
           "ipv%c.route-table = %u%s",
           nm_utils_addr_family_to_char(addr_family),
-          (guint)(route_table ?: RT_TABLE_MAIN),
+          (guint) (route_table ?: RT_TABLE_MAIN),
           route_table != 0u ? "" : " (policy routing not enabled)");
 
     return route_table;
@@ -1523,7 +1386,6 @@ _prop_get_ipvx_dhcp_iaid(NMDevice *    self,
     const int          IS_IPv4 = NM_IS_IPv4(addr_family);
     NMSettingIPConfig *s_ip;
     const char *       iaid_str;
-    gs_free char *     iaid_str_free = NULL;
     guint32            iaid;
     const char *       iface;
     const char *       fail_reason;
@@ -1532,11 +1394,10 @@ _prop_get_ipvx_dhcp_iaid(NMDevice *    self,
     s_ip     = nm_connection_get_setting_ip_config(connection, addr_family);
     iaid_str = nm_setting_ip_config_get_dhcp_iaid(s_ip);
     if (!iaid_str) {
-        iaid_str_free = nm_config_data_get_connection_default(
-            NM_CONFIG_GET_DATA,
-            IS_IPv4 ? NM_CON_DEFAULT("ipv4.dhcp-iaid") : NM_CON_DEFAULT("ipv6.dhcp-iaid"),
-            self);
-        iaid_str = iaid_str_free;
+        iaid_str = nm_config_data_get_connection_default(NM_CONFIG_GET_DATA,
+                                                         IS_IPv4 ? NM_CON_DEFAULT("ipv4.dhcp-iaid")
+                                                                 : NM_CON_DEFAULT("ipv6.dhcp-iaid"),
+                                                         self);
         if (!iaid_str) {
             iaid_str    = NM_IAID_IFNAME;
             is_explicit = FALSE;
@@ -1567,7 +1428,7 @@ _prop_get_ipvx_dhcp_iaid(NMDevice *    self,
         iaid = unaligned_read_be32(&pllink->l_address.data[pllink->l_address.len - 4]);
         goto out_good;
     } else if (nm_streq0(iaid_str, NM_IAID_PERM_MAC)) {
-        guint8      hwaddr_buf[NM_UTILS_HWADDR_LEN_MAX];
+        guint8      hwaddr_buf[_NM_UTILS_HWADDR_LEN_MAX];
         const char *hwaddr_str;
         gsize       hwaddr_len;
 
@@ -1693,12 +1554,10 @@ _prop_get_ipvx_dhcp_hostname_flags(NMDevice *self, int addr_family)
 }
 
 static const char *
-_prop_get_connection_mud_url(NMDevice *self, NMSettingConnection *s_con, char **out_mud_url)
+_prop_get_connection_mud_url(NMDevice *self, NMSettingConnection *s_con)
 {
-    const char *  mud_url;
-    gs_free char *s = NULL;
-
-    nm_assert(out_mud_url && !*out_mud_url);
+    const char *mud_url;
+    const char *s;
 
     mud_url = nm_setting_connection_get_mud_url(s_con);
 
@@ -1715,7 +1574,7 @@ _prop_get_connection_mud_url(NMDevice *self, NMSettingConnection *s_con, char **
         if (nm_streq(s, NM_CONNECTION_MUD_URL_NONE))
             return NULL;
         if (nm_sd_http_url_is_valid_https(s))
-            return (*out_mud_url = g_steal_pointer(&s));
+            return s;
     }
 
     return NULL;
@@ -1726,10 +1585,9 @@ _prop_get_ipv4_dhcp_client_id(NMDevice *self, NMConnection *connection, GBytes *
 {
     NMSettingIPConfig *s_ip4;
     const char *       client_id;
-    gs_free char *     client_id_default = NULL;
     guint8 *           client_id_buf;
     const char *       fail_reason;
-    guint8             hwaddr_bin_buf[NM_UTILS_HWADDR_LEN_MAX];
+    guint8             hwaddr_bin_buf[_NM_UTILS_HWADDR_LEN_MAX];
     const guint8 *     hwaddr_bin;
     int                arp_type;
     gsize              hwaddr_len;
@@ -1740,13 +1598,12 @@ _prop_get_ipv4_dhcp_client_id(NMDevice *self, NMConnection *connection, GBytes *
     client_id = nm_setting_ip4_config_get_dhcp_client_id(NM_SETTING_IP4_CONFIG(s_ip4));
 
     if (!client_id) {
-        client_id_default =
-            nm_config_data_get_connection_default(NM_CONFIG_GET_DATA,
-                                                  NM_CON_DEFAULT("ipv4.dhcp-client-id"),
-                                                  self);
-        if (client_id_default && client_id_default[0]) {
+        client_id = nm_config_data_get_connection_default(NM_CONFIG_GET_DATA,
+                                                          NM_CON_DEFAULT("ipv4.dhcp-client-id"),
+                                                          self);
+        if (client_id && !client_id[0]) {
             /* a non-empty client-id is always valid, see nm_dhcp_utils_client_id_string_to_bytes().  */
-            client_id = client_id_default;
+            client_id = NULL;
         }
     }
 
@@ -1878,8 +1735,7 @@ out_good:
 static GBytes *
 _prop_get_ipv4_dhcp_vendor_class_identifier(NMDevice *self, NMSettingIP4Config *s_ip4)
 {
-    gs_free char *config_data_prop = NULL;
-    gs_free char *to_free          = NULL;
+    gs_free char *to_free = NULL;
     const char *  conn_prop;
     GBytes *      bytes = NULL;
     const char *  bin;
@@ -1889,13 +1745,13 @@ _prop_get_ipv4_dhcp_vendor_class_identifier(NMDevice *self, NMSettingIP4Config *
 
     if (!conn_prop) {
         /* set in NetworkManager.conf ? */
-        config_data_prop = nm_config_data_get_connection_default(
+        conn_prop = nm_config_data_get_connection_default(
             NM_CONFIG_GET_DATA,
             NM_CON_DEFAULT("ipv4.dhcp-vendor-class-identifier"),
             self);
 
-        if (config_data_prop && nm_utils_validate_dhcp4_vendor_class_id(config_data_prop, NULL))
-            conn_prop = config_data_prop;
+        if (conn_prop && !nm_utils_validate_dhcp4_vendor_class_id(conn_prop, NULL))
+            conn_prop = NULL;
     }
 
     if (conn_prop) {
@@ -1961,16 +1817,11 @@ _prop_get_ipv6_ip6_privacy(NMDevice *self)
 }
 
 static const char *
-_prop_get_x_cloned_mac_address(NMDevice *    self,
-                               NMConnection *connection,
-                               gboolean      is_wifi,
-                               char **       out_addr)
+_prop_get_x_cloned_mac_address(NMDevice *self, NMConnection *connection, gboolean is_wifi)
 {
     NMSetting * setting;
     const char *addr = NULL;
 
-    nm_assert(out_addr && !*out_addr);
-
     setting = nm_connection_get_setting(connection,
                                         is_wifi ? NM_TYPE_SETTING_WIRELESS : NM_TYPE_SETTING_WIRED);
     if (setting) {
@@ -1979,7 +1830,7 @@ _prop_get_x_cloned_mac_address(NMDevice *    self,
     }
 
     if (!addr) {
-        gs_free char *a = NULL;
+        const char *a;
 
         a = nm_config_data_get_connection_default(
             NM_CONFIG_GET_DATA,
@@ -1994,36 +1845,28 @@ _prop_get_x_cloned_mac_address(NMDevice *    self,
                 NMSettingMacRandomization v;
 
                 /* for backward compatibility, read the deprecated wifi.mac-address-randomization setting. */
-                a = nm_config_data_get_connection_default(
+                v = nm_config_data_get_connection_default_int64(
                     NM_CONFIG_GET_DATA,
                     NM_CON_DEFAULT("wifi.mac-address-randomization"),
-                    self);
-                v = _nm_utils_ascii_str_to_int64(a,
-                                                 10,
-                                                 NM_SETTING_MAC_RANDOMIZATION_DEFAULT,
-                                                 NM_SETTING_MAC_RANDOMIZATION_ALWAYS,
-                                                 NM_SETTING_MAC_RANDOMIZATION_DEFAULT);
+                    self,
+                    NM_SETTING_MAC_RANDOMIZATION_DEFAULT,
+                    NM_SETTING_MAC_RANDOMIZATION_ALWAYS,
+                    NM_SETTING_MAC_RANDOMIZATION_DEFAULT);
                 if (v == NM_SETTING_MAC_RANDOMIZATION_ALWAYS)
                     addr = NM_CLONED_MAC_RANDOM;
             }
         } else if (NM_CLONED_MAC_IS_SPECIAL(a) || nm_utils_hwaddr_valid(a, ETH_ALEN))
-            addr = *out_addr = g_steal_pointer(&a);
+            addr = a;
     }
 
     return addr;
 }
 
 static const char *
-_prop_get_x_generate_mac_address_mask(NMDevice *    self,
-                                      NMConnection *connection,
-                                      gboolean      is_wifi,
-                                      char **       out_value)
+_prop_get_x_generate_mac_address_mask(NMDevice *self, NMConnection *connection, gboolean is_wifi)
 {
     NMSetting * setting;
-    const char *value = NULL;
-    char *      a;
-
-    nm_assert(out_value && !*out_value);
+    const char *value;
 
     setting = nm_connection_get_setting(connection,
                                         is_wifi ? NM_TYPE_SETTING_WIRELESS : NM_TYPE_SETTING_WIRED);
@@ -2036,15 +1879,11 @@ _prop_get_x_generate_mac_address_mask(NMDevice *    self,
             return value;
     }
 
-    a = nm_config_data_get_connection_default(
+    return nm_config_data_get_connection_default(
         NM_CONFIG_GET_DATA,
         is_wifi ? NM_CON_DEFAULT("wifi.generate-mac-address-mask")
                 : NM_CON_DEFAULT("ethernet.generate-mac-address-mask"),
         self);
-    if (!a)
-        return NULL;
-    *out_value = a;
-    return a;
 }
 
 /*****************************************************************************/
@@ -2273,6 +2112,113 @@ _ethtool_ring_set(NMDevice *        self,
 }
 
 static void
+_ethtool_pause_reset(NMDevice *self, NMPlatform *platform, EthtoolState *ethtool_state)
+{
+    gs_free NMEthtoolPauseState *pause = NULL;
+
+    nm_assert(NM_IS_DEVICE(self));
+    nm_assert(NM_IS_PLATFORM(platform));
+    nm_assert(ethtool_state);
+
+    pause = g_steal_pointer(&ethtool_state->pause);
+    if (!pause)
+        return;
+
+    if (!nm_platform_ethtool_set_pause(platform, ethtool_state->ifindex, pause))
+        _LOGW(LOGD_DEVICE, "ethtool: failure resetting one or more pause settings");
+    else
+        _LOGD(LOGD_DEVICE, "ethtool: pause settings successfully reset");
+}
+
+static void
+_ethtool_pause_set(NMDevice *        self,
+                   NMPlatform *      platform,
+                   EthtoolState *    ethtool_state,
+                   NMSettingEthtool *s_ethtool)
+{
+    NMEthtoolPauseState pause_old;
+    NMEthtoolPauseState pause_new;
+    GHashTable *        hash;
+    GHashTableIter      iter;
+    const char *        name;
+    GVariant *          variant;
+    gboolean            has_old       = FALSE;
+    NMTernary           pause_autoneg = NM_TERNARY_DEFAULT;
+    NMTernary           pause_rx      = NM_TERNARY_DEFAULT;
+    NMTernary           pause_tx      = NM_TERNARY_DEFAULT;
+
+    nm_assert(NM_IS_DEVICE(self));
+    nm_assert(NM_IS_PLATFORM(platform));
+    nm_assert(NM_IS_SETTING_ETHTOOL(s_ethtool));
+    nm_assert(ethtool_state);
+    nm_assert(!ethtool_state->pause);
+
+    hash = _nm_setting_option_hash(NM_SETTING(s_ethtool), FALSE);
+    if (!hash)
+        return;
+
+    g_hash_table_iter_init(&iter, hash);
+    while (g_hash_table_iter_next(&iter, (gpointer *) &name, (gpointer *) &variant)) {
+        NMEthtoolID ethtool_id = nm_ethtool_id_get_by_name(name);
+
+        if (!nm_ethtool_id_is_pause(ethtool_id))
+            continue;
+
+        nm_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_BOOLEAN));
+
+        if (!has_old) {
+            if (!nm_platform_ethtool_get_link_pause(platform, ethtool_state->ifindex, &pause_old)) {
+                _LOGW(LOGD_DEVICE,
+                      "ethtool: failure setting pause options (cannot read "
+                      "existing setting)");
+                return;
+            }
+            has_old = TRUE;
+        }
+
+        switch (ethtool_id) {
+        case NM_ETHTOOL_ID_PAUSE_AUTONEG:
+            pause_autoneg = g_variant_get_boolean(variant);
+            break;
+        case NM_ETHTOOL_ID_PAUSE_RX:
+            pause_rx = g_variant_get_boolean(variant);
+            break;
+        case NM_ETHTOOL_ID_PAUSE_TX:
+            pause_tx = g_variant_get_boolean(variant);
+            break;
+        default:
+            nm_assert_not_reached();
+        }
+    }
+
+    if (!has_old)
+        return;
+
+    if (pause_rx != NM_TERNARY_DEFAULT || pause_tx != NM_TERNARY_DEFAULT) {
+        /* this implies to explicitly disable autoneg. */
+        nm_assert(pause_autoneg != NM_TERNARY_TRUE);
+        pause_autoneg = NM_TERNARY_FALSE;
+    }
+
+    pause_new = pause_old;
+    if (pause_autoneg != NM_TERNARY_DEFAULT)
+        pause_new.autoneg = !!pause_autoneg;
+    if (pause_rx != NM_TERNARY_DEFAULT)
+        pause_new.rx = !!pause_rx;
+    if (pause_tx != NM_TERNARY_DEFAULT)
+        pause_new.tx = !!pause_tx;
+
+    ethtool_state->pause = nm_memdup(&pause_old, sizeof(pause_old));
+
+    if (!nm_platform_ethtool_set_pause(platform, ethtool_state->ifindex, &pause_new)) {
+        _LOGW(LOGD_DEVICE, "ethtool: failure setting pause settings");
+        return;
+    }
+
+    _LOGD(LOGD_DEVICE, "ethtool: pause settings successfully set");
+}
+
+static void
 _ethtool_state_reset(NMDevice *self)
 {
     NMPlatform *     platform           = nm_device_get_platform(self);
@@ -2288,6 +2234,8 @@ _ethtool_state_reset(NMDevice *self)
         _ethtool_coalesce_reset(self, platform, ethtool_state);
     if (ethtool_state->ring)
         _ethtool_ring_reset(self, platform, ethtool_state);
+    if (ethtool_state->pause)
+        _ethtool_pause_reset(self, platform, ethtool_state);
 }
 
 static void
@@ -2321,8 +2269,10 @@ _ethtool_state_set(NMDevice *self)
     _ethtool_features_set(self, platform, ethtool_state, s_ethtool);
     _ethtool_coalesce_set(self, platform, ethtool_state, s_ethtool);
     _ethtool_ring_set(self, platform, ethtool_state, s_ethtool);
+    _ethtool_pause_set(self, platform, ethtool_state, s_ethtool);
 
-    if (ethtool_state->features || ethtool_state->coalesce || ethtool_state->ring)
+    if (ethtool_state->features || ethtool_state->coalesce || ethtool_state->ring
+        || ethtool_state->pause)
         priv->ethtool_state = g_steal_pointer(&ethtool_state);
 }
 
@@ -2521,15 +2471,6 @@ applied_config_reset_nameservers(AppliedConfig *config)
 
 /*****************************************************************************/
 
-static NM_UTILS_LOOKUP_STR_DEFINE(
-    _sys_iface_state_to_str,
-    NMDeviceSysIfaceState,
-    NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT("unknown"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_SYS_IFACE_STATE_EXTERNAL, "external"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_SYS_IFACE_STATE_ASSUME, "assume"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_SYS_IFACE_STATE_MANAGED, "managed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_SYS_IFACE_STATE_REMOVED, "removed"), );
-
 NMDeviceSysIfaceState
 nm_device_sys_iface_state_get(NMDevice *self)
 {
@@ -2568,8 +2509,8 @@ nm_device_sys_iface_state_set(NMDevice *self, NMDeviceSysIfaceState sys_iface_st
     if (priv->sys_iface_state != sys_iface_state) {
         _LOGT(LOGD_DEVICE,
               "sys-iface-state: %s -> %s",
-              _sys_iface_state_to_str(priv->sys_iface_state),
-              _sys_iface_state_to_str(sys_iface_state));
+              nm_device_sys_iface_state_to_str(priv->sys_iface_state),
+              nm_device_sys_iface_state_to_str(sys_iface_state));
         priv->sys_iface_state_ = sys_iface_state;
     }
 
@@ -2600,6 +2541,42 @@ _active_connection_set_state_flags(NMDevice *self, NMActivationStateFlags flags)
 
 /*****************************************************************************/
 
+static gboolean
+set_interface_flags_full(NMDevice *             self,
+                         NMDeviceInterfaceFlags mask,
+                         NMDeviceInterfaceFlags interface_flags,
+                         gboolean               notify)
+{
+    NMDevicePrivate *      priv = NM_DEVICE_GET_PRIVATE(self);
+    NMDeviceInterfaceFlags f;
+
+    nm_assert(!!mask);
+    nm_assert(!NM_FLAGS_ANY(mask, ~_NM_DEVICE_INTERFACE_FLAG_ALL));
+    nm_assert(!NM_FLAGS_ANY(interface_flags, ~mask));
+
+    f = (priv->interface_flags & ~mask) | (interface_flags & mask);
+
+    if (f == priv->interface_flags)
+        return FALSE;
+
+    priv->interface_flags = f;
+    if (notify)
+        _notify(self, PROP_INTERFACE_FLAGS);
+    return TRUE;
+}
+
+static gboolean
+set_interface_flags(NMDevice *             self,
+                    NMDeviceInterfaceFlags interface_flags,
+                    gboolean               set,
+                    gboolean               notify)
+{
+    return set_interface_flags_full(self,
+                                    interface_flags,
+                                    set ? interface_flags : NM_DEVICE_INTERFACE_FLAG_NONE,
+                                    notify);
+}
+
 void
 nm_device_assume_state_get(NMDevice *   self,
                            gboolean *   out_assume_state_guess_assume,
@@ -2810,15 +2787,6 @@ _add_capabilities(NMDevice *self, NMDeviceCapabilities capabilities)
 
 /*****************************************************************************/
 
-static NM_UTILS_LOOKUP_STR_DEFINE(_ip_state_to_string,
-                                  NMDeviceIPState,
-                                  NM_UTILS_LOOKUP_DEFAULT_WARN("unknown"),
-                                  NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_NONE, "none"),
-                                  NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_WAIT, "wait"),
-                                  NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_CONF, "conf"),
-                                  NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_DONE, "done"),
-                                  NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_FAIL, "fail"), );
-
 static void
 _set_ip_state(NMDevice *self, int addr_family, NMDeviceIPState new_state)
 {
@@ -2834,7 +2802,7 @@ _set_ip_state(NMDevice *self, int addr_family, NMDeviceIPState new_state)
           "ip%c-state: set to %d (%s)",
           nm_utils_addr_family_to_char(addr_family),
           (int) new_state,
-          _ip_state_to_string(new_state));
+          nm_device_ip_state_to_str(new_state));
 
     priv->ip_state_x_[IS_IPv4] = new_state;
 
@@ -2943,10 +2911,10 @@ nm_device_take_over_link(NMDevice *self, int ifindex, char **old_name, GError **
 
         /* Rename the link to the device ifname */
         if (up)
-            nm_platform_link_set_down(platform, ifindex);
+            nm_platform_link_change_flags(platform, ifindex, IFF_UP, FALSE);
         success = nm_platform_link_set_name(platform, ifindex, nm_device_get_iface(self));
         if (up)
-            nm_platform_link_set_up(platform, ifindex, NULL);
+            nm_platform_link_change_flags(platform, ifindex, IFF_UP, TRUE);
 
         if (!success) {
             nm_utils_error_set(error, NM_UTILS_ERROR_UNKNOWN, "failure renaming link %d", ifindex);
@@ -3074,7 +3042,7 @@ _set_ip_ifindex(NMDevice *self, int ifindex, const char *ifname)
             nm_platform_link_set_user_ipv6ll_enabled(platform, priv->ip_ifindex, TRUE);
 
         if (!nm_platform_link_is_up(platform, priv->ip_ifindex))
-            nm_platform_link_set_up(platform, priv->ip_ifindex, NULL);
+            nm_platform_link_change_flags(platform, priv->ip_ifindex, IFF_UP, TRUE);
     }
 
     /* We don't care about any saved values from the old iface */
@@ -4870,7 +4838,6 @@ void
 nm_device_update_dynamic_ip_setup(NMDevice *self)
 {
     NMDevicePrivate *priv;
-    GError *         error = NULL;
 
     g_return_if_fail(NM_IS_DEVICE(self));
 
@@ -4903,17 +4870,6 @@ nm_device_update_dynamic_ip_setup(NMDevice *self)
     if (priv->dnsmasq_manager) {
         /* FIXME: todo */
     }
-
-    if (priv->lldp_listener && nm_lldp_listener_is_running(priv->lldp_listener)) {
-        nm_lldp_listener_stop(priv->lldp_listener);
-        if (!nm_lldp_listener_start(priv->lldp_listener, nm_device_get_ifindex(self), &error)) {
-            _LOGD(LOGD_DEVICE,
-                  "LLDP listener %p could not be restarted: %s",
-                  priv->lldp_listener,
-                  error->message);
-            g_clear_error(&error);
-        }
-    }
 }
 
 /*****************************************************************************/
@@ -5030,18 +4986,12 @@ nm_device_set_carrier(NMDevice *self, gboolean carrier)
 
     if (NM_FLAGS_ALL(priv->capabilities,
                      NM_DEVICE_CAP_CARRIER_DETECT | NM_DEVICE_CAP_NONSTANDARD_CARRIER)) {
-        if (carrier)
-            priv->interface_flags |= NM_DEVICE_INTERFACE_FLAG_CARRIER;
-        else
-            priv->interface_flags &= ~NM_DEVICE_INTERFACE_FLAG_CARRIER;
-        notify_flags = TRUE;
+        notify_flags = set_interface_flags(self, NM_DEVICE_INTERFACE_FLAG_CARRIER, carrier, FALSE);
     }
 
     priv->carrier = carrier;
-    if (notify_flags)
-        nm_gobject_notify_together(self, PROP_CARRIER, PROP_INTERFACE_FLAGS);
-    else
-        _notify(self, PROP_CARRIER);
+
+    nm_gobject_notify_together(self, PROP_CARRIER, notify_flags ? PROP_INTERFACE_FLAGS : PROP_0);
 
     if (priv->carrier) {
         _LOGI(LOGD_DEVICE, "carrier: link connected");
@@ -5216,11 +5166,11 @@ ndisc_set_router_config(NMNDisc *ndisc, NMDevice *self)
         if (addr->plen != 64)
             continue;
 
-        lifetime = nm_utils_lifetime_get(addr->timestamp,
-                                         addr->lifetime,
-                                         addr->preferred,
-                                         NM_NDISC_EXPIRY_BASE_TIMESTAMP / 1000,
-                                         &preferred);
+        lifetime = nmp_utils_lifetime_get(addr->timestamp,
+                                          addr->lifetime,
+                                          addr->preferred,
+                                          NM_NDISC_EXPIRY_BASE_TIMESTAMP / 1000,
+                                          &preferred);
         if (!lifetime)
             continue;
 
@@ -5272,6 +5222,8 @@ device_update_interface_flags(NMDevice *self, const NMPlatformLink *plink)
         flags |= NM_DEVICE_INTERFACE_FLAG_UP;
     if (plink && NM_FLAGS_HAS(plink->n_ifi_flags, IFF_LOWER_UP))
         flags |= NM_DEVICE_INTERFACE_FLAG_LOWER_UP;
+    if (plink && NM_FLAGS_HAS(plink->n_ifi_flags, IFF_PROMISC))
+        flags |= NM_DEVICE_INTERFACE_FLAG_PROMISC;
 
     if (NM_FLAGS_ALL(priv->capabilities,
                      NM_DEVICE_CAP_CARRIER_DETECT | NM_DEVICE_CAP_NONSTANDARD_CARRIER)) {
@@ -5282,10 +5234,12 @@ device_update_interface_flags(NMDevice *self, const NMPlatformLink *plink)
             flags |= NM_DEVICE_INTERFACE_FLAG_CARRIER;
     }
 
-    if (flags != priv->interface_flags) {
-        priv->interface_flags = flags;
-        _notify(self, PROP_INTERFACE_FLAGS);
-    }
+    set_interface_flags_full(self,
+                             NM_DEVICE_INTERFACE_FLAG_UP | NM_DEVICE_INTERFACE_FLAG_LOWER_UP
+                                 | NM_DEVICE_INTERFACE_FLAG_CARRIER
+                                 | NM_DEVICE_INTERFACE_FLAG_PROMISC,
+                             flags,
+                             TRUE);
 }
 
 static gboolean
@@ -5415,11 +5369,11 @@ device_link_changed(NMDevice *self)
                 /* Ensure the assume check is queued before any queued state changes
                  * from the transition to UNAVAILABLE.
                  */
-                nm_device_queue_recheck_assume(self);
                 reason = NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED;
             }
         }
 
+        nm_device_queue_recheck_assume(self);
         nm_device_set_unmanaged_by_flags(self, NM_UNMANAGED_PLATFORM_INIT, FALSE, reason);
     }
 
@@ -5892,16 +5846,19 @@ sriov_op_queue(NMDevice *              self,
 static void
 device_init_static_sriov_num_vfs(NMDevice *self)
 {
-    NMDevicePrivate *priv  = NM_DEVICE_GET_PRIVATE(self);
-    gs_free char *   value = NULL;
-    int              num_vfs;
+    NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
 
     if (priv->ifindex > 0 && nm_device_has_capability(self, NM_DEVICE_CAP_SRIOV)) {
-        value   = nm_config_data_get_device_config(NM_CONFIG_GET_DATA,
-                                                 NM_CONFIG_KEYFILE_KEY_DEVICE_SRIOV_NUM_VFS,
-                                                 self,
-                                                 NULL);
-        num_vfs = _nm_utils_ascii_str_to_int64(value, 10, 0, G_MAXINT32, -1);
+        int num_vfs;
+
+        num_vfs = nm_config_data_get_device_config_int64(NM_CONFIG_GET_DATA,
+                                                         NM_CONFIG_KEYFILE_KEY_DEVICE_SRIOV_NUM_VFS,
+                                                         self,
+                                                         10,
+                                                         0,
+                                                         G_MAXINT32,
+                                                         -1,
+                                                         -1);
         if (num_vfs >= 0)
             sriov_op_queue(self, num_vfs, NM_OPTION_BOOL_DEFAULT, NULL, NULL);
     }
@@ -7215,7 +7172,7 @@ nm_device_generate_connection(NMDevice *self,
 
     g_object_set(s_con,
                  NM_SETTING_CONNECTION_UUID,
-                 nm_utils_uuid_generate_buf(uuid),
+                 nm_uuid_generate_random_str_arr(uuid),
                  NM_SETTING_CONNECTION_ID,
                  ifname,
                  NM_SETTING_CONNECTION_AUTOCONNECT,
@@ -7467,11 +7424,10 @@ check_connection_compatible(NMDevice *self, NMConnection *connection, GError **e
     s_match = (NMSettingMatch *) nm_connection_get_setting(connection, NM_TYPE_SETTING_MATCH);
     if (s_match) {
         const char *const *patterns;
-        const char *       device_driver;
         guint              num_patterns = 0;
 
         patterns = nm_setting_match_get_interface_names(s_match, &num_patterns);
-        if (!nm_wildcard_match_check(device_iface, patterns, num_patterns)) {
+        if (num_patterns > 0 && !nm_wildcard_match_check(device_iface, patterns, num_patterns)) {
             nm_utils_error_set_literal(error,
                                        NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
                                        "device does not satisfy match.interface-name property");
@@ -7486,9 +7442,9 @@ check_connection_compatible(NMDevice *self, NMConnection *connection, GError **e
                                                     error))
             return FALSE;
 
-        device_driver = nm_device_get_driver(self);
-        patterns      = nm_setting_match_get_drivers(s_match, &num_patterns);
-        if (!nm_wildcard_match_check(device_driver, patterns, num_patterns)) {
+        patterns = nm_setting_match_get_drivers(s_match, &num_patterns);
+        if (num_patterns > 0
+            && !nm_wildcard_match_check(nm_device_get_driver(self), patterns, num_patterns)) {
             nm_utils_error_set_literal(error,
                                        NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
                                        "device does not satisfy match.driver property");
@@ -7496,7 +7452,7 @@ check_connection_compatible(NMDevice *self, NMConnection *connection, GError **e
         }
 
         patterns = nm_setting_match_get_paths(s_match, &num_patterns);
-        if (!nm_wildcard_match_check(priv->path, patterns, num_patterns)) {
+        if (num_patterns > 0 && !nm_wildcard_match_check(priv->path, patterns, num_patterns)) {
             nm_utils_error_set_literal(error,
                                        NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE,
                                        "device does not satisfy match.path property");
@@ -7925,14 +7881,6 @@ master_ready_cb(NMActiveConnection *active, GParamSpec *pspec, NMDevice *self)
         nm_device_activate_schedule_stage1_device_prepare(self, FALSE);
 }
 
-static void
-lldp_neighbors_changed(NMLldpListener *lldp_listener, GParamSpec *pspec, gpointer user_data)
-{
-    NMDevice *self = NM_DEVICE(user_data);
-
-    _notify(self, PROP_LLDP_NEIGHBORS);
-}
-
 static NMPlatformVF *
 sriov_vf_config_to_platform(NMDevice *self, NMSriovVF *vf, GError **error)
 {
@@ -8220,38 +8168,56 @@ act_stage2_config(NMDevice *self, NMDeviceStateReason *out_failure_reason)
 }
 
 static void
-lldp_init(NMDevice *self, gboolean restart)
+_lldp_neighbors_changed_cb(NMLldpListener *lldp_listener, gpointer user_data)
+{
+    _notify(user_data, PROP_LLDP_NEIGHBORS);
+}
+
+static void
+lldp_setup(NMDevice *self, NMTernary enabled)
 {
     NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+    int              ifindex;
+    gboolean         notify_lldp_neighbors  = FALSE;
+    gboolean         notify_interface_flags = FALSE;
 
-    if (priv->ifindex > 0 && _prop_get_connection_lldp(self)) {
-        gs_free_error GError *error = NULL;
+    ifindex = nm_device_get_ifindex(self);
 
-        if (priv->lldp_listener) {
-            if (restart && nm_lldp_listener_is_running(priv->lldp_listener))
-                nm_lldp_listener_stop(priv->lldp_listener);
-        } else {
-            priv->lldp_listener = nm_lldp_listener_new();
-            g_signal_connect(priv->lldp_listener,
-                             "notify::" NM_LLDP_LISTENER_NEIGHBORS,
-                             G_CALLBACK(lldp_neighbors_changed),
-                             self);
-        }
+    if (ifindex <= 0)
+        enabled = FALSE;
+    else if (enabled == NM_TERNARY_DEFAULT)
+        enabled = _prop_get_connection_lldp(self);
 
-        if (!nm_lldp_listener_is_running(priv->lldp_listener)) {
-            if (nm_lldp_listener_start(priv->lldp_listener, nm_device_get_ifindex(self), &error))
-                _LOGD(LOGD_DEVICE, "LLDP listener %p started", priv->lldp_listener);
-            else {
-                _LOGD(LOGD_DEVICE,
-                      "LLDP listener %p could not be started: %s",
-                      priv->lldp_listener,
-                      error->message);
-            }
+    if (priv->lldp_listener) {
+        if (!enabled || nm_lldp_listener_get_ifindex(priv->lldp_listener) != ifindex) {
+            nm_clear_pointer(&priv->lldp_listener, nm_lldp_listener_destroy);
+            notify_lldp_neighbors = TRUE;
         }
-    } else {
-        if (priv->lldp_listener)
-            nm_lldp_listener_stop(priv->lldp_listener);
     }
+
+    if (enabled && !priv->lldp_listener) {
+        gs_free_error GError *error = NULL;
+
+        priv->lldp_listener =
+            nm_lldp_listener_new(ifindex, _lldp_neighbors_changed_cb, self, &error);
+        if (!priv->lldp_listener) {
+            /* This really shouldn't happen. It's likely a bug. Investigate when this happens! */
+            _LOGW(LOGD_DEVICE,
+                  "LLDP listener for ifindex %d could not be started: %s",
+                  ifindex,
+                  error->message);
+        } else
+            notify_lldp_neighbors = TRUE;
+    }
+
+    notify_interface_flags = set_interface_flags(self,
+                                                 NM_DEVICE_INTERFACE_FLAG_LLDP_CLIENT_ENABLED,
+                                                 !!priv->lldp_listener,
+                                                 FALSE);
+
+    nm_gobject_notify_together(self,
+                               notify_lldp_neighbors ? PROP_LLDP_NEIGHBORS : PROP_0,
+                               notify_interface_flags ? PROP_INTERFACE_FLAGS : PROP_0);
 }
 
 /* set-mode can be:
@@ -8362,26 +8328,23 @@ _routing_rules_sync(NMDevice *self, NMTernary set_mode)
 static gboolean
 tc_commit(NMDevice *self)
 {
-    NMConnection *    connection          = NULL;
     gs_unref_ptrarray GPtrArray *qdiscs   = NULL;
     gs_unref_ptrarray GPtrArray *tfilters = NULL;
-    NMSettingTCConfig *          s_tc     = NULL;
+    NMSettingTCConfig *          s_tc;
     NMPlatform *                 platform;
     int                          ip_ifindex;
 
-    platform   = nm_device_get_platform(self);
-    connection = nm_device_get_applied_connection(self);
-    if (connection)
-        s_tc = nm_connection_get_setting_tc_config(connection);
+    s_tc = nm_device_get_applied_setting(self, NM_TYPE_SETTING_TC_CONFIG);
+    if (!s_tc)
+        return TRUE;
 
     ip_ifindex = nm_device_get_ip_ifindex(self);
     if (!ip_ifindex)
-        return s_tc == NULL;
+        return FALSE;
 
-    if (s_tc) {
-        qdiscs   = nm_utils_qdiscs_from_tc_setting(platform, s_tc, ip_ifindex);
-        tfilters = nm_utils_tfilters_from_tc_setting(platform, s_tc, ip_ifindex);
-    }
+    platform = nm_device_get_platform(self);
+    qdiscs   = nm_utils_qdiscs_from_tc_setting(platform, s_tc, ip_ifindex);
+    tfilters = nm_utils_tfilters_from_tc_setting(platform, s_tc, ip_ifindex);
 
     if (!nm_platform_qdisc_sync(platform, ip_ifindex, qdiscs))
         return FALSE;
@@ -8405,8 +8368,10 @@ activate_stage2_device_config(NMDevice *self)
     NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
     NMDeviceClass *  klass;
     NMActStageReturn ret;
+    NMSettingWired * s_wired;
     gboolean         no_firmware = FALSE;
     CList *          iter;
+    NMTernary        accept_all_mac_addresses;
 
     nm_device_state_changed(self, NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_REASON_NONE);
 
@@ -8464,7 +8429,30 @@ activate_stage2_device_config(NMDevice *self)
             nm_device_queue_recheck_assume(info->slave);
     }
 
-    lldp_init(self, TRUE);
+    s_wired = nm_device_get_applied_setting(self, NM_TYPE_SETTING_WIRED);
+    accept_all_mac_addresses =
+        s_wired ? nm_setting_wired_get_accept_all_mac_addresses(s_wired) : NM_TERNARY_DEFAULT;
+    if (accept_all_mac_addresses != NM_TERNARY_DEFAULT) {
+        int ifindex = nm_device_get_ip_ifindex(self);
+
+        if (ifindex > 0) {
+            int ifi_flags =
+                nm_platform_link_get_ifi_flags(nm_device_get_platform(self), ifindex, IFF_PROMISC);
+
+            if (ifi_flags >= 0 && ((!!ifi_flags) != (!!accept_all_mac_addresses))) {
+                nm_platform_link_change_flags(nm_device_get_platform(self),
+                                              ifindex,
+                                              IFF_PROMISC,
+                                              !!accept_all_mac_addresses);
+                if (priv->promisc_reset == NM_OPTION_BOOL_DEFAULT)
+                    priv->promisc_reset = !accept_all_mac_addresses;
+            }
+        }
+    }
+
+    lldp_setup(self, NM_TERNARY_DEFAULT);
+
+    _commit_mtu(self, NULL);
 
     nm_device_activate_schedule_stage3_ip_config_start(self);
 }
@@ -8881,6 +8869,21 @@ ensure_con_ip_config(NMDevice *self, int addr_family)
 
 /*****************************************************************************/
 
+static const char *
+_device_get_dhcp_anycast_address(NMDevice *self)
+{
+    NMDeviceClass *klass;
+
+    nm_assert(NM_IS_DEVICE(self));
+
+    klass = NM_DEVICE_GET_CLASS(self);
+
+    if (klass->get_dhcp_anycast_address)
+        return klass->get_dhcp_anycast_address(self);
+
+    return NULL;
+}
+
 static void
 dhcp4_cleanup(NMDevice *self, CleanupType cleanup_type, gboolean release)
 {
@@ -9238,7 +9241,7 @@ dhcp4_fail(NMDevice *self, NMDhcpState dhcp_state)
 
     _LOGD(LOGD_DHCP4,
           "DHCPv4 failed (ip_state %s, was_active %d)",
-          _ip_state_to_string(priv->ip_state_4),
+          nm_device_ip_state_to_str(priv->ip_state_4),
           priv->dhcp_data_4.was_active);
 
     /* The client is always left running after a failure. */
@@ -9386,12 +9389,13 @@ dhcp4_start(NMDevice *self)
     gs_unref_bytes GBytes *hwaddr                  = NULL;
     gs_unref_bytes GBytes *bcast_hwaddr            = NULL;
     gs_unref_bytes GBytes *client_id               = NULL;
-    gs_free char *         mud_url_free            = NULL;
     NMConnection *         connection;
     NMSettingConnection *  s_con;
     GError *               error = NULL;
     const NMPlatformLink * pllink;
     const char *const *    reject_servers;
+    gboolean               request_broadcast;
+    const char *           str;
 
     connection = nm_device_get_applied_connection(self);
     g_return_val_if_fail(connection, FALSE);
@@ -9405,10 +9409,22 @@ dhcp4_start(NMDevice *self)
     nm_dbus_object_clear_and_unexport(&priv->dhcp_data_4.config);
     priv->dhcp_data_4.config = nm_dhcp_config_new(AF_INET);
 
+    request_broadcast = FALSE;
+
     pllink = nm_platform_link_get(nm_device_get_platform(self), nm_device_get_ip_ifindex(self));
     if (pllink) {
         hwaddr       = nmp_link_address_get_as_bytes(&pllink->l_address);
         bcast_hwaddr = nmp_link_address_get_as_bytes(&pllink->l_broadcast);
+
+        str = nmp_object_link_udev_device_get_property_value(NMP_OBJECT_UP_CAST(pllink),
+                                                             "ID_NET_DHCP_BROADCAST");
+        if (str && _nm_utils_ascii_str_to_bool(str, FALSE)) {
+            /* Use the device property ID_NET_DHCP_BROADCAST setting, which may be set for interfaces
+             * requiring that the DHCPOFFER message is being broadcast because they can't handle unicast
+             * messages while not fully configured.
+             */
+            request_broadcast = TRUE;
+        }
     }
 
     client_id = _prop_get_ipv4_dhcp_client_id(self, connection, hwaddr);
@@ -9417,28 +9433,29 @@ dhcp4_start(NMDevice *self)
     reject_servers = nm_setting_ip_config_get_dhcp_reject_servers(s_ip4, NULL);
 
     g_warn_if_fail(priv->dhcp_data_4.client == NULL);
-    priv->dhcp_data_4.client =
-        nm_dhcp_manager_start_ip4(nm_dhcp_manager_get(),
-                                  nm_netns_get_multi_idx(nm_device_get_netns(self)),
-                                  nm_device_get_ip_iface(self),
-                                  nm_device_get_ip_ifindex(self),
-                                  hwaddr,
-                                  bcast_hwaddr,
-                                  nm_connection_get_uuid(connection),
-                                  nm_device_get_route_table(self, AF_INET),
-                                  nm_device_get_route_metric(self, AF_INET),
-                                  nm_setting_ip_config_get_dhcp_send_hostname(s_ip4),
-                                  nm_setting_ip_config_get_dhcp_hostname(s_ip4),
-                                  nm_setting_ip4_config_get_dhcp_fqdn(NM_SETTING_IP4_CONFIG(s_ip4)),
-                                  _prop_get_ipvx_dhcp_hostname_flags(self, AF_INET),
-                                  _prop_get_connection_mud_url(self, s_con, &mud_url_free),
-                                  client_id,
-                                  _prop_get_ipvx_dhcp_timeout(self, AF_INET),
-                                  priv->dhcp_anycast_address,
-                                  NULL,
-                                  vendor_class_identifier,
-                                  reject_servers,
-                                  &error);
+    priv->dhcp_data_4.client = nm_dhcp_manager_start_ip4(
+        nm_dhcp_manager_get(),
+        nm_netns_get_multi_idx(nm_device_get_netns(self)),
+        nm_device_get_ip_iface(self),
+        nm_device_get_ip_ifindex(self),
+        hwaddr,
+        bcast_hwaddr,
+        nm_connection_get_uuid(connection),
+        nm_device_get_route_table(self, AF_INET),
+        nm_device_get_route_metric(self, AF_INET),
+        request_broadcast ? NM_DHCP_CLIENT_FLAGS_REQUEST_BROADCAST : NM_DHCP_CLIENT_FLAGS_NONE,
+        nm_setting_ip_config_get_dhcp_send_hostname(s_ip4),
+        nm_setting_ip_config_get_dhcp_hostname(s_ip4),
+        nm_setting_ip4_config_get_dhcp_fqdn(NM_SETTING_IP4_CONFIG(s_ip4)),
+        _prop_get_ipvx_dhcp_hostname_flags(self, AF_INET),
+        _prop_get_connection_mud_url(self, s_con),
+        client_id,
+        _prop_get_ipvx_dhcp_timeout(self, AF_INET),
+        _device_get_dhcp_anycast_address(self),
+        NULL,
+        vendor_class_identifier,
+        reject_servers,
+        &error);
     if (!priv->dhcp_data_4.client) {
         _LOGW(LOGD_DHCP4, "failure to start DHCP: %s", error->message);
         g_clear_error(&error);
@@ -9669,7 +9686,7 @@ dhcp6_fail(NMDevice *self, NMDhcpState dhcp_state)
 
     _LOGD(LOGD_DHCP6,
           "DHCPv6 failed (ip_state %s, was_active %d)",
-          _ip_state_to_string(priv->ip_state_6),
+          nm_device_ip_state_to_str(priv->ip_state_6),
           priv->dhcp_data_6.was_active);
 
     /* The client is always left running after a failure. */
@@ -9835,8 +9852,7 @@ dhcp6_start_with_link_ready(NMDevice *self, NMConnection *connection)
     gs_unref_bytes GBytes *     duid         = NULL;
     gboolean                    enforce_duid = FALSE;
     const NMPlatformLink *      pllink;
-    gs_free char *              mud_url_free = NULL;
-    GError *                    error        = NULL;
+    GError *                    error = NULL;
     guint32                     iaid;
     gboolean                    iaid_explicit;
     NMSettingConnection *       s_con;
@@ -9850,9 +9866,9 @@ dhcp6_start_with_link_ready(NMDevice *self, NMConnection *connection)
     nm_assert(s_con);
 
     if (priv->ext_ip6_config_captured) {
-        ll_addr = nm_ip6_config_find_first_address(priv->ext_ip6_config_captured,
-                                                   NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL
-                                                       | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL);
+        ll_addr = nm_ip_config_find_first_address(NM_IP_CONFIG(priv->ext_ip6_config_captured),
+                                                  NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL
+                                                      | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL);
     }
 
     if (!ll_addr) {
@@ -9876,17 +9892,18 @@ dhcp6_start_with_link_ready(NMDevice *self, NMConnection *connection)
         nm_connection_get_uuid(connection),
         nm_device_get_route_table(self, AF_INET6),
         nm_device_get_route_metric(self, AF_INET6),
+        (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_OTHERCONF) ? NM_DHCP_CLIENT_FLAGS_INFO_ONLY
+                                                            : NM_DHCP_CLIENT_FLAGS_NONE,
         nm_setting_ip_config_get_dhcp_send_hostname(s_ip6),
         nm_setting_ip_config_get_dhcp_hostname(s_ip6),
         _prop_get_ipvx_dhcp_hostname_flags(self, AF_INET6),
-        _prop_get_connection_mud_url(self, s_con, &mud_url_free),
+        _prop_get_connection_mud_url(self, s_con),
         duid,
         enforce_duid,
         iaid,
         iaid_explicit,
         _prop_get_ipvx_dhcp_timeout(self, AF_INET6),
-        priv->dhcp_anycast_address,
-        (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_OTHERCONF) ? TRUE : FALSE,
+        _device_get_dhcp_anycast_address(self),
         nm_setting_ip6_config_get_ip6_privacy(NM_SETTING_IP6_CONFIG(s_ip6)),
         priv->dhcp6.needed_prefixes,
         &error);
@@ -10090,9 +10107,9 @@ linklocal6_check_complete(NMDevice *self)
     }
 
     if (!priv->ext_ip6_config_captured
-        || !nm_ip6_config_find_first_address(priv->ext_ip6_config_captured,
-                                             NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL
-                                                 | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL)) {
+        || !nm_ip_config_find_first_address(NM_IP_CONFIG(priv->ext_ip6_config_captured),
+                                            NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL
+                                                | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL)) {
         /* we don't have a non-tentative link local address yet. Wait longer. */
         return;
     }
@@ -10138,10 +10155,10 @@ check_and_add_ipv6ll_addr(NMDevice *self)
         return;
 
     if (priv->ext_ip6_config_captured
-        && nm_ip6_config_find_first_address(priv->ext_ip6_config_captured,
-                                            NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL
-                                                | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL
-                                                | NM_PLATFORM_MATCH_WITH_ADDRSTATE_TENTATIVE)) {
+        && nm_ip_config_find_first_address(NM_IP_CONFIG(priv->ext_ip6_config_captured),
+                                           NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL
+                                               | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL
+                                               | NM_PLATFORM_MATCH_WITH_ADDRSTATE_TENTATIVE)) {
         /* Already have an LL address, nothing to do */
         return;
     }
@@ -10211,9 +10228,9 @@ linklocal6_start(NMDevice *self)
     nm_clear_g_source(&priv->linklocal6_timeout_id);
 
     if (priv->ext_ip6_config_captured
-        && nm_ip6_config_find_first_address(priv->ext_ip6_config_captured,
-                                            NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL
-                                                | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL))
+        && nm_ip_config_find_first_address(NM_IP_CONFIG(priv->ext_ip6_config_captured),
+                                           NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL
+                                               | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL))
         return TRUE;
 
     _LOGD(LOGD_DEVICE,
@@ -10458,9 +10475,9 @@ _commit_mtu(NMDevice *self, const NMIP4Config *config)
             _LOGT(LOGD_DEVICE,
                   "mtu: value %u from source '%s' (%u), current source '%s' (%u)%s",
                   (guint) mtu,
-                  mtu_source_to_str(source),
+                  nm_device_mtu_source_to_str(source),
                   (guint) source,
-                  mtu_source_to_str(priv->mtu_source),
+                  nm_device_mtu_source_to_str(priv->mtu_source),
                   (guint) priv->mtu_source,
                   force ? " (forced)" : "");
         }
@@ -10792,9 +10809,9 @@ ndisc_ra_timeout(NMNDisc *ndisc, NMDevice *self)
          *        addresses we find inside priv->ip_config_6.
          */
         if (priv->ip_config_6
-            && nm_ip6_config_find_first_address(priv->ip_config_6,
-                                                NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL
-                                                    | NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY))
+            && nm_ip_config_find_first_address(NM_IP_CONFIG(priv->ip_config_6),
+                                               NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL
+                                                   | NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY))
             nm_device_activate_schedule_ip_config_result(self, AF_INET6, NULL);
         else
             nm_device_activate_schedule_ip_config_timeout(self, AF_INET6);
@@ -11397,10 +11414,10 @@ activate_stage3_ip_config_start(NMDevice *self)
 }
 
 static void
-fw_change_zone_cb(NMFirewallManager *      firewall_manager,
-                  NMFirewallManagerCallId *call_id,
-                  GError *                 error,
-                  gpointer                 user_data)
+fw_change_zone_cb(NMFirewalldManager *      firewalld_manager,
+                  NMFirewalldManagerCallId *call_id,
+                  GError *                  error,
+                  gpointer                  user_data)
 {
     NMDevice *       self = user_data;
     NMDevicePrivate *priv;
@@ -11452,12 +11469,12 @@ fw_change_zone(NMDevice *self)
     nm_assert(s_con);
 
     if (priv->fw_call) {
-        nm_firewall_manager_cancel_call(priv->fw_call);
+        nm_firewalld_manager_cancel_call(priv->fw_call);
         nm_assert(!priv->fw_call);
     }
 
     if (G_UNLIKELY(!priv->fw_mgr))
-        priv->fw_mgr = g_object_ref(nm_firewall_manager_get());
+        priv->fw_mgr = g_object_ref(nm_firewalld_manager_get());
 
     zone = nm_setting_connection_get_zone(s_con);
 #if WITH_FIREWALLD_ZONE
@@ -11469,12 +11486,12 @@ fw_change_zone(NMDevice *self)
             zone = "nm-shared";
     }
 #endif
-    priv->fw_call = nm_firewall_manager_add_or_change_zone(priv->fw_mgr,
-                                                           nm_device_get_ip_iface(self),
-                                                           zone,
-                                                           FALSE, /* change zone */
-                                                           fw_change_zone_cb,
-                                                           self);
+    priv->fw_call = nm_firewalld_manager_add_or_change_zone(priv->fw_mgr,
+                                                            nm_device_get_ip_iface(self),
+                                                            zone,
+                                                            FALSE, /* change zone */
+                                                            fw_change_zone_cb,
+                                                            self);
 }
 
 /*
@@ -11634,7 +11651,7 @@ share_init(NMDevice *self, GError **error)
     }
 
     for (i = 0; i < G_N_ELEMENTS(modules); i++)
-        nm_utils_modprobe(NULL, FALSE, modules[i], NULL);
+        nmp_utils_modprobe(NULL, FALSE, modules[i], NULL);
 
     return TRUE;
 }
@@ -11650,7 +11667,7 @@ start_sharing(NMDevice *self, NMIP4Config *config, GError **error)
     NMConnection *              conn;
     NMSettingConnection *       s_con;
     gboolean                    announce_android_metered;
-    NMUtilsShareRules *         share_rules;
+    NMFirewallConfig *          firewall_config;
 
     g_return_val_if_fail(config, FALSE);
 
@@ -11675,13 +11692,9 @@ start_sharing(NMDevice *self, NMIP4Config *config, GError **error)
     req = nm_device_get_act_request(self);
     g_return_val_if_fail(req, FALSE);
 
-    share_rules = nm_utils_share_rules_new();
-
-    nm_utils_share_rules_add_all_rules(share_rules, ip_iface, ip4_addr->address, ip4_addr->plen);
+    firewall_config = nm_firewall_config_new(ip_iface, ip4_addr->address, ip4_addr->plen);
 
-    nm_utils_share_rules_apply(share_rules, TRUE);
-
-    nm_act_request_set_shared(req, share_rules);
+    nm_act_request_set_shared(req, firewall_config);
 
     conn  = nm_act_request_get_applied_connection(req);
     s_con = nm_connection_get_setting_connection(conn);
@@ -11803,7 +11816,7 @@ activate_stage5_ip_config_result_x(NMDevice *self, int addr_family)
 
     if (!nm_platform_link_is_up(nm_device_get_platform(self), ip_ifindex)
         && !nm_device_sys_iface_state_is_external_or_assume(self)) {
-        nm_platform_link_set_up(nm_device_get_platform(self), ip_ifindex, NULL);
+        nm_platform_link_change_flags(nm_device_get_platform(self), ip_ifindex, IFF_UP, TRUE);
         if (!nm_platform_link_is_up(nm_device_get_platform(self), ip_ifindex))
             _LOGW(LOGD_DEVICE,
                   "interface %s not up for IP configuration",
@@ -12141,28 +12154,19 @@ nm_device_is_nm_owned(NMDevice *self)
 static gboolean
 delete_on_deactivate_link_delete(gpointer user_data)
 {
-    DeleteOnDeactivateData *data = user_data;
-    NMDevice *              self = data->device;
+    DeleteOnDeactivateData *data        = user_data;
+    nm_auto_unref_object NMDevice *self = data->device;
+    NMDevicePrivate *              priv = NM_DEVICE_GET_PRIVATE(self);
+    gs_free_error GError *error         = NULL;
 
     _LOGD(LOGD_DEVICE,
-          "delete_on_deactivate: cleanup and delete virtual link #%d (id=%u)",
-          data->ifindex,
+          "delete_on_deactivate: cleanup and delete virtual link (id=%u)",
           data->idle_add_id);
 
-    if (data->device) {
-        NMDevicePrivate *priv       = NM_DEVICE_GET_PRIVATE(data->device);
-        gs_free_error GError *error = NULL;
-
-        g_object_remove_weak_pointer(G_OBJECT(data->device), (void **) &data->device);
-        priv->delete_on_deactivate_data = NULL;
+    priv->delete_on_deactivate_data = NULL;
 
-        if (!nm_device_unrealize(data->device, TRUE, &error))
-            _LOGD(LOGD_DEVICE,
-                  "delete_on_deactivate: unrealizing %d failed (%s)",
-                  data->ifindex,
-                  error->message);
-    } else if (data->ifindex > 0)
-        nm_platform_link_delete(nm_device_get_platform(self), data->ifindex);
+    if (!nm_device_unrealize(self, TRUE, &error))
+        _LOGD(LOGD_DEVICE, "delete_on_deactivate: unrealizing failed (%s)", error->message);
 
     nm_device_emit_recheck_auto_activate(self);
 
@@ -12181,17 +12185,16 @@ delete_on_deactivate_unschedule(NMDevice *self)
         priv->delete_on_deactivate_data = NULL;
 
         g_source_remove(data->idle_add_id);
-        g_object_remove_weak_pointer(G_OBJECT(self), (void **) &data->device);
         _LOGD(LOGD_DEVICE,
-              "delete_on_deactivate: cancel cleanup and delete virtual link #%d (id=%u)",
-              data->ifindex,
+              "delete_on_deactivate: cancel cleanup and delete virtual link (id=%u)",
               data->idle_add_id);
+        g_object_unref(data->device);
         g_free(data);
     }
 }
 
 static void
-delete_on_deactivate_check_and_schedule(NMDevice *self, int ifindex)
+delete_on_deactivate_check_and_schedule(NMDevice *self)
 {
     NMDevicePrivate *       priv = NM_DEVICE_GET_PRIVATE(self);
     DeleteOnDeactivateData *data;
@@ -12208,16 +12211,13 @@ delete_on_deactivate_check_and_schedule(NMDevice *self, int ifindex)
         return;
     delete_on_deactivate_unschedule(self); /* always cancel and reschedule */
 
-    data = g_new(DeleteOnDeactivateData, 1);
-    g_object_add_weak_pointer(G_OBJECT(self), (void **) &data->device);
-    data->device                    = self;
-    data->ifindex                   = ifindex;
+    data                            = g_new(DeleteOnDeactivateData, 1);
+    data->device                    = g_object_ref(self);
     data->idle_add_id               = g_idle_add(delete_on_deactivate_link_delete, data);
     priv->delete_on_deactivate_data = data;
 
     _LOGD(LOGD_DEVICE,
-          "delete_on_deactivate: schedule cleanup and delete virtual link #%d (id=%u)",
-          ifindex,
+          "delete_on_deactivate: schedule cleanup and delete virtual link (id=%u)",
           data->idle_add_id);
 }
 
@@ -12696,7 +12696,7 @@ check_and_reapply_connection(NMDevice *    self,
     klass->reapply_connection(self, con_old, con_new);
 
     if (priv->state >= NM_DEVICE_STATE_CONFIG)
-        lldp_init(self, FALSE);
+        lldp_setup(self, NM_TERNARY_DEFAULT);
 
     if (priv->state >= NM_DEVICE_STATE_IP_CONFIG) {
         s_ip4_old = nm_connection_get_setting_ip4_config(con_old);
@@ -12927,9 +12927,10 @@ impl_device_get_applied_connection(NMDBusObject *                     obj,
         return;
     }
 
-    var_settings = nm_connection_to_dbus(applied_connection, NM_CONNECTION_SERIALIZE_NO_SECRETS);
+    var_settings =
+        nm_connection_to_dbus(applied_connection, NM_CONNECTION_SERIALIZE_WITH_NON_SECRET);
     if (!var_settings)
-        var_settings = g_variant_new_array(G_VARIANT_TYPE("{sa{sv}}"), NULL, 0);
+        var_settings = nm_g_variant_singleton_aLsaLsvII();
 
     g_dbus_method_invocation_return_value(
         invocation,
@@ -13478,12 +13479,13 @@ nm_device_set_ip_config(NMDevice *  self,
                         gboolean    commit,
                         GPtrArray * ip4_dev_route_blacklist)
 {
-    NMDevicePrivate *     priv    = NM_DEVICE_GET_PRIVATE(self);
-    const int             IS_IPv4 = NM_IS_IPv4(addr_family);
-    NMIPConfig *          old_config;
-    gboolean              has_changes = FALSE;
-    gboolean              success     = TRUE;
-    NMSettingsConnection *settings_connection;
+    NMDevicePrivate *      priv    = NM_DEVICE_GET_PRIVATE(self);
+    const int              IS_IPv4 = NM_IS_IPv4(addr_family);
+    NMIPConfig *           old_config;
+    gboolean               has_changes = FALSE;
+    gboolean               success     = TRUE;
+    NMSettingsConnection * settings_connection;
+    NMIPRouteTableSyncMode route_table_sync_mode;
 
     nm_assert_addr_family(addr_family);
     nm_assert(!new_config || nm_ip_config_get_addr_family(new_config) == addr_family);
@@ -13495,11 +13497,18 @@ nm_device_set_ip_config(NMDevice *  self,
                   })));
     nm_assert(IS_IPv4 || !ip4_dev_route_blacklist);
 
+    if (commit && new_config)
+        route_table_sync_mode = _get_route_table_sync_mode_stateful(self, addr_family);
+    else
+        route_table_sync_mode = NM_IP_ROUTE_TABLE_SYNC_MODE_NONE;
+
     _LOGD(LOGD_IPX(IS_IPv4),
-          "ip%c-config: update (commit=%d, new-config=%p)",
+          "ip%c-config: update (commit=%d, new-config=" NM_HASH_OBFUSCATE_PTR_FMT
+          ", route-table-sync-mode=%d)",
           nm_utils_addr_family_to_char(addr_family),
           commit,
-          new_config);
+          NM_HASH_OBFUSCATE_PTR(new_config),
+          (int) route_table_sync_mode);
 
     /* Always commit to nm-platform to update lifetimes */
     if (commit && new_config) {
@@ -13508,7 +13517,7 @@ nm_device_set_ip_config(NMDevice *  self,
         if (IS_IPv4) {
             success = nm_ip4_config_commit(NM_IP4_CONFIG(new_config),
                                            nm_device_get_platform(self),
-                                           _get_route_table_sync_mode_stateful(self, AF_INET));
+                                           route_table_sync_mode);
             nm_platform_ip4_dev_route_blacklist_set(nm_device_get_platform(self),
                                                     nm_ip_config_get_ifindex(new_config),
                                                     ip4_dev_route_blacklist);
@@ -13517,7 +13526,7 @@ nm_device_set_ip_config(NMDevice *  self,
 
             success = nm_ip6_config_commit(NM_IP6_CONFIG(new_config),
                                            nm_device_get_platform(self),
-                                           _get_route_table_sync_mode_stateful(self, AF_INET6),
+                                           route_table_sync_mode,
                                            &temporary_not_available);
 
             if (!_rt6_temporary_not_available_set(self, temporary_not_available))
@@ -13596,7 +13605,7 @@ nm_device_set_ip_config(NMDevice *  self,
                                           NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY,
                                           NM_SETTINGS_CONNECTION_INT_FLAGS_NONE,
                                           NM_SETTINGS_CONNECTION_INT_FLAGS_NONE,
-                                          NM_SETTINGS_CONNECTION_UPDATE_REASON_NONE,
+                                          NM_SETTINGS_CONNECTION_UPDATE_REASON_UPDATE_NON_SECRET,
                                           "update-external",
                                           NULL);
         }
@@ -14007,13 +14016,14 @@ nm_device_is_up(NMDevice *self)
 static gint64
 _get_carrier_wait_ms(NMDevice *self)
 {
-    gs_free char *value = NULL;
-
-    value = nm_config_data_get_device_config(NM_CONFIG_GET_DATA,
-                                             NM_CONFIG_KEYFILE_KEY_DEVICE_CARRIER_WAIT_TIMEOUT,
-                                             self,
-                                             NULL);
-    return _nm_utils_ascii_str_to_int64(value, 10, 0, G_MAXINT32, CARRIER_WAIT_TIME_MS);
+    return nm_config_data_get_device_config_int64(NM_CONFIG_GET_DATA,
+                                                  NM_CONFIG_KEYFILE_KEY_DEVICE_CARRIER_WAIT_TIMEOUT,
+                                                  self,
+                                                  10,
+                                                  0,
+                                                  G_MAXINT32,
+                                                  CARRIER_WAIT_TIME_MS,
+                                                  CARRIER_WAIT_TIME_MS);
 }
 
 gboolean
@@ -14023,6 +14033,7 @@ nm_device_bring_up(NMDevice *self, gboolean block, gboolean *no_firmware)
     gboolean             device_is_up = FALSE;
     NMDeviceCapabilities capabilities;
     int                  ifindex;
+    int                  r;
 
     g_return_val_if_fail(NM_IS_DEVICE(self), FALSE);
 
@@ -14038,7 +14049,9 @@ nm_device_bring_up(NMDevice *self, gboolean block, gboolean *no_firmware)
     if (ifindex <= 0) {
         /* assume success. */
     } else {
-        if (!nm_platform_link_set_up(nm_device_get_platform(self), ifindex, no_firmware))
+        r = nm_platform_link_change_flags(nm_device_get_platform(self), ifindex, IFF_UP, TRUE);
+        NM_SET_OUT(no_firmware, (r == -NME_PL_NO_FIRMWARE));
+        if (r < 0)
             return FALSE;
     }
 
@@ -14125,7 +14138,7 @@ nm_device_take_down(NMDevice *self, gboolean block)
         return;
     }
 
-    if (!nm_platform_link_set_down(nm_device_get_platform(self), ifindex))
+    if (!nm_platform_link_change_flags(nm_device_get_platform(self), ifindex, IFF_UP, FALSE))
         return;
 
     device_is_up = nm_device_is_up(self);
@@ -14855,7 +14868,7 @@ _set_unmanaged_flags(NMDevice *          self,
           flags,
           NM_PRINT_FMT_QUOTED(allow_state_transition,
                               ", reason ",
-                              reason_to_string_a(reason),
+                              nm_device_state_reason_to_str_a(reason),
                               transition_state ? ", transition-state" : "",
                               ""));
 
@@ -15045,20 +15058,6 @@ nm_device_set_unmanaged_by_quitting(NMDevice *self)
 /*****************************************************************************/
 
 void
-nm_device_set_dhcp_anycast_address(NMDevice *self, const char *addr)
-{
-    NMDevicePrivate *priv;
-
-    g_return_if_fail(NM_IS_DEVICE(self));
-    g_return_if_fail(!addr || nm_utils_hwaddr_valid(addr, ETH_ALEN));
-
-    priv = NM_DEVICE_GET_PRIVATE(self);
-
-    g_free(priv->dhcp_anycast_address);
-    priv->dhcp_anycast_address = g_strdup(addr);
-}
-
-void
 nm_device_reapply_settings_immediately(NMDevice *self)
 {
     NMConnection *        applied_connection;
@@ -15730,7 +15729,7 @@ _cancel_activation(NMDevice *self)
     NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
 
     if (priv->fw_call) {
-        nm_firewall_manager_cancel_call(priv->fw_call);
+        nm_firewalld_manager_cancel_call(priv->fw_call);
         nm_assert(!priv->fw_call);
         priv->fw_call  = NULL;
         priv->fw_state = FIREWALL_STATE_INITIALIZED;
@@ -15760,11 +15759,11 @@ _cleanup_generic_pre(NMDevice *self, CleanupType cleanup_type)
 
     if (cleanup_type == CLEANUP_TYPE_DECONFIGURE && priv->fw_state >= FIREWALL_STATE_INITIALIZED
         && priv->fw_mgr && !nm_device_sys_iface_state_is_external(self)) {
-        nm_firewall_manager_remove_from_zone(priv->fw_mgr,
-                                             nm_device_get_ip_iface(self),
-                                             NULL,
-                                             NULL,
-                                             NULL);
+        nm_firewalld_manager_remove_from_zone(priv->fw_mgr,
+                                              nm_device_get_ip_iface(self),
+                                              NULL,
+                                              NULL,
+                                              NULL);
     }
     priv->fw_state = FIREWALL_STATE_UNMANAGED;
     g_clear_object(&priv->fw_mgr);
@@ -15846,7 +15845,7 @@ _cleanup_generic_post(NMDevice *self, CleanupType cleanup_type)
         /* Check if the device was deactivated, and if so, delete_link.
          * Don't call delete_link synchronously because we are currently
          * handling a state change -- which is not reentrant. */
-        delete_on_deactivate_check_and_schedule(self, nm_device_get_ip_ifindex(self));
+        delete_on_deactivate_check_and_schedule(self);
     }
 
     /* ip_iface should be cleared after flushing all routes and addresses, since
@@ -15875,7 +15874,7 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu
     else
         _LOGD(LOGD_DEVICE,
               "deactivating device (reason '%s') [%d]",
-              reason_to_string_a(reason),
+              nm_device_state_reason_to_str_a(reason),
               reason);
 
     /* Save whether or not we tried IPv6 for later */
@@ -15906,9 +15905,12 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu
 
             nm_platform_ip_route_flush(platform, AF_UNSPEC, ifindex);
             nm_platform_ip_address_flush(platform, AF_UNSPEC, ifindex);
-            nm_platform_tfilter_sync(platform, ifindex, NULL);
-            nm_platform_qdisc_sync(platform, ifindex, NULL);
             set_ipv6_token(self, iid, "::");
+
+            if (nm_device_get_applied_setting(self, NM_TYPE_SETTING_TC_CONFIG)) {
+                nm_platform_tfilter_sync(platform, ifindex, NULL);
+                nm_platform_qdisc_sync(platform, ifindex, NULL);
+            }
         }
     }
 
@@ -15927,8 +15929,7 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu
                                            FALSE,
                                            NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED);
 
-    if (priv->lldp_listener)
-        nm_lldp_listener_stop(priv->lldp_listener);
+    lldp_setup(self, NM_TERNARY_FALSE);
 
     nm_device_update_metered(self);
 
@@ -15979,6 +15980,14 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu
 
     _ethtool_state_reset(self);
 
+    if (priv->promisc_reset != NM_OPTION_BOOL_DEFAULT && ifindex > 0) {
+        nm_platform_link_change_flags(nm_device_get_platform(self),
+                                      ifindex,
+                                      IFF_PROMISC,
+                                      !!priv->promisc_reset);
+        priv->promisc_reset = NM_OPTION_BOOL_DEFAULT;
+    }
+
     _cleanup_generic_post(self, cleanup_type);
 }
 
@@ -16093,7 +16102,8 @@ nm_device_spawn_iface_helper(NMDevice *self)
 
             hostname = nm_dhcp_client_get_hostname(priv->dhcp_data_4.client);
             if (hostname) {
-                if (nm_dhcp_client_get_use_fqdn(priv->dhcp_data_4.client))
+                if (NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(priv->dhcp_data_4.client),
+                                 NM_DHCP_CLIENT_FLAGS_USE_FQDN))
                     g_ptr_array_add(argv, g_strdup("--dhcp4-fqdn"));
                 else
                     g_ptr_array_add(argv, g_strdup("--dhcp4-hostname"));
@@ -16360,8 +16370,8 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason,
               "state change: %s -> %s (reason '%s', sys-iface-state: '%s'%s)",
               nm_device_state_to_str(old_state),
               nm_device_state_to_str(state),
-              reason_to_string_a(reason),
-              _sys_iface_state_to_str(priv->sys_iface_state),
+              nm_device_state_reason_to_str_a(reason),
+              nm_device_sys_iface_state_to_str(priv->sys_iface_state),
               priv->firmware_missing ? ", missing firmware" : "");
         return;
     }
@@ -16370,8 +16380,8 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason,
           "state change: %s -> %s (reason '%s', sys-iface-state: '%s')",
           nm_device_state_to_str(old_state),
           nm_device_state_to_str(state),
-          reason_to_string_a(reason),
-          _sys_iface_state_to_str(priv->sys_iface_state));
+          nm_device_state_reason_to_str_a(reason),
+          nm_device_sys_iface_state_to_str(priv->sys_iface_state));
 
     /* in order to prevent triggering any callback caused
      * by the device not having any pending action anymore
@@ -16717,7 +16727,7 @@ queued_state_set(gpointer user_data)
     _LOGD(LOGD_DEVICE,
           "queue-state[%s, reason:%s, id:%u]: %s",
           nm_device_state_to_str(priv->queued_state.state),
-          reason_to_string_a(priv->queued_state.reason),
+          nm_device_state_reason_to_str_a(priv->queued_state.reason),
           priv->queued_state.id,
           "change state");
 
@@ -16729,7 +16739,7 @@ queued_state_set(gpointer user_data)
     new_reason            = priv->queued_state.reason;
 
     nm_device_state_changed(self, new_state, new_reason);
-    nm_device_remove_pending_action(self, queued_state_to_string(new_state), TRUE);
+    nm_device_remove_pending_action(self, nm_device_state_queued_state_to_str(new_state), TRUE);
 
     return G_SOURCE_REMOVE;
 }
@@ -16747,12 +16757,12 @@ nm_device_queue_state(NMDevice *self, NMDeviceState state, NMDeviceStateReason r
         _LOGD(LOGD_DEVICE,
               "queue-state[%s, reason:%s, id:%u]: %s%s%s%s",
               nm_device_state_to_str(priv->queued_state.state),
-              reason_to_string_a(priv->queued_state.reason),
+              nm_device_state_reason_to_str_a(priv->queued_state.reason),
               priv->queued_state.id,
               "ignore queuing same state change",
               NM_PRINT_FMT_QUOTED(priv->queued_state.reason != reason,
                                   " (reason differs: ",
-                                  reason_to_string_a(reason),
+                                  nm_device_state_reason_to_str_a(reason),
                                   ")",
                                   ""));
         return;
@@ -16760,20 +16770,21 @@ nm_device_queue_state(NMDevice *self, NMDeviceState state, NMDeviceStateReason r
 
     /* Add pending action for the new state before clearing the queued states, so
      * that we don't accidentally pop all pending states and reach 'startup complete'  */
-    nm_device_add_pending_action(self, queued_state_to_string(state), TRUE);
+    nm_device_add_pending_action(self, nm_device_state_queued_state_to_str(state), TRUE);
 
     /* We should only ever have one delayed state transition at a time */
     if (priv->queued_state.id) {
         _LOGW(LOGD_DEVICE,
               "queue-state[%s, reason:%s, id:%u]: %s",
               nm_device_state_to_str(priv->queued_state.state),
-              reason_to_string_a(priv->queued_state.reason),
+              nm_device_state_reason_to_str_a(priv->queued_state.reason),
               priv->queued_state.id,
               "replace previously queued state change");
         nm_clear_g_source(&priv->queued_state.id);
-        nm_device_remove_pending_action(self,
-                                        queued_state_to_string(priv->queued_state.state),
-                                        TRUE);
+        nm_device_remove_pending_action(
+            self,
+            nm_device_state_queued_state_to_str(priv->queued_state.state),
+            TRUE);
     }
 
     priv->queued_state.state  = state;
@@ -16783,7 +16794,7 @@ nm_device_queue_state(NMDevice *self, NMDeviceState state, NMDeviceStateReason r
     _LOGD(LOGD_DEVICE,
           "queue-state[%s, reason:%s, id:%u]: %s",
           nm_device_state_to_str(state),
-          reason_to_string_a(reason),
+          nm_device_state_reason_to_str_a(reason),
           priv->queued_state.id,
           "queue state change");
 }
@@ -16799,11 +16810,13 @@ queued_state_clear(NMDevice *self)
     _LOGD(LOGD_DEVICE,
           "queue-state[%s, reason:%s, id:%u]: %s",
           nm_device_state_to_str(priv->queued_state.state),
-          reason_to_string_a(priv->queued_state.reason),
+          nm_device_state_reason_to_str_a(priv->queued_state.reason),
           priv->queued_state.id,
           "clear queued state change");
     nm_clear_g_source(&priv->queued_state.id);
-    nm_device_remove_pending_action(self, queued_state_to_string(priv->queued_state.state), TRUE);
+    nm_device_remove_pending_action(self,
+                                    nm_device_state_queued_state_to_str(priv->queued_state.state),
+                                    TRUE);
 }
 
 NMDeviceState
@@ -16821,7 +16834,7 @@ const char *
 nm_device_get_hw_address(NMDevice *self)
 {
     NMDevicePrivate *priv;
-    char             buf[NM_UTILS_HWADDR_LEN_MAX];
+    char             buf[_NM_UTILS_HWADDR_LEN_MAX];
     gsize            l;
 
     g_return_val_if_fail(NM_IS_DEVICE(self), NULL);
@@ -16915,7 +16928,7 @@ void
 nm_device_update_permanent_hw_address(NMDevice *self, gboolean force_freeze)
 {
     NMDevicePrivate *              priv = NM_DEVICE_GET_PRIVATE(self);
-    guint8                         buf[NM_UTILS_HWADDR_LEN_MAX];
+    guint8                         buf[_NM_UTILS_HWADDR_LEN_MAX];
     size_t                         len = 0;
     gboolean                       success_read;
     int                            ifindex;
@@ -17033,7 +17046,7 @@ _hw_addr_set(NMDevice *        self,
     NMDevicePrivate *priv;
     gboolean         success = FALSE;
     int              r;
-    guint8           addr_bytes[NM_UTILS_HWADDR_LEN_MAX];
+    guint8           addr_bytes[_NM_UTILS_HWADDR_LEN_MAX];
     gsize            addr_len;
     gboolean         was_taken_down = FALSE;
     gboolean         retry_down;
@@ -17234,14 +17247,13 @@ _hw_addr_get_cloned(NMDevice *    self,
                     gboolean *    preserve,
                     char **       hwaddr,
                     HwAddrType *  hwaddr_type,
-                    char **       hwaddr_detail,
+                    const char ** hwaddr_detail,
                     GError **     error)
 {
     NMDevicePrivate *priv;
-    gs_free char *   addr_setting_free             = NULL;
-    gs_free char *   hw_addr_generated             = NULL;
-    gs_free char *   generate_mac_address_mask_tmp = NULL;
-    const char *     addr, *addr_setting;
+    gs_free char *   hw_addr_generated = NULL;
+    const char *     addr;
+    const char *     addr_setting;
     char *           addr_out;
     HwAddrType       type_out;
 
@@ -17254,15 +17266,16 @@ _hw_addr_get_cloned(NMDevice *    self,
     if (!connection)
         g_return_val_if_reached(FALSE);
 
-    addr = addr_setting =
-        _prop_get_x_cloned_mac_address(self, connection, is_wifi, &addr_setting_free);
+    addr_setting = _prop_get_x_cloned_mac_address(self, connection, is_wifi);
+
+    addr = addr_setting;
 
     if (nm_streq(addr, NM_CLONED_MAC_PRESERVE)) {
         /* "preserve" means to reset the initial MAC address. */
         NM_SET_OUT(preserve, TRUE);
         NM_SET_OUT(hwaddr, NULL);
         NM_SET_OUT(hwaddr_type, HW_ADDR_TYPE_UNSET);
-        NM_SET_OUT(hwaddr_detail, g_steal_pointer(&addr_setting_free) ?: g_strdup(addr_setting));
+        NM_SET_OUT(hwaddr_detail, addr_setting);
         return TRUE;
     }
 
@@ -17275,8 +17288,7 @@ _hw_addr_get_cloned(NMDevice *    self,
             NM_SET_OUT(preserve, TRUE);
             NM_SET_OUT(hwaddr, NULL);
             NM_SET_OUT(hwaddr_type, HW_ADDR_TYPE_UNSET);
-            NM_SET_OUT(hwaddr_detail,
-                       g_steal_pointer(&addr_setting_free) ?: g_strdup(addr_setting));
+            NM_SET_OUT(hwaddr_detail, addr_setting);
             return TRUE;
         } else if (!addr) {
             g_set_error_literal(error,
@@ -17296,10 +17308,7 @@ _hw_addr_get_cloned(NMDevice *    self,
         }
         hw_addr_generated = nm_utils_hw_addr_gen_random_eth(
             nm_device_get_initial_hw_address(self),
-            _prop_get_x_generate_mac_address_mask(self,
-                                                  connection,
-                                                  is_wifi,
-                                                  &generate_mac_address_mask_tmp));
+            _prop_get_x_generate_mac_address_mask(self, connection, is_wifi));
         if (!hw_addr_generated) {
             g_set_error(error,
                         NM_DEVICE_ERROR,
@@ -17327,10 +17336,7 @@ _hw_addr_get_cloned(NMDevice *    self,
             stable_id,
             nm_device_get_ip_iface(self),
             nm_device_get_initial_hw_address(self),
-            _prop_get_x_generate_mac_address_mask(self,
-                                                  connection,
-                                                  is_wifi,
-                                                  &generate_mac_address_mask_tmp));
+            _prop_get_x_generate_mac_address_mask(self, connection, is_wifi));
         if (!hw_addr_generated) {
             g_set_error(error,
                         NM_DEVICE_ERROR,
@@ -17354,7 +17360,7 @@ _hw_addr_get_cloned(NMDevice *    self,
     NM_SET_OUT(preserve, FALSE);
     NM_SET_OUT(hwaddr, addr_out);
     NM_SET_OUT(hwaddr_type, type_out);
-    NM_SET_OUT(hwaddr_detail, g_steal_pointer(&addr_setting_free) ?: g_strdup(addr_setting));
+    NM_SET_OUT(hwaddr_detail, addr_setting);
     return TRUE;
 out_no_action:
     NM_SET_OUT(preserve, FALSE);
@@ -17384,7 +17390,7 @@ nm_device_hw_addr_set_cloned(NMDevice *self, NMConnection *connection, gboolean
     NMDevicePrivate *priv;
     gboolean         preserve   = FALSE;
     gs_free char *   hwaddr     = NULL;
-    gs_free char *   detail     = NULL;
+    const char *     detail     = NULL;
     HwAddrType       type       = HW_ADDR_TYPE_UNSET;
     gs_free_error GError *error = NULL;
 
@@ -17624,23 +17630,38 @@ hostname_dns_lookup_callback(GObject *source, GAsyncResult *result, gpointer use
 {
     HostnameResolver *resolver;
     NMDevice *        self;
-    gs_free char *    hostname  = NULL;
     gs_free char *    addr_str  = NULL;
+    gs_free char *    output    = NULL;
     gs_free_error GError *error = NULL;
 
-    hostname = g_resolver_lookup_by_address_finish(G_RESOLVER(source), result, &error);
+    output = nm_device_resolve_address_finish(result, &error);
     if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
         return;
 
-    resolver           = user_data;
-    self               = resolver->device;
-    resolver->state    = RESOLVER_DONE;
-    resolver->hostname = g_strdup(hostname);
+    resolver        = user_data;
+    self            = resolver->device;
+    resolver->state = RESOLVER_DONE;
 
-    _LOGD(LOGD_DNS,
-          "hostname-from-dns: lookup done for %s, result %s%s%s",
-          (addr_str = g_inet_address_to_string(resolver->address)),
-          NM_PRINT_FMT_QUOTE_STRING(hostname));
+    if (error) {
+        _LOGD(LOGD_DNS,
+              "hostname-from-dns: lookup error for %s: %s",
+              (addr_str = g_inet_address_to_string(resolver->address)),
+              error->message);
+    } else {
+        gboolean valid;
+
+        resolver->hostname = g_steal_pointer(&output);
+        valid              = nm_hostname_manager_validate_hostname(resolver->hostname);
+
+        _LOGD(LOGD_DNS,
+              "hostname-from-dns: lookup done for %s, result %s%s%s%s",
+              (addr_str = g_inet_address_to_string(resolver->address)),
+              NM_PRINT_FMT_QUOTE_STRING(resolver->hostname),
+              valid ? "" : " (invalid)");
+
+        if (!valid)
+            g_clear_pointer(&resolver->hostname, g_free);
+    }
 
     nm_clear_g_cancellable(&resolver->cancellable);
     g_signal_emit(self, signals[DNS_LOOKUP_DONE], 0);
@@ -17738,7 +17759,6 @@ nm_device_get_hostname_from_dns_lookup(NMDevice *self, int addr_family, gboolean
     if (!resolver) {
         resolver  = g_slice_new(HostnameResolver);
         *resolver = (HostnameResolver){
-            .resolver    = g_resolver_get_default(),
             .device      = self,
             .addr_family = addr_family,
             .state       = RESOLVER_WAIT_ADDRESS,
@@ -17746,13 +17766,36 @@ nm_device_get_hostname_from_dns_lookup(NMDevice *self, int addr_family, gboolean
         priv->hostname_resolver_x[IS_IPv4] = resolver;
     }
 
-    /* Determine the first address of the interface and
-     * whether it changed from the previous lookup */
+    /* Determine the most suitable address of the interface
+     * and whether it changed from the previous lookup */
     ip_config = priv->ip_config_x[IS_IPv4];
     if (ip_config) {
-        const NMPlatformIPAddress *addr;
+        const NMPlatformIPAddress *addr = NULL;
+
+        if (IS_IPv4) {
+            addr = nm_ip_config_get_first_address(ip_config);
+        } else {
+            /* For IPv6 prefer, in order:
+             * - !link-local, !deprecated
+             * - !link-local, deprecated
+             * - link-local
+             */
+            addr = nm_ip_config_find_first_address(ip_config,
+                                                   NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL
+                                                       | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL);
+            if (!addr) {
+                addr = nm_ip_config_find_first_address(
+                    ip_config,
+                    NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL
+                        | NM_PLATFORM_MATCH_WITH_ADDRSTATE_DEPRECATED);
+            }
+            if (!addr) {
+                addr = nm_ip_config_find_first_address(ip_config,
+                                                       NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL
+                                                           | NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY);
+            }
+        }
 
-        addr = nm_ip_config_get_first_address(ip_config);
         if (addr) {
             new_address = g_inet_address_new_from_bytes(addr->address_ptr,
                                                         IS_IPv4 ? G_SOCKET_FAMILY_IPV4
@@ -17788,20 +17831,15 @@ nm_device_get_hostname_from_dns_lookup(NMDevice *self, int addr_family, gboolean
     }
 
     if (address_changed && new_address) {
-        gs_free char *str = NULL;
-
-        _LOGT(LOGD_DNS,
-              "hostname-from-dns: starting lookup for address %s",
-              (str = g_inet_address_to_string(new_address)));
-
         resolver->state       = RESOLVER_IN_PROGRESS;
         resolver->cancellable = g_cancellable_new();
         resolver->address     = g_steal_pointer(&new_address);
-        g_resolver_lookup_by_address_async(resolver->resolver,
-                                           resolver->address,
-                                           resolver->cancellable,
-                                           hostname_dns_lookup_callback,
-                                           resolver);
+
+        nm_device_resolve_address(addr_family,
+                                  g_inet_address_to_bytes(resolver->address),
+                                  resolver->cancellable,
+                                  hostname_dns_lookup_callback,
+                                  resolver);
         nm_clear_g_source(&resolver->timeout_id);
     }
 
@@ -17851,7 +17889,6 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
 {
     NMDevice *       self = NM_DEVICE(object);
     NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
-    GVariantBuilder  array_builder;
 
     switch (prop_id) {
     case PROP_UDI:
@@ -18002,12 +18039,10 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
         g_value_set_uint(value, priv->metered);
         break;
     case PROP_LLDP_NEIGHBORS:
-        if (priv->lldp_listener)
-            g_value_set_variant(value, nm_lldp_listener_get_neighbors(priv->lldp_listener));
-        else {
-            g_variant_builder_init(&array_builder, G_VARIANT_TYPE("aa{sv}"));
-            g_value_take_variant(value, g_variant_builder_end(&array_builder));
-        }
+        g_value_set_variant(value,
+                            priv->lldp_listener
+                                ? nm_lldp_listener_get_neighbors(priv->lldp_listener)
+                                : nm_g_variant_singleton_aaLsvI());
         break;
     case PROP_REAL:
         g_value_set_boolean(value, nm_device_is_real(self));
@@ -18187,6 +18222,8 @@ nm_device_init(NMDevice *self)
 
     priv->v4_commit_first_time = TRUE;
     priv->v6_commit_first_time = TRUE;
+
+    priv->promisc_reset = NM_OPTION_BOOL_DEFAULT;
 }
 
 static GObject *
@@ -18216,7 +18253,7 @@ constructor(GType type, guint n_construct_params, GObjectConstructParam *constru
     }
 
     if (priv->hw_addr_perm) {
-        guint8 buf[NM_UTILS_HWADDR_LEN_MAX];
+        guint8 buf[_NM_UTILS_HWADDR_LEN_MAX];
         gsize  l;
 
         if (!_nm_utils_hwaddr_aton(priv->hw_addr_perm, buf, sizeof(buf), &l)) {
@@ -18364,13 +18401,7 @@ dispose(GObject *object)
     nm_clear_g_source(&priv->device_link_changed_id);
     nm_clear_g_source(&priv->device_ip_link_changed_id);
 
-    if (priv->lldp_listener) {
-        g_signal_handlers_disconnect_by_func(priv->lldp_listener,
-                                             G_CALLBACK(lldp_neighbors_changed),
-                                             self);
-        nm_lldp_listener_stop(priv->lldp_listener);
-        g_clear_object(&priv->lldp_listener);
-    }
+    lldp_setup(self, FALSE);
 
     nm_clear_g_source(&priv->concheck_x[0].p_cur_id);
     nm_clear_g_source(&priv->concheck_x[1].p_cur_id);
@@ -18413,7 +18444,6 @@ finalize(GObject *object)
     g_free(priv->driver_version);
     g_free(priv->firmware_version);
     g_free(priv->type_desc);
-    g_free(priv->dhcp_anycast_address);
     g_free(priv->current_stable_id);
 
     g_hash_table_unref(priv->ip6_saved_properties);
@@ -18468,75 +18498,69 @@ static const NMDBusInterfaceInfoExtended interface_info_device = {
                                                 .handle = impl_device_delete, ), ),
         .signals    = NM_DEFINE_GDBUS_SIGNAL_INFOS(&signal_info_state_changed, ),
         .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS(
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Udi", "s", NM_DEVICE_UDI),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Path", "s", NM_DEVICE_PATH),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Interface", "s", NM_DEVICE_IFACE),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("IpInterface",
-                                                             "s",
-                                                             NM_DEVICE_IP_IFACE),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Driver", "s", NM_DEVICE_DRIVER),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("DriverVersion",
-                                                             "s",
-                                                             NM_DEVICE_DRIVER_VERSION),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("FirmwareVersion",
-                                                             "s",
-                                                             NM_DEVICE_FIRMWARE_VERSION),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Capabilities",
-                                                             "u",
-                                                             NM_DEVICE_CAPABILITIES),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Ip4Address",
-                                                             "u",
-                                                             NM_DEVICE_IP4_ADDRESS),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("State", "u", NM_DEVICE_STATE),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("StateReason",
-                                                             "(uu)",
-                                                             NM_DEVICE_STATE_REASON),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("ActiveConnection",
-                                                             "o",
-                                                             NM_DEVICE_ACTIVE_CONNECTION),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Ip4Config",
-                                                             "o",
-                                                             NM_DEVICE_IP4_CONFIG),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Dhcp4Config",
-                                                             "o",
-                                                             NM_DEVICE_DHCP4_CONFIG),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Ip6Config",
-                                                             "o",
-                                                             NM_DEVICE_IP6_CONFIG),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Dhcp6Config",
-                                                             "o",
-                                                             NM_DEVICE_DHCP6_CONFIG),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE_L("Managed",
-                                                                 "b",
-                                                                 NM_DEVICE_MANAGED,
-                                                                 NM_AUTH_PERMISSION_NETWORK_CONTROL,
-                                                                 NM_AUDIT_OP_DEVICE_MANAGED),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE_L("Autoconnect",
-                                                                 "b",
-                                                                 NM_DEVICE_AUTOCONNECT,
-                                                                 NM_AUTH_PERMISSION_NETWORK_CONTROL,
-                                                                 NM_AUDIT_OP_DEVICE_AUTOCONNECT),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("FirmwareMissing",
-                                                             "b",
-                                                             NM_DEVICE_FIRMWARE_MISSING),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("NmPluginMissing",
-                                                             "b",
-                                                             NM_DEVICE_NM_PLUGIN_MISSING),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("DeviceType",
-                                                             "u",
-                                                             NM_DEVICE_DEVICE_TYPE),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("AvailableConnections",
-                                                             "ao",
-                                                             NM_DEVICE_AVAILABLE_CONNECTIONS),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("PhysicalPortId",
-                                                             "s",
-                                                             NM_DEVICE_PHYSICAL_PORT_ID),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Mtu", "u", NM_DEVICE_MTU),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Metered", "u", NM_DEVICE_METERED),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("LldpNeighbors",
-                                                             "aa{sv}",
-                                                             NM_DEVICE_LLDP_NEIGHBORS),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Real", "b", NM_DEVICE_REAL),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Udi", "s", NM_DEVICE_UDI),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Path", "s", NM_DEVICE_PATH),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Interface", "s", NM_DEVICE_IFACE),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("IpInterface", "s", NM_DEVICE_IP_IFACE),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Driver", "s", NM_DEVICE_DRIVER),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("DriverVersion",
+                                                           "s",
+                                                           NM_DEVICE_DRIVER_VERSION),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("FirmwareVersion",
+                                                           "s",
+                                                           NM_DEVICE_FIRMWARE_VERSION),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Capabilities",
+                                                           "u",
+                                                           NM_DEVICE_CAPABILITIES),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Ip4Address",
+                                                           "u",
+                                                           NM_DEVICE_IP4_ADDRESS),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("State", "u", NM_DEVICE_STATE),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("StateReason",
+                                                           "(uu)",
+                                                           NM_DEVICE_STATE_REASON),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("ActiveConnection",
+                                                           "o",
+                                                           NM_DEVICE_ACTIVE_CONNECTION),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Ip4Config", "o", NM_DEVICE_IP4_CONFIG),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Dhcp4Config",
+                                                           "o",
+                                                           NM_DEVICE_DHCP4_CONFIG),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Ip6Config", "o", NM_DEVICE_IP6_CONFIG),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Dhcp6Config",
+                                                           "o",
+                                                           NM_DEVICE_DHCP6_CONFIG),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE("Managed",
+                                                               "b",
+                                                               NM_DEVICE_MANAGED,
+                                                               NM_AUTH_PERMISSION_NETWORK_CONTROL,
+                                                               NM_AUDIT_OP_DEVICE_MANAGED),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE("Autoconnect",
+                                                               "b",
+                                                               NM_DEVICE_AUTOCONNECT,
+                                                               NM_AUTH_PERMISSION_NETWORK_CONTROL,
+                                                               NM_AUDIT_OP_DEVICE_AUTOCONNECT),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("FirmwareMissing",
+                                                           "b",
+                                                           NM_DEVICE_FIRMWARE_MISSING),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("NmPluginMissing",
+                                                           "b",
+                                                           NM_DEVICE_NM_PLUGIN_MISSING),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("DeviceType",
+                                                           "u",
+                                                           NM_DEVICE_DEVICE_TYPE),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("AvailableConnections",
+                                                           "ao",
+                                                           NM_DEVICE_AVAILABLE_CONNECTIONS),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("PhysicalPortId",
+                                                           "s",
+                                                           NM_DEVICE_PHYSICAL_PORT_ID),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Mtu", "u", NM_DEVICE_MTU),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Metered", "u", NM_DEVICE_METERED),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("LldpNeighbors",
+                                                           "aa{sv}",
+                                                           NM_DEVICE_LLDP_NEIGHBORS),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Real", "b", NM_DEVICE_REAL),
             NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Ip4Connectivity",
                                                            "u",
                                                            NM_DEVICE_IP4_CONNECTIVITY),
@@ -18551,10 +18575,9 @@ static const NMDBusInterfaceInfoExtended interface_info_device = {
                                                            NM_DEVICE_HW_ADDRESS), ), ),
 };
 
-const NMDBusInterfaceInfoExtended nm_interface_info_device_statistics = {
+static const NMDBusInterfaceInfoExtended interface_info_device_statistics = {
     .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT(
         NM_DBUS_INTERFACE_DEVICE_STATISTICS,
-        .signals    = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ),
         .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS(
             NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE(
                 "RefreshRateMs",
@@ -18580,7 +18603,7 @@ nm_device_class_init(NMDeviceClass *klass)
 
     dbus_object_class->export_path = NM_DBUS_EXPORT_PATH_NUMBERED(NM_DBUS_PATH "/Devices");
     dbus_object_class->interface_infos =
-        NM_DBUS_INTERFACE_INFOS(&interface_info_device, &nm_interface_info_device_statistics);
+        NM_DBUS_INTERFACE_INFOS(&interface_info_device, &interface_info_device_statistics);
 
     object_class->dispose      = dispose;
     object_class->finalize     = finalize;