Blame src/core/settings/plugins/ifupdown/nms-ifupdown-plugin.c

Packit Service 5ffa24
/* SPDX-License-Identifier: GPL-2.0-or-later */
Packit Service 5ffa24
/*
Packit Service 5ffa24
 * Alexander Sack <asac@ubuntu.com>
Packit Service 5ffa24
 * Copyright (C) 2007, 2008 Canonical Ltd.
Packit Service 5ffa24
 * Copyright (C) 2009 - 2011 Red Hat, Inc.
Packit Service 5ffa24
 */
Packit Service 5ffa24
Packit Service 2bceb2
#include "src/core/nm-default-daemon.h"
Packit Service 5ffa24
Packit Service 5ffa24
#include "nms-ifupdown-plugin.h"
Packit Service 5ffa24
Packit Service 5ffa24
#include "nm-core-internal.h"
Packit Service 5ffa24
#include "nm-core-utils.h"
Packit Service 5ffa24
#include "nm-config.h"
Packit Service 5ffa24
#include "settings/nm-settings-plugin.h"
Packit Service 5ffa24
#include "settings/nm-settings-storage.h"
Packit Service 5ffa24
Packit Service 5ffa24
#include "nms-ifupdown-interface-parser.h"
Packit Service 5ffa24
#include "nms-ifupdown-parser.h"
Packit Service 5ffa24
Packit Service 5ffa24
#define ENI_INTERFACES_FILE "/etc/network/interfaces"
Packit Service 5ffa24
Packit Service 5ffa24
#define IFUPDOWN_UNMANAGE_WELL_KNOWN_DEFAULT TRUE
Packit Service 5ffa24
Packit Service 5ffa24
/*****************************************************************************/
Packit Service 5ffa24
Packit Service 5ffa24
typedef struct {
Packit Service 5ffa24
    NMConnection *     connection;
Packit Service 5ffa24
    NMSettingsStorage *storage;
Packit Service 5ffa24
} StorageData;
Packit Service 5ffa24
Packit Service 5ffa24
typedef struct {
Packit Service 5ffa24
    /* Stores an entry for blocks/interfaces read from /e/n/i and (if exists)
Packit Service 5ffa24
     * the StorageData associated with the block.
Packit Service 5ffa24
     */
Packit Service 5ffa24
    GHashTable *eni_ifaces;
Packit Service 5ffa24
Packit Service 5ffa24
    bool ifupdown_managed : 1;
Packit Service 5ffa24
Packit Service 5ffa24
    bool initialized : 1;
Packit Service 5ffa24
Packit Service 5ffa24
    bool already_reloaded : 1;
Packit Service 5ffa24
} NMSIfupdownPluginPrivate;
Packit Service 5ffa24
Packit Service 5ffa24
struct _NMSIfupdownPlugin {
Packit Service 5ffa24
    NMSettingsPlugin         parent;
Packit Service 5ffa24
    NMSIfupdownPluginPrivate _priv;
Packit Service 5ffa24
};
Packit Service 5ffa24
Packit Service 5ffa24
struct _NMSIfupdownPluginClass {
Packit Service 5ffa24
    NMSettingsPluginClass parent;
Packit Service 5ffa24
};
Packit Service 5ffa24
Packit Service 5ffa24
G_DEFINE_TYPE(NMSIfupdownPlugin, nms_ifupdown_plugin, NM_TYPE_SETTINGS_PLUGIN)
Packit Service 5ffa24
Packit Service 5ffa24
#define NMS_IFUPDOWN_PLUGIN_GET_PRIVATE(self) \
Packit Service 5ffa24
    _NM_GET_PRIVATE(self, NMSIfupdownPlugin, NMS_IS_IFUPDOWN_PLUGIN)
Packit Service 5ffa24
Packit Service 5ffa24
/*****************************************************************************/
Packit Service 5ffa24
Packit Service 5ffa24
#define _NMLOG_PREFIX_NAME "ifupdown"
Packit Service 5ffa24
#define _NMLOG_DOMAIN      LOGD_SETTINGS
Packit Service 5ffa24
#define _NMLOG(level, ...)                          \
Packit Service 5ffa24
    nm_log((level),                                 \
Packit Service 5ffa24
           _NMLOG_DOMAIN,                           \
Packit Service 5ffa24
           NULL,                                    \
Packit Service 5ffa24
           NULL,                                    \
Packit Service 5ffa24
           "%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
Packit Service 5ffa24
           _NMLOG_PREFIX_NAME ": " _NM_UTILS_MACRO_REST(__VA_ARGS__))
Packit Service 5ffa24
Packit Service 5ffa24
/*****************************************************************************/
Packit Service 5ffa24
Packit Service 5ffa24
static GHashTable *load_eni_ifaces(NMSIfupdownPlugin *self);
Packit Service 5ffa24
Packit Service 5ffa24
/*****************************************************************************/
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
_storage_data_destroy(StorageData *sd)
Packit Service 5ffa24
{
Packit Service 5ffa24
    if (!sd)
Packit Service 5ffa24
        return;
Packit Service 5ffa24
    nm_g_object_unref(sd->connection);
Packit Service 5ffa24
    nm_g_object_unref(sd->storage);
Packit Service 5ffa24
    g_slice_free(StorageData, sd);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
/*****************************************************************************/
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
initialize(NMSIfupdownPlugin *self)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMSIfupdownPluginPrivate *priv = NMS_IFUPDOWN_PLUGIN_GET_PRIVATE(self);
Packit Service 5ffa24
    gboolean                  ifupdown_managed;
Packit Service 5ffa24
Packit Service 5ffa24
    nm_assert(!priv->initialized);
Packit Service 5ffa24
Packit Service 5ffa24
    priv->initialized = TRUE;
Packit Service 5ffa24
Packit Service 5ffa24
    ifupdown_managed = nm_config_data_get_value_boolean(NM_CONFIG_GET_DATA_ORIG,
Packit Service 5ffa24
                                                        NM_CONFIG_KEYFILE_GROUP_IFUPDOWN,
Packit Service 5ffa24
                                                        NM_CONFIG_KEYFILE_KEY_IFUPDOWN_MANAGED,
Packit Service 5ffa24
                                                        !IFUPDOWN_UNMANAGE_WELL_KNOWN_DEFAULT);
Packit Service 5ffa24
    _LOGI("management mode: %s", ifupdown_managed ? "managed" : "unmanaged");
Packit Service 5ffa24
    priv->ifupdown_managed = ifupdown_managed;
Packit Service 5ffa24
Packit Service 5ffa24
    priv->eni_ifaces = load_eni_ifaces(self);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
reload_connections(NMSettingsPlugin *                     plugin,
Packit Service 5ffa24
                   NMSettingsPluginConnectionLoadCallback callback,
Packit Service 5ffa24
                   gpointer                               user_data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMSIfupdownPlugin *       self                = NMS_IFUPDOWN_PLUGIN(plugin);
Packit Service 5ffa24
    NMSIfupdownPluginPrivate *priv                = NMS_IFUPDOWN_PLUGIN_GET_PRIVATE(self);
Packit Service 5ffa24
    gs_unref_hashtable GHashTable *eni_ifaces_old = NULL;
Packit Service 5ffa24
    GHashTableIter                 iter;
Packit Service 5ffa24
    StorageData *                  sd;
Packit Service 5ffa24
    StorageData *                  sd2;
Packit Service 5ffa24
    const char *                   block_name;
Packit Service 5ffa24
Packit Service 5ffa24
    if (!priv->initialized)
Packit Service 5ffa24
        initialize(self);
Packit Service 5ffa24
    else if (!priv->already_reloaded) {
Packit Service 5ffa24
        /* This is the first call to reload, but we are already initialized.
Packit Service 5ffa24
         *
Packit Service 5ffa24
         * This happens because during start NMSettings first queries unmanaged-specs,
Packit Service 5ffa24
         * and then issues a reload call right away.
Packit Service 5ffa24
         *
Packit Service 5ffa24
         * On future reloads, we really want to load /e/n/i again. */
Packit Service 5ffa24
        priv->already_reloaded = TRUE;
Packit Service 5ffa24
    } else {
Packit Service 5ffa24
        eni_ifaces_old   = priv->eni_ifaces;
Packit Service 5ffa24
        priv->eni_ifaces = load_eni_ifaces(self);
Packit Service 5ffa24
Packit Service 5ffa24
        g_hash_table_iter_init(&iter, eni_ifaces_old);
Packit Service 5ffa24
        while (g_hash_table_iter_next(&iter, (gpointer *) &block_name, (gpointer *) &sd)) {
Packit Service 5ffa24
            if (!sd)
Packit Service 5ffa24
                continue;
Packit Service 5ffa24
Packit Service 5ffa24
            sd2 = g_hash_table_lookup(priv->eni_ifaces, block_name);
Packit Service 5ffa24
            if (!sd2)
Packit Service 5ffa24
                continue;
Packit Service 5ffa24
Packit Service 5ffa24
            nm_assert(nm_streq(nm_settings_storage_get_uuid(sd->storage),
Packit Service 5ffa24
                               nm_settings_storage_get_uuid(sd2->storage)));
Packit Service 5ffa24
            nm_g_object_ref_set(&sd2->storage, sd->storage);
Packit Service 5ffa24
            g_hash_table_iter_remove(&iter);
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (!priv->ifupdown_managed)
Packit Service 5ffa24
        _LOGD("load: no connections due to managed=false");
Packit Service 5ffa24
Packit Service 5ffa24
    g_hash_table_iter_init(&iter, priv->eni_ifaces);
Packit Service 5ffa24
    while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &sd)) {
Packit Service 5ffa24
        gs_unref_object NMConnection *connection = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
        if (!sd)
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
Packit Service 5ffa24
        connection = g_steal_pointer(&sd->connection);
Packit Service 5ffa24
Packit Service 5ffa24
        if (!priv->ifupdown_managed)
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
Packit Service 5ffa24
        _LOGD("load: %s (%s)",
Packit Service 5ffa24
              nm_settings_storage_get_uuid(sd->storage),
Packit Service 5ffa24
              nm_connection_get_id(connection));
Packit Service 5ffa24
        callback(plugin, sd->storage, connection, user_data);
Packit Service 5ffa24
    }
Packit Service 5ffa24
    if (eni_ifaces_old && priv->ifupdown_managed) {
Packit Service 5ffa24
        g_hash_table_iter_init(&iter, eni_ifaces_old);
Packit Service 5ffa24
        while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &sd)) {
Packit Service 5ffa24
            if (!sd)
Packit Service 5ffa24
                continue;
Packit Service 5ffa24
            _LOGD("unload: %s", nm_settings_storage_get_uuid(sd->storage));
Packit Service 5ffa24
            callback(plugin, sd->storage, NULL, user_data);
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
/*****************************************************************************/
Packit Service 5ffa24
Packit Service 5ffa24
static GSList *
Packit Service 5ffa24
_unmanaged_specs(GHashTable *eni_ifaces)
Packit Service 5ffa24
{
Packit Service 5ffa24
    gs_free const char **keys  = NULL;
Packit Service 5ffa24
    GSList *             specs = NULL;
Packit Service 5ffa24
    guint                i, len;
Packit Service 5ffa24
Packit Service 5ffa24
    keys = nm_utils_strdict_get_keys(eni_ifaces, TRUE, &len;;
Packit Service 5ffa24
    for (i = len; i > 0;) {
Packit Service 5ffa24
        i--;
Packit Service 5ffa24
        specs = g_slist_prepend(specs,
Packit Service 5ffa24
                                g_strdup_printf(NM_MATCH_SPEC_INTERFACE_NAME_TAG "=%s", keys[i]));
Packit Service 5ffa24
    }
Packit Service 5ffa24
    return specs;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static GSList *
Packit Service 5ffa24
get_unmanaged_specs(NMSettingsPlugin *plugin)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMSIfupdownPlugin *       self = NMS_IFUPDOWN_PLUGIN(plugin);
Packit Service 5ffa24
    NMSIfupdownPluginPrivate *priv = NMS_IFUPDOWN_PLUGIN_GET_PRIVATE(self);
Packit Service 5ffa24
Packit Service 5ffa24
    if (G_UNLIKELY(!priv->initialized))
Packit Service 5ffa24
        initialize(self);
Packit Service 5ffa24
Packit Service 5ffa24
    if (priv->ifupdown_managed)
Packit Service 5ffa24
        return NULL;
Packit Service 5ffa24
Packit Service 5ffa24
    _LOGD("unmanaged-specs: unmanaged devices count %u", g_hash_table_size(priv->eni_ifaces));
Packit Service 5ffa24
Packit Service 5ffa24
    return _unmanaged_specs(priv->eni_ifaces);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
/*****************************************************************************/
Packit Service 5ffa24
Packit Service 5ffa24
static GHashTable *
Packit Service 5ffa24
load_eni_ifaces(NMSIfupdownPlugin *self)
Packit Service 5ffa24
{
Packit Service 5ffa24
    gs_unref_hashtable GHashTable *eni_ifaces  = NULL;
Packit Service 5ffa24
    gs_unref_hashtable GHashTable *auto_ifaces = NULL;
Packit Service 5ffa24
    nm_auto_ifparser if_parser *parser         = NULL;
Packit Service 5ffa24
    if_block *                  block;
Packit Service 5ffa24
    StorageData *               sd;
Packit Service 5ffa24
Packit Service 5ffa24
    eni_ifaces = g_hash_table_new_full(nm_str_hash,
Packit Service 5ffa24
                                       g_str_equal,
Packit Service 5ffa24
                                       g_free,
Packit Service 5ffa24
                                       (GDestroyNotify) _storage_data_destroy);
Packit Service 5ffa24
Packit Service 5ffa24
    parser = ifparser_parse(ENI_INTERFACES_FILE, 0);
Packit Service 5ffa24
Packit Service 5ffa24
    c_list_for_each_entry (block, &parser->block_lst_head, block_lst) {
Packit Service 5ffa24
        if (NM_IN_STRSET(block->type, "auto", "allow-hotplug")) {
Packit Service 5ffa24
            if (!auto_ifaces)
Packit Service 5ffa24
                auto_ifaces = g_hash_table_new(nm_str_hash, g_str_equal);
Packit Service 5ffa24
            g_hash_table_add(auto_ifaces, (char *) block->name);
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    c_list_for_each_entry (block, &parser->block_lst_head, block_lst) {
Packit Service 5ffa24
        if (NM_IN_STRSET(block->type, "auto", "allow-hotplug"))
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
Packit Service 5ffa24
        if (nm_streq(block->type, "iface")) {
Packit Service 5ffa24
            gs_free_error GError *local                = NULL;
Packit Service 5ffa24
            gs_unref_object NMConnection *connection   = NULL;
Packit Service 5ffa24
            gs_unref_object NMSettingsStorage *storage = NULL;
Packit Service 5ffa24
            const char *                       uuid    = NULL;
Packit Service 5ffa24
            StorageData *                      sd_repl;
Packit Service 5ffa24
Packit Service 5ffa24
            /* Bridge configuration */
Packit Service 5ffa24
            if (g_str_has_prefix(block->name, "br")) {
Packit Service 5ffa24
                /* Try to find bridge ports */
Packit Service 5ffa24
                const char *ports = ifparser_getkey(block, "bridge-ports");
Packit Service 5ffa24
Packit Service 5ffa24
                if (ports) {
Packit Service 5ffa24
                    int                  state       = 0;
Packit Service 5ffa24
                    gs_free const char **port_ifaces = NULL;
Packit Service 5ffa24
                    gsize                i;
Packit Service 5ffa24
Packit Service 5ffa24
                    _LOGD("parse: found bridge ports %s for %s", ports, block->name);
Packit Service 5ffa24
Packit Service 5ffa24
                    port_ifaces = nm_utils_strsplit_set(ports, " \t");
Packit Service 5ffa24
                    for (i = 0; port_ifaces && port_ifaces[i]; i++) {
Packit Service 5ffa24
                        const char *token = port_ifaces[i];
Packit Service 5ffa24
Packit Service 5ffa24
                        /* Skip crazy stuff like regex or all */
Packit Service 5ffa24
                        if (nm_streq(token, "all"))
Packit Service 5ffa24
                            continue;
Packit Service 5ffa24
Packit Service 5ffa24
                        /* Small SM to skip everything inside regex */
Packit Service 5ffa24
                        if (nm_streq(token, "regex")) {
Packit Service 5ffa24
                            state++;
Packit Service 5ffa24
                            continue;
Packit Service 5ffa24
                        }
Packit Service 5ffa24
                        if (nm_streq(token, "noregex")) {
Packit Service 5ffa24
                            state--;
Packit Service 5ffa24
                            continue;
Packit Service 5ffa24
                        }
Packit Service 5ffa24
                        if (nm_streq(token, "none"))
Packit Service 5ffa24
                            continue;
Packit Service 5ffa24
                        if (state == 0) {
Packit Service 5ffa24
                            sd = g_hash_table_lookup(eni_ifaces, block->name);
Packit Service 5ffa24
                            if (!sd) {
Packit Service 5ffa24
                                _LOGD("parse: adding bridge port \"%s\"", token);
Packit Service 5ffa24
                                g_hash_table_insert(eni_ifaces, g_strdup(token), NULL);
Packit Service 5ffa24
                            } else {
Packit Service 5ffa24
                                _LOGD("parse: adding bridge port \"%s\" (have connection %s)",
Packit Service 5ffa24
                                      token,
Packit Service 5ffa24
                                      nm_settings_storage_get_uuid(sd->storage));
Packit Service 5ffa24
                            }
Packit Service 5ffa24
                        }
Packit Service 5ffa24
                    }
Packit Service 5ffa24
                }
Packit Service 5ffa24
                continue;
Packit Service 5ffa24
            }
Packit Service 5ffa24
Packit Service 5ffa24
            /* Skip loopback configuration */
Packit Service 5ffa24
            if (nm_streq(block->name, "lo"))
Packit Service 5ffa24
                continue;
Packit Service 5ffa24
Packit Service 5ffa24
            sd_repl = g_hash_table_lookup(eni_ifaces, block->name);
Packit Service 5ffa24
            if (sd_repl) {
Packit Service 5ffa24
                _LOGD("parse: replace connection \"%s\" (%s)",
Packit Service 5ffa24
                      block->name,
Packit Service 5ffa24
                      nm_settings_storage_get_uuid(sd_repl->storage));
Packit Service 5ffa24
                storage = g_steal_pointer(&sd_repl->storage);
Packit Service 5ffa24
                g_hash_table_remove(eni_ifaces, block->name);
Packit Service 5ffa24
            }
Packit Service 5ffa24
Packit Service 5ffa24
            connection = ifupdown_new_connection_from_if_block(
Packit Service 5ffa24
                block,
Packit Service 5ffa24
                auto_ifaces && g_hash_table_contains(auto_ifaces, block->name),
Packit Service 5ffa24
                &local);
Packit Service 5ffa24
Packit Service 5ffa24
            if (!connection) {
Packit Service 5ffa24
                _LOGD("parse: adding place holder for \"%s\"%s%s%s",
Packit Service 5ffa24
                      block->name,
Packit Service 5ffa24
                      NM_PRINT_FMT_QUOTED(local, " (", local->message, ")", ""));
Packit Service 5ffa24
                sd = NULL;
Packit Service 5ffa24
            } else {
Packit Service 5ffa24
                nmtst_connection_assert_unchanging(connection);
Packit Service 5ffa24
                uuid = nm_connection_get_uuid(connection);
Packit Service 5ffa24
Packit Service 5ffa24
                if (!storage)
Packit Service 5ffa24
                    storage = nm_settings_storage_new(NM_SETTINGS_PLUGIN(self), uuid, NULL);
Packit Service 5ffa24
Packit Service 5ffa24
                sd  = g_slice_new(StorageData);
Packit Service 5ffa24
                *sd = (StorageData){
Packit Service 5ffa24
                    .connection = g_steal_pointer(&connection),
Packit Service 5ffa24
                    .storage    = g_steal_pointer(&storage),
Packit Service 5ffa24
                };
Packit Service 5ffa24
                _LOGD("parse: adding connection \"%s\" (%s)", block->name, uuid);
Packit Service 5ffa24
            }
Packit Service 5ffa24
Packit Service 5ffa24
            g_hash_table_replace(eni_ifaces, g_strdup(block->name), sd);
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        if (nm_streq(block->type, "mapping")) {
Packit Service 5ffa24
            sd = g_hash_table_lookup(eni_ifaces, block->name);
Packit Service 5ffa24
            if (!sd) {
Packit Service 5ffa24
                _LOGD("parse: adding mapping \"%s\"", block->name);
Packit Service 5ffa24
                g_hash_table_insert(eni_ifaces, g_strdup(block->name), NULL);
Packit Service 5ffa24
            } else {
Packit Service 5ffa24
                _LOGD("parse: adding mapping \"%s\" (have connection %s)",
Packit Service 5ffa24
                      block->name,
Packit Service 5ffa24
                      nm_settings_storage_get_uuid(sd->storage));
Packit Service 5ffa24
            }
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    nm_clear_pointer(&auto_ifaces, g_hash_table_destroy);
Packit Service 5ffa24
Packit Service 5ffa24
    return g_steal_pointer(&eni_ifaces);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
/*****************************************************************************/
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
nms_ifupdown_plugin_init(NMSIfupdownPlugin *self)
Packit Service 5ffa24
{}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
dispose(GObject *object)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMSIfupdownPlugin *       plugin = NMS_IFUPDOWN_PLUGIN(object);
Packit Service 5ffa24
    NMSIfupdownPluginPrivate *priv   = NMS_IFUPDOWN_PLUGIN_GET_PRIVATE(plugin);
Packit Service 5ffa24
Packit Service 5ffa24
    nm_clear_pointer(&priv->eni_ifaces, g_hash_table_destroy);
Packit Service 5ffa24
Packit Service 5ffa24
    G_OBJECT_CLASS(nms_ifupdown_plugin_parent_class)->dispose(object);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
nms_ifupdown_plugin_class_init(NMSIfupdownPluginClass *klass)
Packit Service 5ffa24
{
Packit Service 5ffa24
    GObjectClass *         object_class = G_OBJECT_CLASS(klass);
Packit Service 5ffa24
    NMSettingsPluginClass *plugin_class = NM_SETTINGS_PLUGIN_CLASS(klass);
Packit Service 5ffa24
Packit Service 5ffa24
    object_class->dispose = dispose;
Packit Service 5ffa24
Packit Service 5ffa24
    plugin_class->plugin_name         = "ifupdown";
Packit Service 5ffa24
    plugin_class->reload_connections  = reload_connections;
Packit Service 5ffa24
    plugin_class->get_unmanaged_specs = get_unmanaged_specs;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
/*****************************************************************************/
Packit Service 5ffa24
Packit Service 5ffa24
G_MODULE_EXPORT NMSettingsPlugin *
Packit Service 5ffa24
                nm_settings_plugin_factory(void)
Packit Service 5ffa24
{
Packit Service 5ffa24
    return g_object_new(NMS_TYPE_IFUPDOWN_PLUGIN, NULL);
Packit Service 5ffa24
}