mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-07 10:10:18 +01:00
Currently "src/" mostly contains the source code of the daemon. I say mostly, because that is not true, there are also the device, settings, wwan, ppp plugins, the initrd generator, the pppd and dhcp helper, and probably more. Also we have source code under libnm-core/, libnm/, clients/, and shared/ directories. That is all confusing. We should have one "src" directory, that contains subdirectories. Those subdirectories should contain individual parts (libraries or applications), that possibly have dependencies on other subdirectories. There should be a flat hierarchy of directories under src/, which contains individual modules. As the name "src/" is already taken, that prevents any sensible restructuring of the code. As a first step, move "src/" to "src/core/". This gives space to reorganize the code better by moving individual components into "src/". For inspiration, look at systemd's "src/" directory. https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/743
623 lines
22 KiB
C
623 lines
22 KiB
C
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
/*
|
|
* Copyright (C) 2011 - 2015 Red Hat, Inc.
|
|
*/
|
|
|
|
#include "nm-default.h"
|
|
|
|
#include "nm-firewall-manager.h"
|
|
|
|
#include "nm-glib-aux/nm-dbus-aux.h"
|
|
#include "c-list/src/c-list.h"
|
|
|
|
#include "NetworkManagerUtils.h"
|
|
#include "nm-dbus-manager.h"
|
|
|
|
#define FIREWALL_DBUS_SERVICE "org.fedoraproject.FirewallD1"
|
|
#define FIREWALL_DBUS_PATH "/org/fedoraproject/FirewallD1"
|
|
#define FIREWALL_DBUS_INTERFACE_ZONE "org.fedoraproject.FirewallD1.zone"
|
|
|
|
/*****************************************************************************/
|
|
|
|
enum { STATE_CHANGED, LAST_SIGNAL };
|
|
|
|
static guint signals[LAST_SIGNAL] = {0};
|
|
|
|
typedef struct {
|
|
GDBusConnection *dbus_connection;
|
|
|
|
GCancellable *get_name_owner_cancellable;
|
|
|
|
CList pending_calls;
|
|
|
|
guint name_owner_changed_id;
|
|
|
|
bool dbus_inited : 1;
|
|
bool running : 1;
|
|
} NMFirewallManagerPrivate;
|
|
|
|
struct _NMFirewallManager {
|
|
GObject parent;
|
|
NMFirewallManagerPrivate _priv;
|
|
};
|
|
|
|
struct _NMFirewallManagerClass {
|
|
GObjectClass parent;
|
|
};
|
|
|
|
G_DEFINE_TYPE(NMFirewallManager, nm_firewall_manager, G_TYPE_OBJECT)
|
|
|
|
#define NM_FIREWALL_MANAGER_GET_PRIVATE(self) \
|
|
_NM_GET_PRIVATE(self, NMFirewallManager, NM_IS_FIREWALL_MANAGER)
|
|
|
|
/*****************************************************************************/
|
|
|
|
NM_DEFINE_SINGLETON_GETTER(NMFirewallManager, nm_firewall_manager_get, NM_TYPE_FIREWALL_MANAGER);
|
|
|
|
/*****************************************************************************/
|
|
|
|
typedef enum {
|
|
OPS_TYPE_ADD = 1,
|
|
OPS_TYPE_CHANGE,
|
|
OPS_TYPE_REMOVE,
|
|
} OpsType;
|
|
|
|
struct _NMFirewallManagerCallId {
|
|
CList lst;
|
|
|
|
NMFirewallManager *self;
|
|
|
|
char *iface;
|
|
|
|
NMFirewallManagerAddRemoveCallback callback;
|
|
gpointer user_data;
|
|
|
|
union {
|
|
struct {
|
|
GCancellable *cancellable;
|
|
GVariant * arg;
|
|
} dbus;
|
|
struct {
|
|
guint id;
|
|
} idle;
|
|
};
|
|
|
|
OpsType ops_type;
|
|
|
|
bool is_idle : 1;
|
|
};
|
|
|
|
/*****************************************************************************/
|
|
|
|
static const char *
|
|
_ops_type_to_string(OpsType ops_type)
|
|
{
|
|
switch (ops_type) {
|
|
case OPS_TYPE_ADD:
|
|
return "add";
|
|
case OPS_TYPE_REMOVE:
|
|
return "remove";
|
|
case OPS_TYPE_CHANGE:
|
|
return "change";
|
|
}
|
|
nm_assert_not_reached();
|
|
return NULL;
|
|
}
|
|
|
|
#define _NMLOG_DOMAIN LOGD_FIREWALL
|
|
#define _NMLOG_PREFIX_NAME "firewall"
|
|
#define _NMLOG(level, call_id, ...) \
|
|
G_STMT_START \
|
|
{ \
|
|
if (nm_logging_enabled((level), (_NMLOG_DOMAIN))) { \
|
|
NMFirewallManagerCallId *_call_id = (call_id); \
|
|
char _prefix_name[30]; \
|
|
char _prefix_info[100]; \
|
|
\
|
|
_nm_log((level), \
|
|
(_NMLOG_DOMAIN), \
|
|
0, \
|
|
NULL, \
|
|
NULL, \
|
|
"%s: %s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
|
|
(self) != singleton_instance ? ({ \
|
|
g_snprintf(_prefix_name, \
|
|
sizeof(_prefix_name), \
|
|
"%s[" NM_HASH_OBFUSCATE_PTR_FMT "]", \
|
|
""_NMLOG_PREFIX_NAME, \
|
|
NM_HASH_OBFUSCATE_PTR(self)); \
|
|
_prefix_name; \
|
|
}) \
|
|
: _NMLOG_PREFIX_NAME, \
|
|
_call_id ? ({ \
|
|
g_snprintf(_prefix_info, \
|
|
sizeof(_prefix_info), \
|
|
"[" NM_HASH_OBFUSCATE_PTR_FMT ",%s%s:%s%s%s]: ", \
|
|
NM_HASH_OBFUSCATE_PTR(_call_id), \
|
|
_ops_type_to_string(_call_id->ops_type), \
|
|
_call_id->is_idle ? "*" : "", \
|
|
NM_PRINT_FMT_QUOTE_STRING(_call_id->iface)); \
|
|
_prefix_info; \
|
|
}) \
|
|
: "" _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
|
|
} \
|
|
} \
|
|
G_STMT_END
|
|
|
|
/*****************************************************************************/
|
|
|
|
static gboolean
|
|
_get_running(NMFirewallManagerPrivate *priv)
|
|
{
|
|
/* when starting, we need to asynchronously check whether there is
|
|
* a name owner. During that time we optimistically assume that the
|
|
* service is indeed running. That is the time when we queue the
|
|
* requests, and they will be started once the get-name-owner call
|
|
* returns. */
|
|
return priv->running || (priv->dbus_connection && !priv->dbus_inited);
|
|
}
|
|
|
|
gboolean
|
|
nm_firewall_manager_get_running(NMFirewallManager *self)
|
|
{
|
|
g_return_val_if_fail(NM_IS_FIREWALL_MANAGER(self), FALSE);
|
|
|
|
return _get_running(NM_FIREWALL_MANAGER_GET_PRIVATE(self));
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
static NMFirewallManagerCallId *
|
|
_cb_info_create(NMFirewallManager * self,
|
|
OpsType ops_type,
|
|
const char * iface,
|
|
const char * zone,
|
|
NMFirewallManagerAddRemoveCallback callback,
|
|
gpointer user_data)
|
|
{
|
|
NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE(self);
|
|
NMFirewallManagerCallId * call_id;
|
|
|
|
call_id = g_slice_new0(NMFirewallManagerCallId);
|
|
|
|
call_id->self = g_object_ref(self);
|
|
call_id->ops_type = ops_type;
|
|
call_id->iface = g_strdup(iface);
|
|
call_id->callback = callback;
|
|
call_id->user_data = user_data;
|
|
|
|
if (_get_running(priv)) {
|
|
call_id->is_idle = FALSE;
|
|
call_id->dbus.arg = g_variant_new("(ss)", zone ?: "", iface);
|
|
} else
|
|
call_id->is_idle = TRUE;
|
|
|
|
c_list_link_tail(&priv->pending_calls, &call_id->lst);
|
|
|
|
return call_id;
|
|
}
|
|
|
|
static void
|
|
_cb_info_complete(NMFirewallManagerCallId *call_id, GError *error)
|
|
{
|
|
c_list_unlink(&call_id->lst);
|
|
|
|
if (call_id->callback)
|
|
call_id->callback(call_id->self, call_id, error, call_id->user_data);
|
|
|
|
if (call_id->is_idle)
|
|
nm_clear_g_source(&call_id->idle.id);
|
|
else {
|
|
nm_g_variant_unref(call_id->dbus.arg);
|
|
nm_clear_g_cancellable(&call_id->dbus.cancellable);
|
|
}
|
|
g_free(call_id->iface);
|
|
g_object_unref(call_id->self);
|
|
nm_g_slice_free(call_id);
|
|
}
|
|
|
|
static gboolean
|
|
_handle_idle_cb(gpointer user_data)
|
|
{
|
|
NMFirewallManager * self;
|
|
NMFirewallManagerCallId *call_id = user_data;
|
|
|
|
nm_assert(call_id);
|
|
nm_assert(NM_IS_FIREWALL_MANAGER(call_id->self));
|
|
nm_assert(call_id->is_idle);
|
|
nm_assert(c_list_contains(&NM_FIREWALL_MANAGER_GET_PRIVATE(call_id->self)->pending_calls,
|
|
&call_id->lst));
|
|
|
|
self = call_id->self;
|
|
|
|
_LOGD(call_id, "complete: fake success");
|
|
|
|
call_id->idle.id = 0;
|
|
|
|
_cb_info_complete(call_id, NULL);
|
|
return G_SOURCE_REMOVE;
|
|
}
|
|
|
|
static gboolean
|
|
_handle_idle_start(NMFirewallManager *self, NMFirewallManagerCallId *call_id)
|
|
{
|
|
if (!call_id->callback) {
|
|
/* if the user did not provide a callback and firewalld is not running,
|
|
* there is no point in scheduling an idle-request to fake success. Just
|
|
* return right away. */
|
|
_LOGD(call_id, "complete: drop request simulating success");
|
|
_cb_info_complete(call_id, NULL);
|
|
return FALSE;
|
|
}
|
|
call_id->idle.id = g_idle_add(_handle_idle_cb, call_id);
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
_handle_dbus_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
|
{
|
|
NMFirewallManager * self;
|
|
NMFirewallManagerCallId *call_id;
|
|
gs_free_error GError *error = NULL;
|
|
gs_unref_variant GVariant *ret = NULL;
|
|
|
|
ret = g_dbus_connection_call_finish(G_DBUS_CONNECTION(source), result, &error);
|
|
|
|
if (!ret && nm_utils_error_is_cancelled(error))
|
|
return;
|
|
|
|
call_id = user_data;
|
|
|
|
nm_assert(call_id);
|
|
nm_assert(NM_IS_FIREWALL_MANAGER(call_id->self));
|
|
nm_assert(!call_id->is_idle);
|
|
nm_assert(c_list_contains(&NM_FIREWALL_MANAGER_GET_PRIVATE(call_id->self)->pending_calls,
|
|
&call_id->lst));
|
|
|
|
self = call_id->self;
|
|
|
|
if (error) {
|
|
const char *non_error = NULL;
|
|
|
|
g_dbus_error_strip_remote_error(error);
|
|
|
|
switch (call_id->ops_type) {
|
|
case OPS_TYPE_ADD:
|
|
case OPS_TYPE_CHANGE:
|
|
non_error = "ZONE_ALREADY_SET";
|
|
break;
|
|
case OPS_TYPE_REMOVE:
|
|
non_error = "UNKNOWN_INTERFACE";
|
|
break;
|
|
}
|
|
if (error->message && non_error && g_str_has_prefix(error->message, non_error)
|
|
&& NM_IN_SET(error->message[strlen(non_error)], '\0', ':')) {
|
|
_LOGD(call_id, "complete: request failed with a non-error (%s)", error->message);
|
|
|
|
/* The operation failed with an error reason that we don't want
|
|
* to propagate. Instead, signal success. */
|
|
g_clear_error(&error);
|
|
} else
|
|
_LOGW(call_id, "complete: request failed (%s)", error->message);
|
|
} else
|
|
_LOGD(call_id, "complete: success");
|
|
|
|
g_clear_object(&call_id->dbus.cancellable);
|
|
|
|
_cb_info_complete(call_id, error);
|
|
}
|
|
|
|
static void
|
|
_handle_dbus_start(NMFirewallManager *self, NMFirewallManagerCallId *call_id)
|
|
{
|
|
NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE(self);
|
|
const char * dbus_method = NULL;
|
|
GVariant * arg;
|
|
|
|
nm_assert(call_id);
|
|
nm_assert(priv->running);
|
|
nm_assert(!call_id->is_idle);
|
|
nm_assert(c_list_contains(&priv->pending_calls, &call_id->lst));
|
|
|
|
switch (call_id->ops_type) {
|
|
case OPS_TYPE_ADD:
|
|
dbus_method = "addInterface";
|
|
break;
|
|
case OPS_TYPE_CHANGE:
|
|
dbus_method = "changeZone";
|
|
break;
|
|
case OPS_TYPE_REMOVE:
|
|
dbus_method = "removeInterface";
|
|
break;
|
|
}
|
|
nm_assert(dbus_method);
|
|
|
|
arg = g_steal_pointer(&call_id->dbus.arg);
|
|
|
|
nm_assert(arg && g_variant_is_floating(arg));
|
|
|
|
nm_assert(!call_id->dbus.cancellable);
|
|
|
|
call_id->dbus.cancellable = g_cancellable_new();
|
|
|
|
g_dbus_connection_call(priv->dbus_connection,
|
|
FIREWALL_DBUS_SERVICE,
|
|
FIREWALL_DBUS_PATH,
|
|
FIREWALL_DBUS_INTERFACE_ZONE,
|
|
dbus_method,
|
|
arg,
|
|
NULL,
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
10000,
|
|
call_id->dbus.cancellable,
|
|
_handle_dbus_cb,
|
|
call_id);
|
|
}
|
|
|
|
static NMFirewallManagerCallId *
|
|
_start_request(NMFirewallManager * self,
|
|
OpsType ops_type,
|
|
const char * iface,
|
|
const char * zone,
|
|
NMFirewallManagerAddRemoveCallback callback,
|
|
gpointer user_data)
|
|
{
|
|
NMFirewallManagerPrivate *priv;
|
|
NMFirewallManagerCallId * call_id;
|
|
|
|
g_return_val_if_fail(NM_IS_FIREWALL_MANAGER(self), NULL);
|
|
g_return_val_if_fail(iface && *iface, NULL);
|
|
|
|
priv = NM_FIREWALL_MANAGER_GET_PRIVATE(self);
|
|
|
|
call_id = _cb_info_create(self, ops_type, iface, zone, callback, user_data);
|
|
|
|
_LOGD(call_id,
|
|
"firewall zone %s %s:%s%s%s%s",
|
|
_ops_type_to_string(call_id->ops_type),
|
|
iface,
|
|
NM_PRINT_FMT_QUOTED(zone, "\"", zone, "\"", "default"),
|
|
call_id->is_idle ? " (not running, simulate success)"
|
|
: (!priv->running ? " (waiting to initialize)" : ""));
|
|
|
|
if (!call_id->is_idle) {
|
|
if (priv->running)
|
|
_handle_dbus_start(self, call_id);
|
|
if (!call_id->callback) {
|
|
/* if the user did not provide a callback, the call_id is useless.
|
|
* Especially, the user cannot use the call-id to cancel the request,
|
|
* because he cannot know whether the request is still pending.
|
|
*
|
|
* Hence, returning %NULL doesn't mean that the request could not be started
|
|
* (this function never fails and always starts a request). */
|
|
return NULL;
|
|
}
|
|
} else {
|
|
if (!_handle_idle_start(self, call_id)) {
|
|
/* if the user did not provide a callback and firewalld is not running,
|
|
* there is no point in scheduling an idle-request to fake success. Just
|
|
* return right away. */
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return call_id;
|
|
}
|
|
|
|
NMFirewallManagerCallId *
|
|
nm_firewall_manager_add_or_change_zone(NMFirewallManager *self,
|
|
const char * iface,
|
|
const char * zone,
|
|
gboolean add, /* TRUE == add, FALSE == change */
|
|
NMFirewallManagerAddRemoveCallback callback,
|
|
gpointer user_data)
|
|
{
|
|
return _start_request(self,
|
|
add ? OPS_TYPE_ADD : OPS_TYPE_CHANGE,
|
|
iface,
|
|
zone,
|
|
callback,
|
|
user_data);
|
|
}
|
|
|
|
NMFirewallManagerCallId *
|
|
nm_firewall_manager_remove_from_zone(NMFirewallManager * self,
|
|
const char * iface,
|
|
const char * zone,
|
|
NMFirewallManagerAddRemoveCallback callback,
|
|
gpointer user_data)
|
|
{
|
|
return _start_request(self, OPS_TYPE_REMOVE, iface, zone, callback, user_data);
|
|
}
|
|
|
|
void
|
|
nm_firewall_manager_cancel_call(NMFirewallManagerCallId *call_id)
|
|
{
|
|
NMFirewallManager * self;
|
|
NMFirewallManagerPrivate *priv;
|
|
gs_free_error GError *error = NULL;
|
|
|
|
g_return_if_fail(call_id);
|
|
g_return_if_fail(NM_IS_FIREWALL_MANAGER(call_id->self));
|
|
g_return_if_fail(!c_list_is_empty(&call_id->lst));
|
|
|
|
self = call_id->self;
|
|
priv = NM_FIREWALL_MANAGER_GET_PRIVATE(self);
|
|
|
|
nm_assert(c_list_contains(&priv->pending_calls, &call_id->lst));
|
|
|
|
nm_utils_error_set_cancelled(&error, FALSE, "NMFirewallManager");
|
|
|
|
_LOGD(call_id, "complete: cancel (%s)", error->message);
|
|
|
|
_cb_info_complete(call_id, error);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
static void
|
|
name_owner_changed(NMFirewallManager *self, const char *owner)
|
|
{
|
|
_nm_unused gs_unref_object NMFirewallManager *self_keep_alive = g_object_ref(self);
|
|
NMFirewallManagerPrivate * priv = NM_FIREWALL_MANAGER_GET_PRIVATE(self);
|
|
gboolean was_running;
|
|
gboolean now_running;
|
|
gboolean just_initied;
|
|
|
|
owner = nm_str_not_empty(owner);
|
|
|
|
if (!owner)
|
|
_LOGT(NULL, "D-Bus name for firewalld has no owner (firewall stopped)");
|
|
else
|
|
_LOGT(NULL, "D-Bus name for firewalld has owner %s (firewall started)", owner);
|
|
|
|
was_running = _get_running(priv);
|
|
just_initied = !priv->dbus_inited;
|
|
|
|
priv->dbus_inited = TRUE;
|
|
priv->running = !!owner;
|
|
|
|
now_running = _get_running(priv);
|
|
|
|
if (just_initied) {
|
|
NMFirewallManagerCallId *call_id_safe;
|
|
NMFirewallManagerCallId *call_id;
|
|
|
|
/* We kick of the requests that we have pending. Note that this is
|
|
* entirely asynchronous and also we don't invoke any callbacks for
|
|
* the user.
|
|
* Even _handle_idle_start() just schedules an idle handler. That is,
|
|
* because we don't want to callback to the user before emitting the
|
|
* DISCONNECTED signal below. Also, emitting callbacks means the user
|
|
* can call back to modify the list of pending-calls and we'd have
|
|
* to handle reentrancy. */
|
|
c_list_for_each_entry_safe (call_id, call_id_safe, &priv->pending_calls, lst) {
|
|
nm_assert(!call_id->is_idle);
|
|
nm_assert(call_id->dbus.arg);
|
|
|
|
if (priv->running) {
|
|
_LOGD(call_id, "initalizing: make D-Bus call");
|
|
_handle_dbus_start(self, call_id);
|
|
} else {
|
|
/* we don't want to invoke callbacks to the user right away. That is because
|
|
* the user might schedule/cancel more calls, which messes up the order.
|
|
*
|
|
* Instead, convert the pending calls to idle requests... */
|
|
nm_clear_pointer(&call_id->dbus.arg, g_variant_unref);
|
|
call_id->is_idle = TRUE;
|
|
_LOGD(call_id, "initializing: fake success on idle");
|
|
_handle_idle_start(self, call_id);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (was_running != now_running)
|
|
g_signal_emit(self, signals[STATE_CHANGED], 0, FALSE);
|
|
}
|
|
|
|
static void
|
|
name_owner_changed_cb(GDBusConnection *connection,
|
|
const char * sender_name,
|
|
const char * object_path,
|
|
const char * interface_name,
|
|
const char * signal_name,
|
|
GVariant * parameters,
|
|
gpointer user_data)
|
|
{
|
|
NMFirewallManager *self = user_data;
|
|
const char * new_owner;
|
|
|
|
if (!g_variant_is_of_type(parameters, G_VARIANT_TYPE("(sss)")))
|
|
return;
|
|
|
|
g_variant_get(parameters, "(&s&s&s)", NULL, NULL, &new_owner);
|
|
|
|
name_owner_changed(self, new_owner);
|
|
}
|
|
|
|
static void
|
|
get_name_owner_cb(const char *name_owner, GError *error, gpointer user_data)
|
|
{
|
|
NMFirewallManager * self;
|
|
NMFirewallManagerPrivate *priv;
|
|
|
|
if (!name_owner && g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
return;
|
|
|
|
self = user_data;
|
|
priv = NM_FIREWALL_MANAGER_GET_PRIVATE(self);
|
|
|
|
g_clear_object(&priv->get_name_owner_cancellable);
|
|
|
|
name_owner_changed(self, name_owner);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
static void
|
|
nm_firewall_manager_init(NMFirewallManager *self)
|
|
{
|
|
NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE(self);
|
|
|
|
c_list_init(&priv->pending_calls);
|
|
|
|
priv->dbus_connection = nm_g_object_ref(NM_MAIN_DBUS_CONNECTION_GET);
|
|
|
|
if (!priv->dbus_connection) {
|
|
_LOGD(NULL, "no D-Bus connection");
|
|
return;
|
|
}
|
|
|
|
priv->name_owner_changed_id =
|
|
nm_dbus_connection_signal_subscribe_name_owner_changed(priv->dbus_connection,
|
|
FIREWALL_DBUS_SERVICE,
|
|
name_owner_changed_cb,
|
|
self,
|
|
NULL);
|
|
|
|
priv->get_name_owner_cancellable = g_cancellable_new();
|
|
nm_dbus_connection_call_get_name_owner(priv->dbus_connection,
|
|
FIREWALL_DBUS_SERVICE,
|
|
-1,
|
|
priv->get_name_owner_cancellable,
|
|
get_name_owner_cb,
|
|
self);
|
|
}
|
|
|
|
static void
|
|
dispose(GObject *object)
|
|
{
|
|
NMFirewallManager * self = NM_FIREWALL_MANAGER(object);
|
|
NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE(self);
|
|
|
|
/* as every pending operation takes a reference to the manager,
|
|
* we don't expect pending operations at this point. */
|
|
nm_assert(c_list_is_empty(&priv->pending_calls));
|
|
|
|
nm_clear_g_dbus_connection_signal(priv->dbus_connection, &priv->name_owner_changed_id);
|
|
|
|
nm_clear_g_cancellable(&priv->get_name_owner_cancellable);
|
|
|
|
G_OBJECT_CLASS(nm_firewall_manager_parent_class)->dispose(object);
|
|
|
|
g_clear_object(&priv->dbus_connection);
|
|
}
|
|
|
|
static void
|
|
nm_firewall_manager_class_init(NMFirewallManagerClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
|
|
|
object_class->dispose = dispose;
|
|
|
|
signals[STATE_CHANGED] = g_signal_new(NM_FIREWALL_MANAGER_STATE_CHANGED,
|
|
G_OBJECT_CLASS_TYPE(object_class),
|
|
G_SIGNAL_RUN_FIRST,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
g_cclosure_marshal_VOID__BOOLEAN,
|
|
G_TYPE_NONE,
|
|
1,
|
|
G_TYPE_BOOLEAN /* initialized_now */);
|
|
}
|