about summary refs log tree commit diff
path: root/src/libnm-client-impl
diff options
context:
space:
mode:
Diffstat (limited to 'src/libnm-client-impl')
-rw-r--r--src/libnm-client-impl/libnm.ver42
-rw-r--r--src/libnm-client-impl/meson.build1
-rw-r--r--src/libnm-client-impl/nm-active-connection.c4
-rw-r--r--src/libnm-client-impl/nm-client.c17
-rw-r--r--src/libnm-client-impl/nm-device-ipvlan.c233
-rw-r--r--src/libnm-client-impl/nm-device.c7
-rw-r--r--src/libnm-client-impl/nm-ip-config.c21
-rw-r--r--src/libnm-client-impl/nm-libnm-utils.c1
-rw-r--r--src/libnm-client-impl/nm-libnm-utils.h23
-rw-r--r--src/libnm-client-impl/nm-secret-agent-old.c2
-rw-r--r--src/libnm-client-impl/nm-vpn-service-plugin.c32
-rw-r--r--src/libnm-client-impl/tests/test-libnm.c15
-rw-r--r--src/libnm-client-impl/tests/test-nm-client.c14
-rw-r--r--src/libnm-client-impl/tests/test-secret-agent.c2
14 files changed, 367 insertions, 47 deletions
diff --git a/src/libnm-client-impl/libnm.ver b/src/libnm-client-impl/libnm.ver
index 23e6042f..faa872d7 100644
--- a/src/libnm-client-impl/libnm.ver
+++ b/src/libnm-client-impl/libnm.ver
@@ -2007,4 +2007,44 @@ libnm_1_50_0 {
 global:
 	nm_setting_wireless_channel_width_get_type;
 	nm_setting_wireless_get_channel_width;
-} libnm_1_48_0;
\ No newline at end of file
+} libnm_1_48_0;
+
+libnm_1_52_0 {
+global:
+	nm_device_ipvlan_get_mode;
+	nm_device_ipvlan_get_parent;
+	nm_device_ipvlan_get_private;
+	nm_device_ipvlan_get_type;
+	nm_device_ipvlan_get_vepa;
+	nm_setting_ip4_config_get_dhcp_ipv6_only_preferred;
+	nm_setting_ip4_dhcp_ipv6_only_preferred_get_type;
+	nm_setting_ip_config_get_routed_dns;
+	nm_setting_ip_config_get_shared_dhcp_range;
+	nm_setting_ip_config_get_shared_dhcp_lease_time;
+	nm_setting_ip_config_routed_dns_get_type;
+	nm_setting_ipvlan_get_mode;
+	nm_setting_ipvlan_get_parent;
+	nm_setting_gsm_get_initial_eps_password;
+	nm_setting_gsm_get_initial_eps_username;
+	nm_setting_gsm_get_initial_eps_noauth;
+	nm_setting_gsm_get_initial_eps_refuse_pap;
+	nm_setting_gsm_get_initial_eps_refuse_chap;
+	nm_setting_gsm_get_initial_eps_refuse_eap;
+	nm_setting_gsm_get_initial_eps_refuse_mschap;
+	nm_setting_gsm_get_initial_eps_refuse_mschapv2;
+	nm_setting_ipvlan_get_private;
+	nm_setting_ipvlan_get_type;
+	nm_setting_ipvlan_get_vepa;
+	nm_setting_ipvlan_mode_get_type;
+	nm_setting_ipvlan_new;
+	nm_setting_ip_config_get_dhcp_send_hostname_v2;
+	nm_setting_connection_get_ip_ping_address;
+	nm_setting_connection_get_ip_ping_timeout;
+	nm_setting_connection_add_ip_ping_address;
+	nm_setting_connection_remove_ip_ping_address;
+	nm_setting_connection_clear_ip_ping_addresses;
+	nm_setting_connection_remove_ip_ping_address_by_value;
+	nm_setting_connection_get_ip_ping_addresses_require_all;
+	nm_setting_ethtool_fec_mode_get_type;
+	nm_ethtool_optname_is_fec;
+} libnm_1_50_0;
diff --git a/src/libnm-client-impl/meson.build b/src/libnm-client-impl/meson.build
index 3dd2338a..e50e8fbd 100644
--- a/src/libnm-client-impl/meson.build
+++ b/src/libnm-client-impl/meson.build
@@ -20,6 +20,7 @@ libnm_client_impl_sources = files(
   'nm-device-hsr.c',
   'nm-device-infiniband.c',
   'nm-device-ip-tunnel.c',
+  'nm-device-ipvlan.c',
   'nm-device-loopback.c',
   'nm-device-macsec.c',
   'nm-device-macvlan.c',
diff --git a/src/libnm-client-impl/nm-active-connection.c b/src/libnm-client-impl/nm-active-connection.c
index 0d186361..9008256a 100644
--- a/src/libnm-client-impl/nm-active-connection.c
+++ b/src/libnm-client-impl/nm-active-connection.c
@@ -624,7 +624,7 @@ const NMLDBusMetaIface _nml_dbus_meta_iface_nm_connection_active = NML_DBUS_META
                                         PROP_CONTROLLER,
                                         "o",
                                         active_connection_update_prop_controller,
-                                        .extra.property_vtable_o = &((const NMLDBusPropertVTableO){
+                                        .extra.property_vtable_o = &((const NMLDBusPropertVTableO) {
                                             .get_o_type_fcn = (nm_device_get_type)})),
         NML_DBUS_META_PROPERTY_INIT_B("Default",
                                       PROP_DEFAULT,
@@ -664,7 +664,7 @@ const NMLDBusMetaIface _nml_dbus_meta_iface_nm_connection_active = NML_DBUS_META
                                         PROP_MASTER,
                                         "o",
                                         active_connection_update_prop_controller,
-                                        .extra.property_vtable_o = &((const NMLDBusPropertVTableO){
+                                        .extra.property_vtable_o = &((const NMLDBusPropertVTableO) {
                                             .get_o_type_fcn = (nm_device_get_type)})),
         NML_DBUS_META_PROPERTY_INIT_O("SpecificObject",
                                       PROP_SPECIFIC_OBJECT_PATH,
diff --git a/src/libnm-client-impl/nm-client.c b/src/libnm-client-impl/nm-client.c
index 6e722c5c..fc30cd06 100644
--- a/src/libnm-client-impl/nm-client.c
+++ b/src/libnm-client-impl/nm-client.c
@@ -32,6 +32,7 @@
 #include "nm-device-hsr.h"
 #include "nm-device-infiniband.h"
 #include "nm-device-ip-tunnel.h"
+#include "nm-device-ipvlan.h"
 #include "nm-device-loopback.h"
 #include "nm-device-macsec.h"
 #include "nm-device-macvlan.h"
@@ -418,7 +419,7 @@ nml_init_data_new_sync(GCancellable *cancellable, GMainLoop *main_loop, GError *
     NMLInitData *init_data;
 
     init_data  = g_slice_new(NMLInitData);
-    *init_data = (NMLInitData){
+    *init_data = (NMLInitData) {
         .cancellable = nm_g_object_ref(cancellable),
         .is_sync     = TRUE,
         .data.sync =
@@ -436,7 +437,7 @@ nml_init_data_new_async(GCancellable *cancellable, GTask *task_take)
     NMLInitData *init_data;
 
     init_data  = g_slice_new(NMLInitData);
-    *init_data = (NMLInitData){
+    *init_data = (NMLInitData) {
         .cancellable = nm_g_object_ref(cancellable),
         .is_sync     = FALSE,
         .data.async =
@@ -1102,7 +1103,7 @@ nml_dbus_object_new(NMRefString *dbus_path_take)
     nm_assert(NM_IS_REF_STRING(dbus_path_take));
 
     dbobj  = g_slice_new(NMLDBusObject);
-    *dbobj = (NMLDBusObject){
+    *dbobj = (NMLDBusObject) {
         .dbus_path        = g_steal_pointer(&dbus_path_take),
         .ref_count        = 1,
         .dbus_objects_lst = C_LIST_INIT(dbobj->dbus_objects_lst),
@@ -1208,7 +1209,7 @@ nml_dbus_object_iface_data_get(NMLDBusObject *dbobj,
         G_STRUCT_OFFSET(NMLDBusObjIfaceData, prop_datas)
         + (meta_iface ? (sizeof(NMLDBusObjPropData) * meta_iface->n_dbus_properties) : 0u));
     if (meta_iface) {
-        *db_iface_data = (NMLDBusObjIfaceData){
+        *db_iface_data = (NMLDBusObjIfaceData) {
             .dbus_iface.meta         = meta_iface,
             .dbus_iface_is_wellknown = TRUE,
             .changed_prop_lst_head   = C_LIST_INIT(db_iface_data->changed_prop_lst_head),
@@ -1216,7 +1217,7 @@ nml_dbus_object_iface_data_get(NMLDBusObject *dbobj,
         };
         db_prop_data = &db_iface_data->prop_datas[0];
         for (i = 0; i < meta_iface->n_dbus_properties; i++, db_prop_data++) {
-            *db_prop_data = (NMLDBusObjPropData){
+            *db_prop_data = (NMLDBusObjPropData) {
                 .prop_data_value  = NULL,
                 .changed_prop_lst = C_LIST_INIT(db_prop_data->changed_prop_lst),
             };
@@ -3911,7 +3912,7 @@ _request_wait_start(GTask      *task_take,
     }
 
     request_data  = g_slice_new(RequestWaitData);
-    *request_data = (RequestWaitData){
+    *request_data = (RequestWaitData) {
         .task           = g_steal_pointer(&task),
         .op_name        = op_name,
         .gtype          = gtype,
@@ -7076,7 +7077,7 @@ _init_release_all(NMClient *self)
 
     nm_assert(c_list_is_empty(&priv->obj_changed_lst_head));
 
-    dbus_objects_lst_heads = ((CList *[]){
+    dbus_objects_lst_heads = ((CList *[]) {
         &priv->dbus_objects_lst_head_on_dbus,
         &priv->dbus_objects_lst_head_with_nmobj_not_ready,
         &priv->dbus_objects_lst_head_with_nmobj_ready,
@@ -9148,7 +9149,7 @@ nm_client_wait_shutdown(NMClient           *client,
     }
 
     data  = g_slice_new(WaitShutdownData);
-    *data = (WaitShutdownData){
+    *data = (WaitShutdownData) {
         .cancellable        = nm_g_object_ref(cancellable),
         .task               = g_object_ref(task),
         .result             = -1,
diff --git a/src/libnm-client-impl/nm-device-ipvlan.c b/src/libnm-client-impl/nm-device-ipvlan.c
new file mode 100644
index 00000000..85d799c2
--- /dev/null
+++ b/src/libnm-client-impl/nm-device-ipvlan.c
@@ -0,0 +1,233 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2024 Red Hat, Inc.
+ */
+
+#include "libnm-client-impl/nm-default-libnm.h"
+
+#include "nm-device-ipvlan.h"
+
+#include "nm-setting-connection.h"
+#include "nm-setting-ipvlan.h"
+#include "nm-utils.h"
+#include "nm-object-private.h"
+
+/*****************************************************************************/
+
+NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_PARENT, PROP_MODE, PROP_PRIVATE, PROP_VEPA, );
+
+typedef struct {
+    NMLDBusPropertyO parent;
+    char            *mode;
+    bool             private_flag;
+    bool             vepa;
+} NMDeviceIpvlanPrivate;
+
+struct _NMDeviceIpvlan {
+    NMDevice              parent;
+    NMDeviceIpvlanPrivate _priv;
+};
+
+struct _NMDeviceIpvlanClass {
+    NMDeviceClass parent;
+};
+
+G_DEFINE_TYPE(NMDeviceIpvlan, nm_device_ipvlan, NM_TYPE_DEVICE)
+
+#define NM_DEVICE_IPVLAN_GET_PRIVATE(self) \
+    _NM_GET_PRIVATE(self, NMDeviceIpvlan, NM_IS_DEVICE_IPVLAN, NMObject, NMDevice)
+
+/*****************************************************************************/
+
+/**
+ * nm_device_ipvlan_get_parent:
+ * @device: a #NMDeviceIpvlan
+ *
+ * Returns: (transfer none): the device's parent device
+ *
+ * Since: 1.52
+ **/
+NMDevice *
+nm_device_ipvlan_get_parent(NMDeviceIpvlan *device)
+{
+    g_return_val_if_fail(NM_IS_DEVICE_IPVLAN(device), FALSE);
+
+    return nml_dbus_property_o_get_obj(&NM_DEVICE_IPVLAN_GET_PRIVATE(device)->parent);
+}
+
+/**
+ * nm_device_ipvlan_get_mode:
+ * @device: a #NMDeviceIpvlan
+ *
+ * Gets the IPVLAN mode of the device.
+ *
+ * Returns: the IPVLAN mode. This is the internal string used by the
+ * device, and must not be modified.
+ *
+ * Since: 1.52
+ **/
+const char *
+nm_device_ipvlan_get_mode(NMDeviceIpvlan *device)
+{
+    g_return_val_if_fail(NM_IS_DEVICE_IPVLAN(device), NULL);
+
+    return _nml_coerce_property_str_not_empty(NM_DEVICE_IPVLAN_GET_PRIVATE(device)->mode);
+}
+
+/**
+ * nm_device_ipvlan_get_private
+ * @device: a #NMDeviceIpvlan
+ *
+ * Gets the private flag of the device.
+ *
+ * Returns: the private flag of the device.
+ *
+ * Since: 1.52
+ **/
+gboolean
+nm_device_ipvlan_get_private(NMDeviceIpvlan *device)
+{
+    g_return_val_if_fail(NM_IS_DEVICE_IPVLAN(device), FALSE);
+
+    return NM_DEVICE_IPVLAN_GET_PRIVATE(device)->private_flag;
+}
+
+/**
+ * nm_device_ipvlan_get_vepa
+ * @device: a #NMDeviceIpvlan
+ *
+ * Gets the VEPA flag of the device.
+ *
+ * Returns: the VEPA flag of the device.
+ *
+ * Since: 1.52
+ **/
+gboolean
+nm_device_ipvlan_get_vepa(NMDeviceIpvlan *device)
+{
+    g_return_val_if_fail(NM_IS_DEVICE_IPVLAN(device), FALSE);
+
+    return NM_DEVICE_IPVLAN_GET_PRIVATE(device)->vepa;
+}
+
+/*****************************************************************************/
+
+static void
+get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+    NMDeviceIpvlan *device = NM_DEVICE_IPVLAN(object);
+
+    switch (prop_id) {
+    case PROP_PARENT:
+        g_value_set_object(value, nm_device_ipvlan_get_parent(device));
+        break;
+    case PROP_MODE:
+        g_value_set_string(value, nm_device_ipvlan_get_mode(device));
+        break;
+    case PROP_PRIVATE:
+        g_value_set_boolean(value, nm_device_ipvlan_get_private(device));
+        break;
+    case PROP_VEPA:
+        g_value_set_boolean(value, nm_device_ipvlan_get_vepa(device));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+nm_device_ipvlan_init(NMDeviceIpvlan *device)
+{}
+
+static void
+finalize(GObject *object)
+{
+    NMDeviceIpvlanPrivate *priv = NM_DEVICE_IPVLAN_GET_PRIVATE(object);
+
+    g_free(priv->mode);
+
+    G_OBJECT_CLASS(nm_device_ipvlan_parent_class)->finalize(object);
+}
+
+const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_ipvlan = NML_DBUS_META_IFACE_INIT_PROP(
+    NM_DBUS_INTERFACE_DEVICE_IPVLAN,
+    nm_device_ipvlan_get_type,
+    NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_30,
+    NML_DBUS_META_IFACE_DBUS_PROPERTIES(
+        NML_DBUS_META_PROPERTY_INIT_S("Mode", PROP_MODE, NMDeviceIpvlan, _priv.mode),
+        NML_DBUS_META_PROPERTY_INIT_O_PROP("Parent",
+                                           PROP_PARENT,
+                                           NMDeviceIpvlan,
+                                           _priv.parent,
+                                           nm_device_get_type),
+        NML_DBUS_META_PROPERTY_INIT_B("Private", PROP_PRIVATE, NMDeviceIpvlan, _priv.private_flag),
+        NML_DBUS_META_PROPERTY_INIT_B("Vepa", PROP_VEPA, NMDeviceIpvlan, _priv.vepa), ), );
+
+static void
+nm_device_ipvlan_class_init(NMDeviceIpvlanClass *klass)
+{
+    GObjectClass  *object_class    = G_OBJECT_CLASS(klass);
+    NMObjectClass *nm_object_class = NM_OBJECT_CLASS(klass);
+
+    object_class->get_property = get_property;
+    object_class->finalize     = finalize;
+
+    _NM_OBJECT_CLASS_INIT_PRIV_PTR_DIRECT(nm_object_class, NMDeviceIpvlan);
+
+    _NM_OBJECT_CLASS_INIT_PROPERTY_O_FIELDS_1(nm_object_class, NMDeviceIpvlanPrivate, parent);
+
+    /**
+     * NMDeviceIpvlan:parent:
+     *
+     * The devices's parent device.
+     *
+     * Since: 1.52
+     **/
+    obj_properties[PROP_PARENT] = g_param_spec_object(NM_DEVICE_IPVLAN_PARENT,
+                                                      "",
+                                                      "",
+                                                      NM_TYPE_DEVICE,
+                                                      G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMDeviceIpvlan:mode:
+     *
+     * The IPVLAN mode.
+     *
+     * Since: 1.52
+     **/
+    obj_properties[PROP_MODE] = g_param_spec_string(NM_DEVICE_IPVLAN_MODE,
+                                                    "",
+                                                    "",
+                                                    NULL,
+                                                    G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMDeviceIpvlan:private:
+     *
+     * Whether the device has the private flag.
+     *
+     * Since: 1.52
+     **/
+    obj_properties[PROP_PRIVATE] = g_param_spec_boolean(NM_DEVICE_IPVLAN_PRIVATE,
+                                                        "",
+                                                        "",
+                                                        FALSE,
+                                                        G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMDeviceIpvlan:vepa:
+     *
+     * Whether the device has the VEPA flag.
+     *
+     * Since: 1.52
+     **/
+    obj_properties[PROP_VEPA] = g_param_spec_boolean(NM_DEVICE_IPVLAN_VEPA,
+                                                     "",
+                                                     "",
+                                                     FALSE,
+                                                     G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+    _nml_dbus_meta_class_init_with_properties(object_class, &_nml_dbus_meta_iface_nm_device_ipvlan);
+}
diff --git a/src/libnm-client-impl/nm-device.c b/src/libnm-client-impl/nm-device.c
index dc868f5b..f9d7329b 100644
--- a/src/libnm-client-impl/nm-device.c
+++ b/src/libnm-client-impl/nm-device.c
@@ -314,6 +314,7 @@ coerce_type(NMDeviceType type)
     case NM_DEVICE_TYPE_VRF:
     case NM_DEVICE_TYPE_LOOPBACK:
     case NM_DEVICE_TYPE_HSR:
+    case NM_DEVICE_TYPE_IPVLAN:
         return type;
     }
     return NM_DEVICE_TYPE_UNKNOWN;
@@ -609,7 +610,7 @@ const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device = NML_DBUS_META_IFACE_INIT
             .prop_struct_offset =
                 G_STRUCT_OFFSET(NMDevicePrivate, property_ao[PROPERTY_AO_IDX_PORTS]),
             .extra.property_vtable_ao =
-                &((const NMLDBusPropertVTableAO){.get_o_type_fcn = (nm_device_get_type)})),
+                &((const NMLDBusPropertVTableAO) {.get_o_type_fcn = (nm_device_get_type)})),
         NML_DBUS_META_PROPERTY_INIT_B("Real", PROP_REAL, NMDevicePrivate, real),
         NML_DBUS_META_PROPERTY_INIT_IGNORE("State", "u"),
         NML_DBUS_META_PROPERTY_INIT_FCN("StateReason",
@@ -1817,6 +1818,8 @@ get_type_name(NMDevice *device)
         return _("Loopback");
     case NM_DEVICE_TYPE_HSR:
         return _("HSR");
+    case NM_DEVICE_TYPE_IPVLAN:
+        return _("IPVLAN");
     case NM_DEVICE_TYPE_GENERIC:
     case NM_DEVICE_TYPE_UNUSED1:
     case NM_DEVICE_TYPE_UNUSED2:
@@ -3001,7 +3004,7 @@ nm_lldp_neighbor_new(void)
     NMLldpNeighbor *neigh;
 
     neigh  = g_slice_new(NMLldpNeighbor);
-    *neigh = (NMLldpNeighbor){
+    *neigh = (NMLldpNeighbor) {
         .refcount = 1,
         .attrs    = g_hash_table_new_full(nm_str_hash,
                                        g_str_equal,
diff --git a/src/libnm-client-impl/nm-ip-config.c b/src/libnm-client-impl/nm-ip-config.c
index c054f2cc..ad5f08f8 100644
--- a/src/libnm-client-impl/nm-ip-config.c
+++ b/src/libnm-client-impl/nm-ip-config.c
@@ -166,25 +166,32 @@ _notify_update_prop_nameservers(NMClient               *client,
 
             g_variant_iter_init(&iter, value);
             while (g_variant_iter_next(&iter, "a{sv}", &iter_v)) {
-                const char *key;
-                GVariant   *val;
+                const char   *key;
+                GVariant     *val;
+                gs_free char *nameserver = NULL;
 
                 while (g_variant_iter_next(iter_v, "{&sv}", &key, &val)) {
-                    if (nm_streq(key, "address")) {
+                    if (nm_streq(key, "address") && !nameserver) {
                         gs_free char *val_str = NULL;
 
                         if (!g_variant_is_of_type(val, G_VARIANT_TYPE_STRING))
                             goto next;
                         if (!nm_inet_parse_str(AF_INET, g_variant_get_string(val, NULL), &val_str))
                             goto next;
-                        if (!arr)
-                            arr = g_ptr_array_new();
-                        g_ptr_array_add(arr, g_steal_pointer(&val_str));
-                        goto next;
+                        nameserver = g_steal_pointer(&val_str);
+                    } else if (nm_streq(key, "uri")) {
+                        nameserver = g_variant_dup_string(val, NULL);
                     }
 next:
                     g_variant_unref(val);
                 }
+
+                if (nameserver) {
+                    if (!arr)
+                        arr = g_ptr_array_new();
+                    g_ptr_array_add(arr, g_steal_pointer(&nameserver));
+                }
+
                 g_variant_iter_free(iter_v);
             }
             if (arr && arr->len > 0)
diff --git a/src/libnm-client-impl/nm-libnm-utils.c b/src/libnm-client-impl/nm-libnm-utils.c
index 8af234ce..1b25c92c 100644
--- a/src/libnm-client-impl/nm-libnm-utils.c
+++ b/src/libnm-client-impl/nm-libnm-utils.c
@@ -785,6 +785,7 @@ const NMLDBusMetaIface *const _nml_dbus_meta_ifaces[] = {
     &_nml_dbus_meta_iface_nm_device_hsr,
     &_nml_dbus_meta_iface_nm_device_iptunnel,
     &_nml_dbus_meta_iface_nm_device_infiniband,
+    &_nml_dbus_meta_iface_nm_device_ipvlan,
     &_nml_dbus_meta_iface_nm_device_loopback,
     &_nml_dbus_meta_iface_nm_device_lowpan,
     &_nml_dbus_meta_iface_nm_device_macsec,
diff --git a/src/libnm-client-impl/nm-libnm-utils.h b/src/libnm-client-impl/nm-libnm-utils.h
index 61ff442d..7dcf8c18 100644
--- a/src/libnm-client-impl/nm-libnm-utils.h
+++ b/src/libnm-client-impl/nm-libnm-utils.h
@@ -440,8 +440,8 @@ typedef struct {
         v_obj_properties_idx,                                                     \
         .prop_struct_offset =                                                     \
             NM_STRUCT_OFFSET_ENSURE_TYPE(NMLDBusPropertyO, v_container, v_field), \
-        .extra.property_vtable_o =                                                \
-            &((const NMLDBusPropertVTableO){.get_o_type_fcn = (v_get_o_type_fcn), ##__VA_ARGS__}))
+        .extra.property_vtable_o = &(                                             \
+            (const NMLDBusPropertVTableO) {.get_o_type_fcn = (v_get_o_type_fcn), ##__VA_ARGS__}))
 
 #define NML_DBUS_META_PROPERTY_INIT_AO_PROP(v_dbus_property_name,                  \
                                             v_obj_properties_idx,                  \
@@ -456,7 +456,7 @@ typedef struct {
         .prop_struct_offset =                                                      \
             NM_STRUCT_OFFSET_ENSURE_TYPE(NMLDBusPropertyAO, v_container, v_field), \
         .extra.property_vtable_ao = &(                                             \
-            (const NMLDBusPropertVTableAO){.get_o_type_fcn = (v_get_o_type_fcn), ##__VA_ARGS__}))
+            (const NMLDBusPropertVTableAO) {.get_o_type_fcn = (v_get_o_type_fcn), ##__VA_ARGS__}))
 
 #define NML_DBUS_META_PROPERTY_INIT_FCN(v_dbus_property_name,                 \
                                         v_obj_properties_idx,                 \
@@ -559,12 +559,12 @@ struct _NMLDBusMetaIface {
 #define NML_DBUS_META_IFACE_OBJ_PROPERTIES()                                    \
     .obj_properties             = (const GParamSpec *const *) (obj_properties), \
     .n_obj_properties           = _PROPERTY_ENUMS_LAST,                         \
-    .obj_properties_reverse_idx = ((guint8[_PROPERTY_ENUMS_LAST]){})
+    .obj_properties_reverse_idx = ((guint8[_PROPERTY_ENUMS_LAST]) {})
 
-#define NML_DBUS_META_IFACE_DBUS_PROPERTIES(...)                     \
-    .dbus_properties = ((const NMLDBusMetaProperty[]){__VA_ARGS__}), \
-    .n_dbus_properties =                                             \
-        (sizeof((const NMLDBusMetaProperty[]){__VA_ARGS__}) / sizeof(NMLDBusMetaProperty))
+#define NML_DBUS_META_IFACE_DBUS_PROPERTIES(...)                      \
+    .dbus_properties = ((const NMLDBusMetaProperty[]) {__VA_ARGS__}), \
+    .n_dbus_properties =                                              \
+        (sizeof((const NMLDBusMetaProperty[]) {__VA_ARGS__}) / sizeof(NMLDBusMetaProperty))
 
 #define NML_DBUS_META_IFACE_INIT(v_dbus_iface_name, v_get_type_fcn, v_interface_prio, ...) \
     {.dbus_iface_name = "" v_dbus_iface_name "",                                           \
@@ -579,7 +579,7 @@ struct _NMLDBusMetaIface {
                              NML_DBUS_META_IFACE_OBJ_PROPERTIES(),                              \
                              ##__VA_ARGS__)
 
-extern const NMLDBusMetaIface *const _nml_dbus_meta_ifaces[46];
+extern const NMLDBusMetaIface *const _nml_dbus_meta_ifaces[47];
 
 extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm;
 extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_accesspoint;
@@ -596,6 +596,7 @@ extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_generic;
 extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_hsr;
 extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_infiniband;
 extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_iptunnel;
+extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_ipvlan;
 extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_loopback;
 extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_lowpan;
 extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_macsec;
@@ -639,7 +640,7 @@ void _nml_dbus_meta_class_init_with_properties_impl(GObjectClass
 #define _nml_dbus_meta_class_init_with_properties(object_class, ...) \
     _nml_dbus_meta_class_init_with_properties_impl(                  \
         (object_class),                                              \
-        ((const NMLDBusMetaIface *const[]){__VA_ARGS__, NULL}))
+        ((const NMLDBusMetaIface *const[]) {__VA_ARGS__, NULL}))
 
 /*****************************************************************************/
 
@@ -792,7 +793,7 @@ struct _NMObjectClass {
              * variable here. */          \
             nm_assert(!_f.klass);                                                    \
                                                                                      \
-            _f = (_NMObjectClassFieldInfo){                                          \
+            _f = (_NMObjectClassFieldInfo) {                                         \
                 .parent = _klass->field_name,                                        \
                 .klass  = _klass,                                                    \
                 .offset = (_offset),                                                 \
diff --git a/src/libnm-client-impl/nm-secret-agent-old.c b/src/libnm-client-impl/nm-secret-agent-old.c
index 8f7e0b4d..73850bf1 100644
--- a/src/libnm-client-impl/nm-secret-agent-old.c
+++ b/src/libnm-client-impl/nm-secret-agent-old.c
@@ -476,7 +476,7 @@ impl_get_secrets(NMSecretAgentOld *self, GVariant *parameters, GDBusMethodInvoca
         _cancel_get_secret_request(self, info, "Request aborted due to new request");
 
     info  = g_slice_new(GetSecretsInfo);
-    *info = (GetSecretsInfo){
+    *info = (GetSecretsInfo) {
         .context         = context,
         .connection_path = g_strdup(arg_connection_path),
         .setting_name    = g_strdup(arg_setting_name),
diff --git a/src/libnm-client-impl/nm-vpn-service-plugin.c b/src/libnm-client-impl/nm-vpn-service-plugin.c
index d26a4ff5..1235a2a5 100644
--- a/src/libnm-client-impl/nm-vpn-service-plugin.c
+++ b/src/libnm-client-impl/nm-vpn-service-plugin.c
@@ -232,11 +232,30 @@ nm_vpn_service_plugin_disconnect(NMVpnServicePlugin *plugin, GError **err)
 }
 
 static void
-nm_vpn_service_plugin_emit_quit(NMVpnServicePlugin *plugin)
+flushed_cb(GObject *object, GAsyncResult *res, gpointer data)
 {
+    NMVpnServicePlugin *plugin = NM_VPN_SERVICE_PLUGIN(data);
+    GError             *error  = NULL;
+
+    if (!g_dbus_connection_flush_finish(G_DBUS_CONNECTION(object), res, &error)) {
+        g_warning("Error flushing D-Bus connection: %s", error->message);
+        g_error_free(error);
+    }
+
     g_signal_emit(plugin, signals[QUIT], 0);
 }
 
+static void
+flush_and_quit(NMVpnServicePlugin *plugin)
+{
+    NMVpnServicePluginPrivate *priv = NM_VPN_SERVICE_PLUGIN_GET_PRIVATE(plugin);
+
+    if (priv->connection != NULL)
+        g_dbus_connection_flush(priv->connection, NULL, flushed_cb, plugin);
+    else
+        g_signal_emit(plugin, signals[QUIT], 0);
+}
+
 /**
  * nm_vpn_service_plugin_shutdown:
  * @plugin: the #NMVpnServicePlugin instance
@@ -305,7 +324,8 @@ quit_timer_expired(gpointer data)
     NMVpnServicePlugin *self = NM_VPN_SERVICE_PLUGIN(data);
 
     NM_VPN_SERVICE_PLUGIN_GET_PRIVATE(self)->quit_timer = 0;
-    nm_vpn_service_plugin_emit_quit(self);
+    flush_and_quit(self);
+
     return G_SOURCE_REMOVE;
 }
 
@@ -997,17 +1017,17 @@ impl_vpn_service_plugin_set_failure(NMVpnServicePlugin    *plugin,
 /*****************************************************************************/
 
 static void
-_emit_quit(gpointer data, gpointer user_data)
+_flush_and_quit_plugin(gpointer data, gpointer user_data)
 {
     NMVpnServicePlugin *plugin = data;
 
-    nm_vpn_service_plugin_emit_quit(plugin);
+    flush_and_quit(plugin);
 }
 
 static void
 sigterm_handler(int signum)
 {
-    g_slist_foreach(active_plugins, _emit_quit, NULL);
+    g_slist_foreach(active_plugins, _flush_and_quit_plugin, NULL);
 }
 
 static void
@@ -1204,7 +1224,7 @@ state_changed(NMVpnServicePlugin *plugin, NMVpnServiceState state)
         break;
     case NM_VPN_SERVICE_STATE_STOPPED:
         if (priv->dbus_watch_peer)
-            nm_vpn_service_plugin_emit_quit(plugin);
+            flush_and_quit(plugin);
         else
             schedule_quit_timer(plugin);
         nm_clear_g_dbus_connection_signal(nm_vpn_service_plugin_get_connection(plugin),
diff --git a/src/libnm-client-impl/tests/test-libnm.c b/src/libnm-client-impl/tests/test-libnm.c
index f6bf1567..f56521a4 100644
--- a/src/libnm-client-impl/tests/test-libnm.c
+++ b/src/libnm-client-impl/tests/test-libnm.c
@@ -2285,7 +2285,7 @@ typedef struct {
     const char *val;
 } ReadVpnDetailData;
 
-#define READ_VPN_DETAIL_DATA(...) ((ReadVpnDetailData[]){__VA_ARGS__})
+#define READ_VPN_DETAIL_DATA(...) ((ReadVpnDetailData[]) {__VA_ARGS__})
 
 static gboolean
 _do_read_vpn_details_impl1(const char              *file,
@@ -2693,6 +2693,7 @@ test_types(void)
         G(nm_device_hsr_get_type),
         G(nm_device_infiniband_get_type),
         G(nm_device_ip_tunnel_get_type),
+        G(nm_device_ipvlan_get_type),
         G(nm_device_macsec_get_type),
         G(nm_device_macvlan_get_type),
         G(nm_device_modem_capabilities_get_type),
@@ -2771,6 +2772,8 @@ test_types(void)
         G(nm_setting_ip6_config_privacy_get_type),
         G(nm_setting_ip_config_get_type),
         G(nm_setting_ip_tunnel_get_type),
+        G(nm_setting_ipvlan_get_type),
+        G(nm_setting_ipvlan_mode_get_type),
         G(nm_setting_mac_randomization_get_type),
         G(nm_setting_macsec_get_type),
         G(nm_setting_macsec_mode_get_type),
@@ -3001,8 +3004,13 @@ test_nml_dbus_meta(void)
                             g_assert(NM_IS_OBJECT_CLASS(p->klass));
                             g_assert(g_type_is_a(gtype, G_TYPE_FROM_CLASS(p->klass)));
                             if (ii == 0)
+                                /* If there is more than one NMLDBusPropertyO needed in the struct
+                                 * associated to the DBus object, they must be all in the same struct field
+                                 * as an array. This is later used on nm-object.c to perform operations on
+                                 * all the object properties at once. */
                                 g_assert(p->klass->property_o_info == p);
                             else
+                                /* Same check than above if branch but for NMLDBusPropertyAO. */
                                 g_assert(p->klass->property_ao_info == p);
                             g_assert_cmpint(p->klass->priv_ptr_offset, >, 0);
                             if (p_prev) {
@@ -3401,6 +3409,11 @@ test_dbus_meta_types(void)
             NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_30,
         },
         {
+            NM_DBUS_INTERFACE_DEVICE_IPVLAN,
+            NM_TYPE_DEVICE_IPVLAN,
+            NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_30,
+        },
+        {
             NM_DBUS_INTERFACE_DEVICE_MACSEC,
             NM_TYPE_DEVICE_MACSEC,
             NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_30,
diff --git a/src/libnm-client-impl/tests/test-nm-client.c b/src/libnm-client-impl/tests/test-nm-client.c
index 3d527324..39831509 100644
--- a/src/libnm-client-impl/tests/test-nm-client.c
+++ b/src/libnm-client-impl/tests/test-nm-client.c
@@ -1099,7 +1099,7 @@ test_connection_invalid(void)
     g_assert_cmpint(connections->len, ==, 3);
     n_found = nmtst_find_all_indexes(connections->pdata,
                                      connections->len,
-                                     (gpointer *) ((const char *[]){path0, path1, path2}),
+                                     (gpointer *) ((const char *[]) {path0, path1, path2}),
                                      3,
                                      _test_connection_invalid_find_connections,
                                      NULL,
@@ -1134,7 +1134,7 @@ test_connection_invalid(void)
     g_assert_cmpint(connections->len, ==, 4);
     n_found = nmtst_find_all_indexes(connections->pdata,
                                      connections->len,
-                                     (gpointer *) ((const char *[]){path0, path1, path2, path3}),
+                                     (gpointer *) ((const char *[]) {path0, path1, path2, path3}),
                                      4,
                                      _test_connection_invalid_find_connections,
                                      NULL,
@@ -1166,7 +1166,7 @@ test_connection_invalid(void)
     g_assert_cmpint(connections->len, ==, 4);
     n_found = nmtst_find_all_indexes(connections->pdata,
                                      connections->len,
-                                     (gpointer *) ((const char *[]){path0, path1, path2, path3}),
+                                     (gpointer *) ((const char *[]) {path0, path1, path2, path3}),
                                      4,
                                      _test_connection_invalid_find_connections,
                                      NULL,
@@ -1202,7 +1202,7 @@ test_connection_invalid(void)
     g_assert_cmpint(connections->len, ==, 4);
     n_found = nmtst_find_all_indexes(connections->pdata,
                                      connections->len,
-                                     (gpointer *) ((const char *[]){path0, path1, path2, path3}),
+                                     (gpointer *) ((const char *[]) {path0, path1, path2, path3}),
                                      4,
                                      _test_connection_invalid_find_connections,
                                      NULL,
@@ -1232,7 +1232,7 @@ test_connection_invalid(void)
     g_assert_cmpint(connections->len, ==, 4);
     n_found = nmtst_find_all_indexes(connections->pdata,
                                      connections->len,
-                                     (gpointer *) ((const char *[]){path0, path1, path2, path3}),
+                                     (gpointer *) ((const char *[]) {path0, path1, path2, path3}),
                                      4,
                                      _test_connection_invalid_find_connections,
                                      NULL,
@@ -1279,7 +1279,7 @@ test_connection_invalid(void)
     g_assert_cmpint(connections->len, ==, 4);
     n_found = nmtst_find_all_indexes(connections->pdata,
                                      connections->len,
-                                     (gpointer *) ((const char *[]){path0, path1, path2, path3}),
+                                     (gpointer *) ((const char *[]) {path0, path1, path2, path3}),
                                      4,
                                      _test_connection_invalid_find_connections,
                                      NULL,
@@ -1326,7 +1326,7 @@ test_connection_invalid(void)
     g_assert_cmpint(connections->len, ==, 4);
     n_found = nmtst_find_all_indexes(connections->pdata,
                                      connections->len,
-                                     (gpointer *) ((const char *[]){path0, path1, path2, path3}),
+                                     (gpointer *) ((const char *[]) {path0, path1, path2, path3}),
                                      4,
                                      _test_connection_invalid_find_connections,
                                      NULL,
diff --git a/src/libnm-client-impl/tests/test-secret-agent.c b/src/libnm-client-impl/tests/test-secret-agent.c
index 1fffb556..9871b1a4 100644
--- a/src/libnm-client-impl/tests/test-secret-agent.c
+++ b/src/libnm-client-impl/tests/test-secret-agent.c
@@ -344,7 +344,7 @@ test_cleanup(TestSecretAgentData *sadata, gconstpointer test_data)
     g_free(sadata->ifname);
     g_free(sadata->con_id);
 
-    *sadata = (TestSecretAgentData){};
+    *sadata = (TestSecretAgentData) {};
 
     nmtst_context_busy_watcher_wait(&watcher_data);