about summary refs log tree commit diff
path: root/src/core/devices/nm-device-loopback.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/devices/nm-device-loopback.c')
-rw-r--r--src/core/devices/nm-device-loopback.c166
1 files changed, 166 insertions, 0 deletions
diff --git a/src/core/devices/nm-device-loopback.c b/src/core/devices/nm-device-loopback.c
new file mode 100644
index 00000000..ec72aa96
--- /dev/null
+++ b/src/core/devices/nm-device-loopback.c
@@ -0,0 +1,166 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2022 Red Hat, Inc.
+ */
+
+#include "src/core/nm-default-daemon.h"
+#include "nm-device-loopback.h"
+#include "nm-device-private.h"
+#include "libnm-platform/nm-platform.h"
+#include "nm-device-factory.h"
+#include "nm-setting-loopback.h"
+#include "libnm-core-aux-intern/nm-libnm-core-utils.h"
+
+#define _NMLOG_DEVICE_TYPE NMDeviceLoopback
+#include "nm-device-logging.h"
+
+/*****************************************************************************/
+
+struct _NMDeviceLoopback {
+    NMDevice parent;
+};
+
+struct _NMDeviceLoopbackClass {
+    NMDeviceClass parent;
+};
+
+G_DEFINE_TYPE(NMDeviceLoopback, nm_device_loopback, NM_TYPE_DEVICE)
+
+/*****************************************************************************/
+
+static NMDeviceCapabilities
+get_generic_capabilities(NMDevice *dev)
+{
+    /* In many aspects, loopback is a software device. Still, don't return
+     * NM_DEVICE_CAP_IS_SOFTWARE here, because we cannot delete nor create
+     * such an interface. */
+    return NM_DEVICE_CAP_NONE;
+}
+
+static guint32
+get_configured_mtu(NMDevice *device, NMDeviceMtuSource *out_source, gboolean *out_force)
+{
+    return nm_device_get_configured_mtu_from_connection(device,
+                                                        NM_TYPE_SETTING_LOOPBACK,
+                                                        out_source);
+}
+
+static const char *
+get_auto_ip_config_method(NMDevice *device, int addr_family)
+{
+    return NM_IS_IPv4(addr_family) ? NM_SETTING_IP4_CONFIG_METHOD_MANUAL
+                                   : NM_SETTING_IP6_CONFIG_METHOD_MANUAL;
+}
+
+static gboolean
+complete_connection(NMDevice            *device,
+                    NMConnection        *connection,
+                    const char          *specific_object,
+                    NMConnection *const *existing_connections,
+                    GError             **error)
+{
+    nm_utils_complete_generic_with_params(nm_device_get_platform(device),
+                                          connection,
+                                          NM_SETTING_LOOPBACK_SETTING_NAME,
+                                          existing_connections,
+                                          NULL,
+                                          _("Loopback connection"),
+                                          NULL,
+                                          nm_device_get_ip_iface(device));
+
+    _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_LOOPBACK);
+
+    return TRUE;
+}
+
+static void
+update_connection(NMDevice *device, NMConnection *connection)
+{
+    _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_LOOPBACK);
+}
+
+static gboolean
+can_reapply_change(NMDevice   *device,
+                   const char *setting_name,
+                   NMSetting  *s_old,
+                   NMSetting  *s_new,
+                   GHashTable *diffs,
+                   GError    **error)
+{
+    if (!nm_streq(setting_name, NM_SETTING_LOOPBACK_SETTING_NAME)) {
+        return NM_DEVICE_CLASS(nm_device_loopback_parent_class)
+            ->can_reapply_change(device, setting_name, s_old, s_new, diffs, error);
+    }
+
+    return nm_device_hash_check_invalid_keys(diffs,
+                                             NM_SETTING_LOOPBACK_SETTING_NAME,
+                                             error,
+                                             NM_SETTING_LOOPBACK_MTU);
+}
+
+/*****************************************************************************/
+
+static const NMDBusInterfaceInfoExtended interface_info_device_loopback = {
+    .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT(NM_DBUS_INTERFACE_DEVICE_LOOPBACK, ),
+};
+
+static void
+nm_device_loopback_init(NMDeviceLoopback *self)
+{}
+
+static void
+nm_device_loopback_class_init(NMDeviceLoopbackClass *klass)
+{
+    NMDeviceClass     *device_class      = NM_DEVICE_CLASS(klass);
+    NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass);
+
+    dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_device_loopback);
+
+    device_class->connection_type_supported        = NM_SETTING_LOOPBACK_SETTING_NAME;
+    device_class->connection_type_check_compatible = NM_SETTING_LOOPBACK_SETTING_NAME;
+    device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES(NM_LINK_TYPE_LOOPBACK);
+
+    device_class->complete_connection                    = complete_connection;
+    device_class->get_generic_capabilities               = get_generic_capabilities;
+    device_class->update_connection                      = update_connection;
+    device_class->act_stage1_prepare_set_hwaddr_ethernet = TRUE;
+    device_class->get_auto_ip_config_method              = get_auto_ip_config_method;
+    device_class->get_configured_mtu                     = get_configured_mtu;
+    device_class->allow_autoconnect_on_external          = TRUE;
+    device_class->can_reapply_change                     = can_reapply_change;
+}
+
+/*****************************************************************************/
+
+#define NM_TYPE_LOOPBACK_DEVICE_FACTORY (nm_loopback_device_factory_get_type())
+#define NM_LOOPBACK_DEVICE_FACTORY(obj)                              \
+    (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj),                           \
+                                    NM_TYPE_LOOPBACK_DEVICE_FACTORY, \
+                                    NMLoopbackDeviceFactory))
+
+static NMDevice *
+create_device(NMDeviceFactory      *factory,
+              const char           *iface,
+              const NMPlatformLink *plink,
+              NMConnection         *connection,
+              gboolean             *out_ignore)
+{
+    return g_object_new(NM_TYPE_DEVICE_LOOPBACK,
+                        NM_DEVICE_IFACE,
+                        iface,
+                        NM_DEVICE_TYPE_DESC,
+                        "Loopback",
+                        NM_DEVICE_DEVICE_TYPE,
+                        NM_DEVICE_TYPE_LOOPBACK,
+                        NM_DEVICE_LINK_TYPE,
+                        NM_LINK_TYPE_LOOPBACK,
+                        NULL);
+}
+
+NM_DEVICE_FACTORY_DEFINE_INTERNAL(
+    LOOPBACK,
+    Loopback,
+    loopback,
+    NM_DEVICE_FACTORY_DECLARE_LINK_TYPES(NM_LINK_TYPE_LOOPBACK)
+        NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES(NM_SETTING_LOOPBACK_SETTING_NAME),
+    factory_class->create_device = create_device;);