mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-29 22:00:13 +01:00
We use clang-format for automatic formatting of our source files. Since clang-format is actively maintained software, the actual formatting depends on the used version of clang-format. That is unfortunate and painful, but really unavoidable unless clang-format would be strictly bug-compatible. So the version that we must use is from the current Fedora release, which is also tested by our gitlab-ci. Previously, we were using Fedora 34 with clang-tools-extra-12.0.1-1.fc34.x86_64. As Fedora 35 comes along, we need to update our formatting as Fedora 35 comes with version "13.0.0~rc1-1.fc35". An alternative would be to freeze on version 12, but that has different problems (like, it's cumbersome to rebuild clang 12 on Fedora 35 and it would be cumbersome for our developers which are on Fedora 35 to use a clang that they cannot easily install). The (differently painful) solution is to reformat from time to time, as we switch to a new Fedora (and thus clang) version. Usually we would expect that such a reformatting brings minor changes. But this time, the changes are huge. That is mentioned in the release notes [1] as Makes PointerAligment: Right working with AlignConsecutiveDeclarations. (Fixes https://llvm.org/PR27353) [1] https://releases.llvm.org/13.0.0/tools/clang/docs/ReleaseNotes.html#clang-format
669 lines
24 KiB
C
669 lines
24 KiB
C
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
/*
|
|
* Copyright (C) 2011 - 2015 Red Hat, Inc.
|
|
*/
|
|
|
|
#include "src/core/nm-default-daemon.h"
|
|
|
|
#include "nm-firewalld-manager.h"
|
|
|
|
#include "libnm-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 "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;
|
|
|
|
char *name_owner;
|
|
|
|
guint reloaded_id;
|
|
guint name_owner_changed_id;
|
|
|
|
bool dbus_inited : 1;
|
|
} NMFirewalldManagerPrivate;
|
|
|
|
struct _NMFirewalldManager {
|
|
GObject parent;
|
|
NMFirewalldManagerPrivate _priv;
|
|
};
|
|
|
|
struct _NMFirewalldManagerClass {
|
|
GObjectClass parent;
|
|
};
|
|
|
|
G_DEFINE_TYPE(NMFirewalldManager, nm_firewalld_manager, G_TYPE_OBJECT)
|
|
|
|
#define NM_FIREWALLD_MANAGER_GET_PRIVATE(self) \
|
|
_NM_GET_PRIVATE(self, NMFirewalldManager, NM_IS_FIREWALLD_MANAGER)
|
|
|
|
/*****************************************************************************/
|
|
|
|
NM_DEFINE_SINGLETON_GETTER(NMFirewalldManager, nm_firewalld_manager_get, NM_TYPE_FIREWALLD_MANAGER);
|
|
|
|
/*****************************************************************************/
|
|
|
|
typedef enum {
|
|
OPS_TYPE_ADD = 1,
|
|
OPS_TYPE_CHANGE,
|
|
OPS_TYPE_REMOVE,
|
|
} OpsType;
|
|
|
|
struct _NMFirewalldManagerCallId {
|
|
CList lst;
|
|
|
|
NMFirewalldManager *self;
|
|
|
|
char *iface;
|
|
|
|
NMFirewalldManagerAddRemoveCallback 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 "firewalld"
|
|
#define _NMLOG(level, call_id, ...) \
|
|
G_STMT_START \
|
|
{ \
|
|
if (nm_logging_enabled((level), (_NMLOG_DOMAIN))) { \
|
|
NMFirewalldManagerCallId *_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 void
|
|
_signal_emit_state_changed(NMFirewalldManager *self, NMFirewalldManagerStateChangedType signal_type)
|
|
{
|
|
g_signal_emit(self, signals[STATE_CHANGED], 0, (int) signal_type);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
static gboolean
|
|
_get_running(NMFirewalldManagerPrivate *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->name_owner || (priv->dbus_connection && !priv->dbus_inited);
|
|
}
|
|
|
|
gboolean
|
|
nm_firewalld_manager_get_running(NMFirewalldManager *self)
|
|
{
|
|
g_return_val_if_fail(NM_IS_FIREWALLD_MANAGER(self), FALSE);
|
|
|
|
return _get_running(NM_FIREWALLD_MANAGER_GET_PRIVATE(self));
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
static NMFirewalldManagerCallId *
|
|
_cb_info_create(NMFirewalldManager *self,
|
|
OpsType ops_type,
|
|
const char *iface,
|
|
const char *zone,
|
|
NMFirewalldManagerAddRemoveCallback callback,
|
|
gpointer user_data)
|
|
{
|
|
NMFirewalldManagerPrivate *priv = NM_FIREWALLD_MANAGER_GET_PRIVATE(self);
|
|
NMFirewalldManagerCallId *call_id;
|
|
|
|
call_id = g_slice_new0(NMFirewalldManagerCallId);
|
|
|
|
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(NMFirewalldManagerCallId *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)
|
|
{
|
|
NMFirewalldManager *self;
|
|
NMFirewalldManagerCallId *call_id = user_data;
|
|
|
|
nm_assert(call_id);
|
|
nm_assert(NM_IS_FIREWALLD_MANAGER(call_id->self));
|
|
nm_assert(call_id->is_idle);
|
|
nm_assert(c_list_contains(&NM_FIREWALLD_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(NMFirewalldManager *self, NMFirewalldManagerCallId *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)
|
|
{
|
|
NMFirewalldManager *self;
|
|
NMFirewalldManagerCallId *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_FIREWALLD_MANAGER(call_id->self));
|
|
nm_assert(!call_id->is_idle);
|
|
nm_assert(c_list_contains(&NM_FIREWALLD_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(NMFirewalldManager *self, NMFirewalldManagerCallId *call_id)
|
|
{
|
|
NMFirewalldManagerPrivate *priv = NM_FIREWALLD_MANAGER_GET_PRIVATE(self);
|
|
const char *dbus_method = NULL;
|
|
GVariant *arg;
|
|
|
|
nm_assert(call_id);
|
|
nm_assert(priv->name_owner);
|
|
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 = "changeZoneOfInterface";
|
|
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,
|
|
priv->name_owner,
|
|
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 NMFirewalldManagerCallId *
|
|
_start_request(NMFirewalldManager *self,
|
|
OpsType ops_type,
|
|
const char *iface,
|
|
const char *zone,
|
|
NMFirewalldManagerAddRemoveCallback callback,
|
|
gpointer user_data)
|
|
{
|
|
NMFirewalldManagerPrivate *priv;
|
|
NMFirewalldManagerCallId *call_id;
|
|
|
|
g_return_val_if_fail(NM_IS_FIREWALLD_MANAGER(self), NULL);
|
|
g_return_val_if_fail(iface && *iface, NULL);
|
|
|
|
priv = NM_FIREWALLD_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->name_owner ? " (waiting to initialize)" : ""));
|
|
|
|
if (!call_id->is_idle) {
|
|
if (priv->name_owner)
|
|
_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;
|
|
}
|
|
|
|
NMFirewalldManagerCallId *
|
|
nm_firewalld_manager_add_or_change_zone(NMFirewalldManager *self,
|
|
const char *iface,
|
|
const char *zone,
|
|
gboolean add, /* TRUE == add, FALSE == change */
|
|
NMFirewalldManagerAddRemoveCallback callback,
|
|
gpointer user_data)
|
|
{
|
|
return _start_request(self,
|
|
add ? OPS_TYPE_ADD : OPS_TYPE_CHANGE,
|
|
iface,
|
|
zone,
|
|
callback,
|
|
user_data);
|
|
}
|
|
|
|
NMFirewalldManagerCallId *
|
|
nm_firewalld_manager_remove_from_zone(NMFirewalldManager *self,
|
|
const char *iface,
|
|
const char *zone,
|
|
NMFirewalldManagerAddRemoveCallback callback,
|
|
gpointer user_data)
|
|
{
|
|
return _start_request(self, OPS_TYPE_REMOVE, iface, zone, callback, user_data);
|
|
}
|
|
|
|
void
|
|
nm_firewalld_manager_cancel_call(NMFirewalldManagerCallId *call_id)
|
|
{
|
|
NMFirewalldManager *self;
|
|
NMFirewalldManagerPrivate *priv;
|
|
gs_free_error GError *error = NULL;
|
|
|
|
g_return_if_fail(call_id);
|
|
g_return_if_fail(NM_IS_FIREWALLD_MANAGER(call_id->self));
|
|
g_return_if_fail(!c_list_is_empty(&call_id->lst));
|
|
|
|
self = call_id->self;
|
|
priv = NM_FIREWALLD_MANAGER_GET_PRIVATE(self);
|
|
|
|
nm_assert(c_list_contains(&priv->pending_calls, &call_id->lst));
|
|
|
|
nm_utils_error_set_cancelled(&error, FALSE, "NMFirewalldManager");
|
|
|
|
_LOGD(call_id, "complete: cancel (%s)", error->message);
|
|
|
|
_cb_info_complete(call_id, error);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
static void
|
|
name_owner_changed(NMFirewalldManager *self, const char *owner)
|
|
{
|
|
_nm_unused gs_unref_object NMFirewalldManager *self_keep_alive = g_object_ref(self);
|
|
NMFirewalldManagerPrivate *priv = NM_FIREWALLD_MANAGER_GET_PRIVATE(self);
|
|
gboolean was_running;
|
|
gboolean now_running;
|
|
gboolean just_initied;
|
|
gboolean name_owner_changed;
|
|
|
|
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;
|
|
name_owner_changed = nm_strdup_reset(&priv->name_owner, owner);
|
|
|
|
now_running = _get_running(priv);
|
|
|
|
if (just_initied) {
|
|
NMFirewalldManagerCallId *call_id_safe;
|
|
NMFirewalldManagerCallId *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->name_owner) {
|
|
_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 (just_initied)
|
|
_signal_emit_state_changed(self, NM_FIREWALLD_MANAGER_STATE_CHANGED_TYPE_INITIALIZED);
|
|
else if (was_running != now_running || name_owner_changed)
|
|
_signal_emit_state_changed(self,
|
|
NM_FIREWALLD_MANAGER_STATE_CHANGED_TYPE_NAME_OWNER_CHANGED);
|
|
}
|
|
|
|
static void
|
|
reloaded_cb(GDBusConnection *connection,
|
|
const char *sender_name,
|
|
const char *object_path,
|
|
const char *interface_name,
|
|
const char *signal_name,
|
|
GVariant *parameters,
|
|
gpointer user_data)
|
|
{
|
|
NMFirewalldManager *self = user_data;
|
|
NMFirewalldManagerPrivate *priv = NM_FIREWALLD_MANAGER_GET_PRIVATE(self);
|
|
|
|
if (!nm_streq0(sender_name, priv->name_owner))
|
|
return;
|
|
|
|
_LOGT(NULL, "reloaded signal received");
|
|
_signal_emit_state_changed(self, NM_FIREWALLD_MANAGER_STATE_CHANGED_TYPE_RELOADED);
|
|
}
|
|
|
|
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)
|
|
{
|
|
NMFirewalldManager *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)
|
|
{
|
|
NMFirewalldManager *self;
|
|
NMFirewalldManagerPrivate *priv;
|
|
|
|
if (nm_utils_error_is_cancelled(error))
|
|
return;
|
|
|
|
self = user_data;
|
|
priv = NM_FIREWALLD_MANAGER_GET_PRIVATE(self);
|
|
|
|
g_clear_object(&priv->get_name_owner_cancellable);
|
|
|
|
name_owner_changed(self, name_owner);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
static void
|
|
nm_firewalld_manager_init(NMFirewalldManager *self)
|
|
{
|
|
NMFirewalldManagerPrivate *priv = NM_FIREWALLD_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->reloaded_id = g_dbus_connection_signal_subscribe(priv->dbus_connection,
|
|
FIREWALL_DBUS_SERVICE,
|
|
FIREWALL_DBUS_INTERFACE,
|
|
"Reloaded",
|
|
FIREWALL_DBUS_PATH,
|
|
NULL,
|
|
G_DBUS_SIGNAL_FLAGS_NONE,
|
|
reloaded_cb,
|
|
self,
|
|
NULL);
|
|
|
|
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)
|
|
{
|
|
NMFirewalldManager *self = NM_FIREWALLD_MANAGER(object);
|
|
NMFirewalldManagerPrivate *priv = NM_FIREWALLD_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->reloaded_id);
|
|
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_firewalld_manager_parent_class)->dispose(object);
|
|
|
|
g_clear_object(&priv->dbus_connection);
|
|
}
|
|
|
|
static void
|
|
nm_firewalld_manager_class_init(NMFirewalldManagerClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
|
|
|
object_class->dispose = dispose;
|
|
|
|
signals[STATE_CHANGED] = g_signal_new(NM_FIREWALLD_MANAGER_STATE_CHANGED,
|
|
G_OBJECT_CLASS_TYPE(object_class),
|
|
G_SIGNAL_RUN_FIRST,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
g_cclosure_marshal_VOID__INT,
|
|
G_TYPE_NONE,
|
|
1,
|
|
G_TYPE_INT /* signal-type */);
|
|
}
|