mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-05-09 08:18:03 +02:00
dns,dbus: merge branch 'th/systemd-resolved-dbus-activated'
https://github.com/NetworkManager/NetworkManager/pull/336
This commit is contained in:
commit
3a2e002a2e
7 changed files with 435 additions and 182 deletions
|
|
@ -347,13 +347,20 @@ gboolean
|
||||||
nm_dns_manager_has_systemd_resolved (NMDnsManager *self)
|
nm_dns_manager_has_systemd_resolved (NMDnsManager *self)
|
||||||
{
|
{
|
||||||
NMDnsManagerPrivate *priv;
|
NMDnsManagerPrivate *priv;
|
||||||
|
NMDnsSystemdResolved *plugin = NULL;
|
||||||
|
|
||||||
g_return_val_if_fail (NM_IS_DNS_MANAGER (self), FALSE);
|
g_return_val_if_fail (NM_IS_DNS_MANAGER (self), FALSE);
|
||||||
|
|
||||||
priv = NM_DNS_MANAGER_GET_PRIVATE (self);
|
priv = NM_DNS_MANAGER_GET_PRIVATE (self);
|
||||||
|
|
||||||
return priv->sd_resolve_plugin
|
if (priv->sd_resolve_plugin) {
|
||||||
|| NM_IS_DNS_SYSTEMD_RESOLVED (priv->plugin);
|
nm_assert (!NM_IS_DNS_SYSTEMD_RESOLVED (priv->plugin));
|
||||||
|
plugin = NM_DNS_SYSTEMD_RESOLVED (priv->sd_resolve_plugin);
|
||||||
|
} else if (NM_IS_DNS_SYSTEMD_RESOLVED (priv->plugin))
|
||||||
|
plugin = NM_DNS_SYSTEMD_RESOLVED (priv->plugin);
|
||||||
|
|
||||||
|
return plugin
|
||||||
|
&& nm_dns_systemd_resolved_is_running (plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
|
||||||
|
|
@ -42,9 +42,11 @@
|
||||||
#include "nm-setting-connection.h"
|
#include "nm-setting-connection.h"
|
||||||
#include "devices/nm-device.h"
|
#include "devices/nm-device.h"
|
||||||
#include "NetworkManagerUtils.h"
|
#include "NetworkManagerUtils.h"
|
||||||
|
#include "nm-dbus-compat.h"
|
||||||
|
|
||||||
#define SYSTEMD_RESOLVED_DBUS_SERVICE "org.freedesktop.resolve1"
|
#define SYSTEMD_RESOLVED_DBUS_SERVICE "org.freedesktop.resolve1"
|
||||||
#define SYSTEMD_RESOLVED_DBUS_PATH "/org/freedesktop/resolve1"
|
#define SYSTEMD_RESOLVED_MANAGER_IFACE "org.freedesktop.resolve1.Manager"
|
||||||
|
#define SYSTEMD_RESOLVED_DBUS_PATH "/org/freedesktop/resolve1"
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
@ -62,10 +64,14 @@ typedef struct {
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GDBusProxy *resolve;
|
GDBusConnection *dbus_connection;
|
||||||
GCancellable *init_cancellable;
|
GCancellable *cancellable;
|
||||||
GCancellable *update_cancellable;
|
|
||||||
CList request_queue_lst_head;
|
CList request_queue_lst_head;
|
||||||
|
guint name_owner_changed_id;
|
||||||
|
bool send_updates_warn_ratelimited:1;
|
||||||
|
bool try_start_blocked:1;
|
||||||
|
bool dbus_has_owner:1;
|
||||||
|
bool dbus_initied:1;
|
||||||
} NMDnsSystemdResolvedPrivate;
|
} NMDnsSystemdResolvedPrivate;
|
||||||
|
|
||||||
struct _NMDnsSystemdResolved {
|
struct _NMDnsSystemdResolved {
|
||||||
|
|
@ -121,16 +127,26 @@ _interface_config_free (InterfaceConfig *config)
|
||||||
static void
|
static void
|
||||||
call_done (GObject *source, GAsyncResult *r, gpointer user_data)
|
call_done (GObject *source, GAsyncResult *r, gpointer user_data)
|
||||||
{
|
{
|
||||||
GVariant *v;
|
gs_unref_variant GVariant *v = NULL;
|
||||||
gs_free_error GError *error = NULL;
|
gs_free_error GError *error = NULL;
|
||||||
NMDnsSystemdResolved *self = (NMDnsSystemdResolved *) user_data;
|
NMDnsSystemdResolved *self = (NMDnsSystemdResolved *) user_data;
|
||||||
|
NMDnsSystemdResolvedPrivate *priv;
|
||||||
|
|
||||||
|
v = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), r, &error);
|
||||||
|
if ( !v
|
||||||
|
&& g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||||
|
return;
|
||||||
|
|
||||||
|
priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE (self);
|
||||||
|
|
||||||
v = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), r, &error);
|
|
||||||
if (!v) {
|
if (!v) {
|
||||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
if (!priv->send_updates_warn_ratelimited) {
|
||||||
return;
|
priv->send_updates_warn_ratelimited = TRUE;
|
||||||
_LOGW ("Failed: %s", error->message);
|
_LOGW ("send-updates failed to update systemd-resolved: %s", error->message);
|
||||||
}
|
} else
|
||||||
|
_LOGD ("send-updates failed: %s", error->message);
|
||||||
|
} else
|
||||||
|
priv->send_updates_warn_ratelimited = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -174,12 +190,11 @@ static void
|
||||||
free_pending_updates (NMDnsSystemdResolved *self)
|
free_pending_updates (NMDnsSystemdResolved *self)
|
||||||
{
|
{
|
||||||
NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE (self);
|
NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE (self);
|
||||||
RequestItem *request_item, *request_item_safe;
|
RequestItem *request_item;
|
||||||
|
|
||||||
c_list_for_each_entry_safe (request_item,
|
while ((request_item = c_list_first_entry (&priv->request_queue_lst_head,
|
||||||
request_item_safe,
|
RequestItem,
|
||||||
&priv->request_queue_lst_head,
|
request_queue_lst)))
|
||||||
request_queue_lst)
|
|
||||||
_request_item_free (request_item);
|
_request_item_free (request_item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -266,27 +281,74 @@ static void
|
||||||
send_updates (NMDnsSystemdResolved *self)
|
send_updates (NMDnsSystemdResolved *self)
|
||||||
{
|
{
|
||||||
NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE (self);
|
NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE (self);
|
||||||
RequestItem *request_item, *request_item_safe;
|
RequestItem *request_item;
|
||||||
|
|
||||||
nm_clear_g_cancellable (&priv->update_cancellable);
|
if (c_list_is_empty (&priv->request_queue_lst_head)) {
|
||||||
|
/* nothing to do. */
|
||||||
if (!priv->resolve)
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
priv->update_cancellable = g_cancellable_new ();
|
if (!priv->dbus_initied) {
|
||||||
|
_LOGT ("send-updates: D-Bus connection not ready");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
c_list_for_each_entry_safe (request_item,
|
if (!priv->dbus_has_owner) {
|
||||||
request_item_safe,
|
if (priv->try_start_blocked) {
|
||||||
&priv->request_queue_lst_head,
|
/* we have no name owner and we already tried poking the service to
|
||||||
request_queue_lst) {
|
* autostart. */
|
||||||
g_dbus_proxy_call (priv->resolve,
|
_LOGT ("send-updates: no name owner");
|
||||||
request_item->operation,
|
return;
|
||||||
request_item->argument,
|
}
|
||||||
G_DBUS_CALL_FLAGS_NONE,
|
|
||||||
-1,
|
_LOGT ("send-updates: no name owner. Try start service...");
|
||||||
priv->update_cancellable,
|
priv->try_start_blocked = TRUE;
|
||||||
call_done,
|
|
||||||
self);
|
g_dbus_connection_call (priv->dbus_connection,
|
||||||
|
DBUS_SERVICE_DBUS,
|
||||||
|
DBUS_PATH_DBUS,
|
||||||
|
DBUS_INTERFACE_DBUS,
|
||||||
|
"StartServiceByName",
|
||||||
|
g_variant_new ("(su)", SYSTEMD_RESOLVED_DBUS_SERVICE, 0u),
|
||||||
|
G_VARIANT_TYPE ("(u)"),
|
||||||
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
-1,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_LOGT ("send-updates: start %lu requests",
|
||||||
|
c_list_length (&priv->request_queue_lst_head));
|
||||||
|
|
||||||
|
nm_clear_g_cancellable (&priv->cancellable);
|
||||||
|
|
||||||
|
priv->cancellable = g_cancellable_new ();
|
||||||
|
|
||||||
|
while ((request_item = c_list_first_entry (&priv->request_queue_lst_head,
|
||||||
|
RequestItem,
|
||||||
|
request_queue_lst))) {
|
||||||
|
/* Above we explicitly call "StartServiceByName" trying to avoid D-Bus activating systmd-resolved
|
||||||
|
* multiple times. There is still a race, were we might hit this line although actually
|
||||||
|
* the service just quit this very moment. In that case, we would try to D-Bus activate the
|
||||||
|
* service multiple times during each call (something we wanted to avoid).
|
||||||
|
*
|
||||||
|
* But this is hard to avoid, because we'd have to check the error failure to detect the reason
|
||||||
|
* and retry. The race is not critical, because at worst it results in logging a warning
|
||||||
|
* about failure to start systemd.resolved. */
|
||||||
|
g_dbus_connection_call (priv->dbus_connection,
|
||||||
|
SYSTEMD_RESOLVED_DBUS_SERVICE,
|
||||||
|
SYSTEMD_RESOLVED_DBUS_PATH,
|
||||||
|
SYSTEMD_RESOLVED_MANAGER_IFACE,
|
||||||
|
request_item->operation,
|
||||||
|
request_item->argument,
|
||||||
|
NULL,
|
||||||
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
-1,
|
||||||
|
priv->cancellable,
|
||||||
|
call_done,
|
||||||
|
self);
|
||||||
_request_item_free (request_item);
|
_request_item_free (request_item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -360,28 +422,100 @@ get_name (NMDnsPlugin *plugin)
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
resolved_proxy_created (GObject *source, GAsyncResult *r, gpointer user_data)
|
name_owner_changed (NMDnsSystemdResolved *self,
|
||||||
|
const char *owner)
|
||||||
{
|
{
|
||||||
NMDnsSystemdResolved *self = (NMDnsSystemdResolved *) user_data;
|
NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE (self);
|
||||||
NMDnsSystemdResolvedPrivate *priv;
|
|
||||||
gs_free_error GError *error = NULL;
|
|
||||||
GDBusProxy *resolve;
|
|
||||||
|
|
||||||
resolve = g_dbus_proxy_new_finish (r, &error);
|
owner = nm_str_not_empty (owner);
|
||||||
if ( !resolve
|
|
||||||
|
if (!owner)
|
||||||
|
_LOGT ("D-Bus name for systemd-resolved has no owner");
|
||||||
|
else
|
||||||
|
_LOGT ("D-Bus name for systemd-resolved has owner %s", owner);
|
||||||
|
|
||||||
|
priv->dbus_has_owner = !!owner;
|
||||||
|
if (owner)
|
||||||
|
priv->try_start_blocked = FALSE;
|
||||||
|
|
||||||
|
send_updates (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
NMDnsSystemdResolved *self = user_data;
|
||||||
|
NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE (self);
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (!priv->dbus_initied) {
|
||||||
|
/* There was a race and we got a NameOwnerChanged signal before GetNameOwner
|
||||||
|
* returns. */
|
||||||
|
priv->dbus_initied = TRUE;
|
||||||
|
nm_clear_g_cancellable (&priv->cancellable);
|
||||||
|
}
|
||||||
|
|
||||||
|
name_owner_changed (user_data, new_owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_name_owner_cb (GObject *source,
|
||||||
|
GAsyncResult *res,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
NMDnsSystemdResolved *self;
|
||||||
|
NMDnsSystemdResolvedPrivate *priv;
|
||||||
|
gs_unref_variant GVariant *ret = NULL;
|
||||||
|
gs_free_error GError *error = NULL;
|
||||||
|
const char *owner = NULL;
|
||||||
|
|
||||||
|
ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), res, &error);
|
||||||
|
if ( !ret
|
||||||
&& g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
&& g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE (self);
|
if (ret)
|
||||||
g_clear_object (&priv->init_cancellable);
|
g_variant_get (ret, "(&s)", &owner);
|
||||||
if (!resolve) {
|
|
||||||
_LOGW ("failed to connect to resolved via DBus: %s", error->message);
|
|
||||||
g_signal_emit_by_name (self, NM_DNS_PLUGIN_FAILED);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
priv->resolve = resolve;
|
self = user_data;
|
||||||
send_updates (self);
|
priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE (self);
|
||||||
|
|
||||||
|
g_clear_object (&priv->cancellable);
|
||||||
|
|
||||||
|
priv->dbus_initied = TRUE;
|
||||||
|
|
||||||
|
name_owner_changed (self, owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nm_dns_systemd_resolved_is_running (NMDnsSystemdResolved *self)
|
||||||
|
{
|
||||||
|
NMDnsSystemdResolvedPrivate *priv;
|
||||||
|
|
||||||
|
g_return_val_if_fail (NM_IS_DNS_SYSTEMD_RESOLVED (self), FALSE);
|
||||||
|
|
||||||
|
priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE (self);
|
||||||
|
|
||||||
|
return priv->dbus_initied
|
||||||
|
&& ( priv->dbus_has_owner
|
||||||
|
|| !priv->try_start_blocked);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
@ -393,17 +527,35 @@ nm_dns_systemd_resolved_init (NMDnsSystemdResolved *self)
|
||||||
|
|
||||||
c_list_init (&priv->request_queue_lst_head);
|
c_list_init (&priv->request_queue_lst_head);
|
||||||
|
|
||||||
priv->init_cancellable = g_cancellable_new ();
|
priv->dbus_connection = nm_g_object_ref (nm_dbus_manager_get_dbus_connection (nm_dbus_manager_get ()));
|
||||||
g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
|
if (!priv->dbus_connection) {
|
||||||
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
|
_LOGD ("no D-Bus connection");
|
||||||
G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
|
return;
|
||||||
NULL,
|
}
|
||||||
SYSTEMD_RESOLVED_DBUS_SERVICE,
|
|
||||||
SYSTEMD_RESOLVED_DBUS_PATH,
|
priv->name_owner_changed_id = g_dbus_connection_signal_subscribe (priv->dbus_connection,
|
||||||
SYSTEMD_RESOLVED_DBUS_SERVICE ".Manager",
|
DBUS_SERVICE_DBUS,
|
||||||
priv->init_cancellable,
|
DBUS_INTERFACE_DBUS,
|
||||||
resolved_proxy_created,
|
"NameOwnerChanged",
|
||||||
self);
|
DBUS_PATH_DBUS,
|
||||||
|
SYSTEMD_RESOLVED_DBUS_SERVICE,
|
||||||
|
G_DBUS_SIGNAL_FLAGS_NONE,
|
||||||
|
name_owner_changed_cb,
|
||||||
|
self,
|
||||||
|
NULL);
|
||||||
|
priv->cancellable = g_cancellable_new ();
|
||||||
|
g_dbus_connection_call (priv->dbus_connection,
|
||||||
|
DBUS_SERVICE_DBUS,
|
||||||
|
DBUS_PATH_DBUS,
|
||||||
|
DBUS_INTERFACE_DBUS,
|
||||||
|
"GetNameOwner",
|
||||||
|
g_variant_new ("(s)", SYSTEMD_RESOLVED_DBUS_SERVICE),
|
||||||
|
G_VARIANT_TYPE ("(s)"),
|
||||||
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
-1,
|
||||||
|
priv->cancellable,
|
||||||
|
get_name_owner_cb,
|
||||||
|
self);
|
||||||
}
|
}
|
||||||
|
|
||||||
NMDnsPlugin *
|
NMDnsPlugin *
|
||||||
|
|
@ -419,9 +571,15 @@ dispose (GObject *object)
|
||||||
NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE (self);
|
NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE (self);
|
||||||
|
|
||||||
free_pending_updates (self);
|
free_pending_updates (self);
|
||||||
g_clear_object (&priv->resolve);
|
|
||||||
nm_clear_g_cancellable (&priv->init_cancellable);
|
if (priv->name_owner_changed_id != 0) {
|
||||||
nm_clear_g_cancellable (&priv->update_cancellable);
|
g_dbus_connection_signal_unsubscribe (priv->dbus_connection,
|
||||||
|
nm_steal_int (&priv->name_owner_changed_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
nm_clear_g_cancellable (&priv->cancellable);
|
||||||
|
|
||||||
|
g_clear_object (&priv->dbus_connection);
|
||||||
|
|
||||||
G_OBJECT_CLASS (nm_dns_systemd_resolved_parent_class)->dispose (object);
|
G_OBJECT_CLASS (nm_dns_systemd_resolved_parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,4 +36,6 @@ GType nm_dns_systemd_resolved_get_type (void);
|
||||||
|
|
||||||
NMDnsPlugin *nm_dns_systemd_resolved_new (void);
|
NMDnsPlugin *nm_dns_systemd_resolved_new (void);
|
||||||
|
|
||||||
|
gboolean nm_dns_systemd_resolved_is_running (NMDnsSystemdResolved *self);
|
||||||
|
|
||||||
#endif /* __NETWORKMANAGER_DNS_SYSTEMD_RESOLVED_H__ */
|
#endif /* __NETWORKMANAGER_DNS_SYSTEMD_RESOLVED_H__ */
|
||||||
|
|
|
||||||
|
|
@ -173,9 +173,10 @@ _new_unix_process (GDBusMethodInvocation *context,
|
||||||
GDBusMessage *message)
|
GDBusMessage *message)
|
||||||
{
|
{
|
||||||
NMAuthSubject *self;
|
NMAuthSubject *self;
|
||||||
gboolean success = FALSE;
|
const char *dbus_sender = NULL;
|
||||||
gulong pid = 0, uid = 0;
|
gulong uid = 0;
|
||||||
gs_free char *dbus_sender = NULL;
|
gulong pid = 0;
|
||||||
|
gboolean success;
|
||||||
|
|
||||||
g_return_val_if_fail (context || (connection && message), NULL);
|
g_return_val_if_fail (context || (connection && message), NULL);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -840,7 +840,18 @@ nm_connectivity_check_start (NMConnectivity *self,
|
||||||
*
|
*
|
||||||
* Yes, this makes NMConnectivity singleton dependent on NMDnsManager singleton.
|
* Yes, this makes NMConnectivity singleton dependent on NMDnsManager singleton.
|
||||||
* Well, not really: it makes connectivity-check-start dependent on NMDnsManager
|
* Well, not really: it makes connectivity-check-start dependent on NMDnsManager
|
||||||
* which merely means, not to start a connectivity check, late during shutdown. */
|
* which merely means, not to start a connectivity check, late during shutdown.
|
||||||
|
*
|
||||||
|
* NMDnsSystemdResolved tries to D-Bus activate systemd-resolved only once,
|
||||||
|
* to not spam syslog with failures messages from dbus-daemon.
|
||||||
|
* Note that unless NMDnsSystemdResolved tried and failed to start systemd-resolved,
|
||||||
|
* it guesses that systemd-resolved is activatable and returns %TRUE here. That
|
||||||
|
* means, while NMDnsSystemdResolved would not try to D-Bus activate systemd-resolved
|
||||||
|
* more than once, NMConnectivity might -- until NMDnsSystemdResolved tried itself
|
||||||
|
* and noticed that systemd-resolved is not available.
|
||||||
|
* This is relatively cumbersome to avoid, because we would have to go through
|
||||||
|
* NMDnsSystemdResolved trying to asynchronously start the service, to ensure there
|
||||||
|
* is only one attempt to start the service. */
|
||||||
has_systemd_resolved = nm_dns_manager_has_systemd_resolved (nm_dns_manager_get ());
|
has_systemd_resolved = nm_dns_manager_has_systemd_resolved (nm_dns_manager_get ());
|
||||||
|
|
||||||
if (has_systemd_resolved) {
|
if (has_systemd_resolved) {
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include "c-list/src/c-list.h"
|
#include "c-list/src/c-list.h"
|
||||||
|
#include "nm-utils/nm-c-list.h"
|
||||||
#include "nm-dbus-interface.h"
|
#include "nm-dbus-interface.h"
|
||||||
#include "nm-core-internal.h"
|
#include "nm-core-internal.h"
|
||||||
#include "nm-dbus-compat.h"
|
#include "nm-dbus-compat.h"
|
||||||
|
|
@ -43,6 +44,17 @@
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
CList caller_info_lst;
|
||||||
|
gulong uid;
|
||||||
|
gulong pid;
|
||||||
|
gint64 uid_checked_at;
|
||||||
|
gint64 pid_checked_at;
|
||||||
|
bool uid_valid:1;
|
||||||
|
bool pid_valid:1;
|
||||||
|
char sender[0];
|
||||||
|
} CallerInfo;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GVariant *value;
|
GVariant *value;
|
||||||
} PropertyCacheData;
|
} PropertyCacheData;
|
||||||
|
|
@ -78,8 +90,10 @@ typedef struct {
|
||||||
NMDBusManagerSetPropertyHandler set_property_handler;
|
NMDBusManagerSetPropertyHandler set_property_handler;
|
||||||
gpointer set_property_handler_data;
|
gpointer set_property_handler_data;
|
||||||
|
|
||||||
GDBusConnection *connection;
|
GDBusConnection *main_dbus_connection;
|
||||||
GDBusProxy *proxy;
|
|
||||||
|
CList caller_info_lst_head;
|
||||||
|
|
||||||
guint objmgr_registration_id;
|
guint objmgr_registration_id;
|
||||||
bool started:1;
|
bool started:1;
|
||||||
bool shutting_down:1;
|
bool shutting_down:1;
|
||||||
|
|
@ -441,21 +455,33 @@ private_server_get_connection_by_owner (PrivateServer *s, const char *owner)
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
static void
|
||||||
|
_caller_info_free (CallerInfo *caller_info)
|
||||||
|
{
|
||||||
|
c_list_unlink_stale (&caller_info->caller_info_lst);
|
||||||
|
g_free (caller_info);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
_bus_get_unix_pid (NMDBusManager *self,
|
_bus_get_unix_pid (NMDBusManager *self,
|
||||||
const char *sender,
|
const char *sender,
|
||||||
gulong *out_pid,
|
gulong *out_pid)
|
||||||
GError **error)
|
|
||||||
{
|
{
|
||||||
|
NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
|
||||||
guint32 unix_pid = G_MAXUINT32;
|
guint32 unix_pid = G_MAXUINT32;
|
||||||
gs_unref_variant GVariant *ret = NULL;
|
gs_unref_variant GVariant *ret = NULL;
|
||||||
|
|
||||||
ret = _nm_dbus_proxy_call_sync (NM_DBUS_MANAGER_GET_PRIVATE (self)->proxy,
|
ret = g_dbus_connection_call_sync (priv->main_dbus_connection,
|
||||||
"GetConnectionUnixProcessID",
|
DBUS_SERVICE_DBUS,
|
||||||
g_variant_new ("(s)", sender),
|
DBUS_PATH_DBUS,
|
||||||
G_VARIANT_TYPE ("(u)"),
|
DBUS_INTERFACE_DBUS,
|
||||||
G_DBUS_CALL_FLAGS_NONE, 2000,
|
"GetConnectionUnixProcessID",
|
||||||
NULL, error);
|
g_variant_new ("(s)", sender),
|
||||||
|
G_VARIANT_TYPE ("(u)"),
|
||||||
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
2000,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
|
@ -468,18 +494,23 @@ _bus_get_unix_pid (NMDBusManager *self,
|
||||||
static gboolean
|
static gboolean
|
||||||
_bus_get_unix_user (NMDBusManager *self,
|
_bus_get_unix_user (NMDBusManager *self,
|
||||||
const char *sender,
|
const char *sender,
|
||||||
gulong *out_user,
|
gulong *out_user)
|
||||||
GError **error)
|
|
||||||
{
|
{
|
||||||
|
NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
|
||||||
guint32 unix_uid = G_MAXUINT32;
|
guint32 unix_uid = G_MAXUINT32;
|
||||||
gs_unref_variant GVariant *ret = NULL;
|
gs_unref_variant GVariant *ret = NULL;
|
||||||
|
|
||||||
ret = _nm_dbus_proxy_call_sync (NM_DBUS_MANAGER_GET_PRIVATE (self)->proxy,
|
ret = g_dbus_connection_call_sync (priv->main_dbus_connection,
|
||||||
"GetConnectionUnixUser",
|
DBUS_SERVICE_DBUS,
|
||||||
g_variant_new ("(s)", sender),
|
DBUS_PATH_DBUS,
|
||||||
G_VARIANT_TYPE ("(u)"),
|
DBUS_INTERFACE_DBUS,
|
||||||
G_DBUS_CALL_FLAGS_NONE, 2000,
|
"GetConnectionUnixUser",
|
||||||
NULL, error);
|
g_variant_new ("(s)", sender),
|
||||||
|
G_VARIANT_TYPE ("(u)"),
|
||||||
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
2000,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
|
@ -489,34 +520,102 @@ _bus_get_unix_user (NMDBusManager *self,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static const CallerInfo *
|
||||||
* _get_caller_info():
|
_get_caller_info_ensure (NMDBusManager *self,
|
||||||
*
|
const char *sender,
|
||||||
* Given a GDBus method invocation, or a GDBusConnection + GDBusMessage,
|
gboolean ensure_uid,
|
||||||
* return the sender and the UID of the sender.
|
gboolean ensure_pid)
|
||||||
*/
|
{
|
||||||
|
NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
|
||||||
|
CallerInfo *caller_info;
|
||||||
|
CallerInfo *ci;
|
||||||
|
gint64 now_ns;
|
||||||
|
gsize num;
|
||||||
|
|
||||||
|
#define CALLER_INFO_MAX_AGE (NM_UTILS_NS_PER_SECOND * 1)
|
||||||
|
|
||||||
|
/* Linear search the cache for the sender.
|
||||||
|
*
|
||||||
|
* The number of cached caller-infos is limited. Hence, it's O(1) and
|
||||||
|
* the list is reasonably short.
|
||||||
|
* Also, the entire caching assumes that we repeatedly ask for the
|
||||||
|
* same sender. That means, we expect to find the right caller info
|
||||||
|
* at the front of the list. */
|
||||||
|
num = 1;
|
||||||
|
caller_info = NULL;
|
||||||
|
c_list_for_each_entry (ci, &priv->caller_info_lst_head, caller_info_lst) {
|
||||||
|
if (nm_streq (sender, ci->sender)) {
|
||||||
|
caller_info = ci;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (caller_info)
|
||||||
|
nm_c_list_move_front (&priv->caller_info_lst_head, &caller_info->caller_info_lst);
|
||||||
|
else {
|
||||||
|
gsize l = strlen (sender) + 1;
|
||||||
|
|
||||||
|
caller_info = g_malloc (sizeof (CallerInfo) + l);
|
||||||
|
*caller_info = (CallerInfo) {
|
||||||
|
.uid_checked_at = - CALLER_INFO_MAX_AGE,
|
||||||
|
.pid_checked_at = - CALLER_INFO_MAX_AGE,
|
||||||
|
};
|
||||||
|
memcpy (caller_info->sender, sender, l);
|
||||||
|
c_list_link_front (&priv->caller_info_lst_head, &caller_info->caller_info_lst);
|
||||||
|
|
||||||
|
/* only cache the last few entries. */
|
||||||
|
while (TRUE) {
|
||||||
|
nm_assert (num > 0 && num == c_list_length (&priv->caller_info_lst_head));
|
||||||
|
if (num-- <= 5)
|
||||||
|
break;
|
||||||
|
_caller_info_free (c_list_last_entry (&priv->caller_info_lst_head, CallerInfo, caller_info_lst));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
now_ns = nm_utils_get_monotonic_timestamp_ns ();
|
||||||
|
|
||||||
|
if ( ensure_uid
|
||||||
|
&& (now_ns - caller_info->uid_checked_at) > CALLER_INFO_MAX_AGE) {
|
||||||
|
caller_info->uid_checked_at = now_ns;
|
||||||
|
if (!(caller_info->uid_valid = _bus_get_unix_user (self, sender, &caller_info->uid)))
|
||||||
|
caller_info->uid = G_MAXULONG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ensure_pid
|
||||||
|
&& (now_ns - caller_info->pid_checked_at) > CALLER_INFO_MAX_AGE) {
|
||||||
|
caller_info->pid_checked_at = now_ns;
|
||||||
|
if (!(caller_info->pid_valid = _bus_get_unix_pid (self, sender, &caller_info->pid)))
|
||||||
|
caller_info->pid = G_MAXULONG;
|
||||||
|
}
|
||||||
|
|
||||||
|
return caller_info;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
_get_caller_info (NMDBusManager *self,
|
_get_caller_info (NMDBusManager *self,
|
||||||
GDBusMethodInvocation *context,
|
GDBusMethodInvocation *context,
|
||||||
GDBusConnection *connection,
|
GDBusConnection *connection,
|
||||||
GDBusMessage *message,
|
GDBusMessage *message,
|
||||||
char **out_sender,
|
const char **out_sender,
|
||||||
gulong *out_uid,
|
gulong *out_uid,
|
||||||
gulong *out_pid)
|
gulong *out_pid)
|
||||||
{
|
{
|
||||||
NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
|
NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
|
||||||
|
const CallerInfo *caller_info;
|
||||||
const char *sender;
|
const char *sender;
|
||||||
|
|
||||||
if (context) {
|
if (context) {
|
||||||
|
nm_assert (G_IS_DBUS_METHOD_INVOCATION (context));
|
||||||
connection = g_dbus_method_invocation_get_connection (context);
|
connection = g_dbus_method_invocation_get_connection (context);
|
||||||
|
|
||||||
/* only bus connections will have a sender */
|
/* only bus connections will have a sender */
|
||||||
sender = g_dbus_method_invocation_get_sender (context);
|
sender = g_dbus_method_invocation_get_sender (context);
|
||||||
} else {
|
} else {
|
||||||
g_assert (message);
|
nm_assert (G_IS_DBUS_MESSAGE (message));
|
||||||
sender = g_dbus_message_get_sender (message);
|
sender = g_dbus_message_get_sender (message);
|
||||||
}
|
}
|
||||||
g_assert (connection);
|
nm_assert (G_IS_DBUS_CONNECTION (connection));
|
||||||
|
|
||||||
if (!sender) {
|
if (!sender) {
|
||||||
PrivateServer *s;
|
PrivateServer *s;
|
||||||
|
|
@ -525,10 +624,8 @@ _get_caller_info (NMDBusManager *self,
|
||||||
c_list_for_each_entry (s, &priv->private_servers_lst_head, private_servers_lst) {
|
c_list_for_each_entry (s, &priv->private_servers_lst_head, private_servers_lst) {
|
||||||
sender = private_server_get_connection_owner (s, connection);
|
sender = private_server_get_connection_owner (s, connection);
|
||||||
if (sender) {
|
if (sender) {
|
||||||
if (out_uid)
|
NM_SET_OUT (out_uid, 0);
|
||||||
*out_uid = 0;
|
NM_SET_OUT (out_sender, sender);
|
||||||
if (out_sender)
|
|
||||||
*out_sender = g_strdup (sender);
|
|
||||||
if (out_pid) {
|
if (out_pid) {
|
||||||
GCredentials *creds;
|
GCredentials *creds;
|
||||||
|
|
||||||
|
|
@ -547,35 +644,29 @@ _get_caller_info (NMDBusManager *self,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
NM_SET_OUT (out_sender, NULL);
|
||||||
|
NM_SET_OUT (out_uid, G_MAXULONG);
|
||||||
|
NM_SET_OUT (out_pid, G_MAXULONG);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bus connections always have a sender */
|
caller_info = _get_caller_info_ensure (self, sender, !!out_uid, !!out_pid);
|
||||||
g_assert (sender);
|
|
||||||
if (out_uid) {
|
|
||||||
if (!_bus_get_unix_user (self, sender, out_uid, NULL)) {
|
|
||||||
*out_uid = G_MAXULONG;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (out_pid) {
|
NM_SET_OUT (out_sender, caller_info->sender);
|
||||||
if (!_bus_get_unix_pid (self, sender, out_pid, NULL)) {
|
NM_SET_OUT (out_uid, caller_info->uid);
|
||||||
*out_pid = G_MAXULONG;
|
NM_SET_OUT (out_pid, caller_info->pid);
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (out_sender)
|
|
||||||
*out_sender = g_strdup (sender);
|
|
||||||
|
|
||||||
|
if (out_uid && !caller_info->uid_valid)
|
||||||
|
return FALSE;
|
||||||
|
if (out_pid && !caller_info->pid_valid)
|
||||||
|
return FALSE;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
nm_dbus_manager_get_caller_info (NMDBusManager *self,
|
nm_dbus_manager_get_caller_info (NMDBusManager *self,
|
||||||
GDBusMethodInvocation *context,
|
GDBusMethodInvocation *context,
|
||||||
char **out_sender,
|
const char **out_sender,
|
||||||
gulong *out_uid,
|
gulong *out_uid,
|
||||||
gulong *out_pid)
|
gulong *out_pid)
|
||||||
{
|
{
|
||||||
|
|
@ -586,7 +677,7 @@ gboolean
|
||||||
nm_dbus_manager_get_caller_info_from_message (NMDBusManager *self,
|
nm_dbus_manager_get_caller_info_from_message (NMDBusManager *self,
|
||||||
GDBusConnection *connection,
|
GDBusConnection *connection,
|
||||||
GDBusMessage *message,
|
GDBusMessage *message,
|
||||||
char **out_sender,
|
const char **out_sender,
|
||||||
gulong *out_uid,
|
gulong *out_uid,
|
||||||
gulong *out_pid)
|
gulong *out_pid)
|
||||||
{
|
{
|
||||||
|
|
@ -647,8 +738,8 @@ nm_dbus_manager_get_unix_user (NMDBusManager *self,
|
||||||
gulong *out_uid)
|
gulong *out_uid)
|
||||||
{
|
{
|
||||||
NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
|
NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
|
||||||
|
const CallerInfo *caller_info;
|
||||||
PrivateServer *s;
|
PrivateServer *s;
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
g_return_val_if_fail (sender != NULL, FALSE);
|
g_return_val_if_fail (sender != NULL, FALSE);
|
||||||
g_return_val_if_fail (out_uid != NULL, FALSE);
|
g_return_val_if_fail (out_uid != NULL, FALSE);
|
||||||
|
|
@ -665,13 +756,12 @@ nm_dbus_manager_get_unix_user (NMDBusManager *self,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Otherwise, a bus connection */
|
/* Otherwise, a bus connection */
|
||||||
if (!_bus_get_unix_user (self, sender, out_uid, &error)) {
|
caller_info = _get_caller_info_ensure (self, sender, TRUE, FALSE);
|
||||||
_LOGW ("failed to get unix user for dbus sender '%s': %s",
|
*out_uid = caller_info->uid;
|
||||||
sender, error->message);
|
if (!caller_info->uid_valid) {
|
||||||
g_error_free (error);
|
_LOGW ("failed to get unix user for dbus sender '%s'", sender);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -757,16 +847,6 @@ nm_dbus_manager_new_proxy (NMDBusManager *self,
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
GDBusConnection *
|
|
||||||
nm_dbus_manager_get_connection (NMDBusManager *self)
|
|
||||||
{
|
|
||||||
g_return_val_if_fail (NM_IS_DBUS_MANAGER (self), NULL);
|
|
||||||
|
|
||||||
return NM_DBUS_MANAGER_GET_PRIVATE (self)->connection;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
static const NMDBusInterfaceInfoExtended *
|
static const NMDBusInterfaceInfoExtended *
|
||||||
_reg_data_get_interface_info (RegistrationData *reg_data)
|
_reg_data_get_interface_info (RegistrationData *reg_data)
|
||||||
{
|
{
|
||||||
|
|
@ -943,7 +1023,7 @@ _obj_register (NMDBusManager *self,
|
||||||
GVariantBuilder builder;
|
GVariantBuilder builder;
|
||||||
|
|
||||||
nm_assert (c_list_is_empty (&obj->internal.registration_lst_head));
|
nm_assert (c_list_is_empty (&obj->internal.registration_lst_head));
|
||||||
nm_assert (priv->connection);
|
nm_assert (priv->main_dbus_connection);
|
||||||
nm_assert (priv->started);
|
nm_assert (priv->started);
|
||||||
|
|
||||||
n_klasses = 0;
|
n_klasses = 0;
|
||||||
|
|
@ -980,7 +1060,7 @@ _obj_register (NMDBusManager *self,
|
||||||
|
|
||||||
reg_data = g_malloc0 (sizeof (RegistrationData) + (sizeof (PropertyCacheData) * prop_len));
|
reg_data = g_malloc0 (sizeof (RegistrationData) + (sizeof (PropertyCacheData) * prop_len));
|
||||||
|
|
||||||
registration_id = g_dbus_connection_register_object (priv->connection,
|
registration_id = g_dbus_connection_register_object (priv->main_dbus_connection,
|
||||||
obj->internal.path,
|
obj->internal.path,
|
||||||
NM_UNCONST_PTR (GDBusInterfaceInfo, &interface_info->parent),
|
NM_UNCONST_PTR (GDBusInterfaceInfo, &interface_info->parent),
|
||||||
&dbus_vtable,
|
&dbus_vtable,
|
||||||
|
|
@ -1019,7 +1099,7 @@ _obj_register (NMDBusManager *self,
|
||||||
*
|
*
|
||||||
* In general, it's ok to export an object with frozen signals. But you better make sure
|
* In general, it's ok to export an object with frozen signals. But you better make sure
|
||||||
* that all properties are in a self-consistent state when exporting the object. */
|
* that all properties are in a self-consistent state when exporting the object. */
|
||||||
g_dbus_connection_emit_signal (priv->connection,
|
g_dbus_connection_emit_signal (priv->main_dbus_connection,
|
||||||
NULL,
|
NULL,
|
||||||
OBJECT_MANAGER_SERVER_BASE_PATH,
|
OBJECT_MANAGER_SERVER_BASE_PATH,
|
||||||
interface_info_objmgr.name,
|
interface_info_objmgr.name,
|
||||||
|
|
@ -1040,7 +1120,7 @@ _obj_unregister (NMDBusManager *self,
|
||||||
|
|
||||||
nm_assert (NM_IS_DBUS_OBJECT (obj));
|
nm_assert (NM_IS_DBUS_OBJECT (obj));
|
||||||
|
|
||||||
if (!priv->connection) {
|
if (!priv->main_dbus_connection) {
|
||||||
/* nothing to do for the moment. */
|
/* nothing to do for the moment. */
|
||||||
nm_assert (c_list_is_empty (&obj->internal.registration_lst_head));
|
nm_assert (c_list_is_empty (&obj->internal.registration_lst_head));
|
||||||
return;
|
return;
|
||||||
|
|
@ -1059,7 +1139,7 @@ _obj_unregister (NMDBusManager *self,
|
||||||
"s",
|
"s",
|
||||||
interface_info->parent.name);
|
interface_info->parent.name);
|
||||||
c_list_unlink_stale (®_data->registration_lst);
|
c_list_unlink_stale (®_data->registration_lst);
|
||||||
if (!g_dbus_connection_unregister_object (priv->connection, reg_data->registration_id))
|
if (!g_dbus_connection_unregister_object (priv->main_dbus_connection, reg_data->registration_id))
|
||||||
nm_assert_not_reached ();
|
nm_assert_not_reached ();
|
||||||
|
|
||||||
if (interface_info->parent.properties) {
|
if (interface_info->parent.properties) {
|
||||||
|
|
@ -1071,7 +1151,7 @@ _obj_unregister (NMDBusManager *self,
|
||||||
g_free (reg_data);
|
g_free (reg_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_dbus_connection_emit_signal (priv->connection,
|
g_dbus_connection_emit_signal (priv->main_dbus_connection,
|
||||||
NULL,
|
NULL,
|
||||||
OBJECT_MANAGER_SERVER_BASE_PATH,
|
OBJECT_MANAGER_SERVER_BASE_PATH,
|
||||||
interface_info_objmgr.name,
|
interface_info_objmgr.name,
|
||||||
|
|
@ -1122,7 +1202,7 @@ _nm_dbus_manager_obj_export (NMDBusObject *obj)
|
||||||
nm_assert_not_reached ();
|
nm_assert_not_reached ();
|
||||||
c_list_link_tail (&priv->objects_lst_head, &obj->internal.objects_lst);
|
c_list_link_tail (&priv->objects_lst_head, &obj->internal.objects_lst);
|
||||||
|
|
||||||
if (priv->connection && priv->started)
|
if (priv->main_dbus_connection && priv->started)
|
||||||
_obj_register (self, obj);
|
_obj_register (self, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1239,7 +1319,7 @@ _nm_dbus_manager_obj_notify (NMDBusObject *obj,
|
||||||
}
|
}
|
||||||
|
|
||||||
g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as"));
|
g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as"));
|
||||||
g_dbus_connection_emit_signal (priv->connection,
|
g_dbus_connection_emit_signal (priv->main_dbus_connection,
|
||||||
NULL,
|
NULL,
|
||||||
obj->internal.path,
|
obj->internal.path,
|
||||||
"org.freedesktop.DBus.Properties",
|
"org.freedesktop.DBus.Properties",
|
||||||
|
|
@ -1255,7 +1335,7 @@ _nm_dbus_manager_obj_notify (NMDBusObject *obj,
|
||||||
/* this is a special interface: it has a legacy PropertiesChanged signal,
|
/* this is a special interface: it has a legacy PropertiesChanged signal,
|
||||||
* however, contrary to other interfaces with ~regular~ legacy signals,
|
* however, contrary to other interfaces with ~regular~ legacy signals,
|
||||||
* we only notify about properties that actually belong to this interface. */
|
* we only notify about properties that actually belong to this interface. */
|
||||||
g_dbus_connection_emit_signal (priv->connection,
|
g_dbus_connection_emit_signal (priv->main_dbus_connection,
|
||||||
NULL,
|
NULL,
|
||||||
obj->internal.path,
|
obj->internal.path,
|
||||||
nm_interface_info_device_statistics.parent.name,
|
nm_interface_info_device_statistics.parent.name,
|
||||||
|
|
@ -1292,7 +1372,7 @@ _nm_dbus_manager_obj_notify (NMDBusObject *obj,
|
||||||
const NMDBusInterfaceInfoExtended *interface_info = _reg_data_get_interface_info (reg_data);
|
const NMDBusInterfaceInfoExtended *interface_info = _reg_data_get_interface_info (reg_data);
|
||||||
|
|
||||||
if (interface_info->legacy_property_changed) {
|
if (interface_info->legacy_property_changed) {
|
||||||
g_dbus_connection_emit_signal (priv->connection,
|
g_dbus_connection_emit_signal (priv->main_dbus_connection,
|
||||||
NULL,
|
NULL,
|
||||||
obj->internal.path,
|
obj->internal.path,
|
||||||
interface_info->parent.name,
|
interface_info->parent.name,
|
||||||
|
|
@ -1321,12 +1401,12 @@ _nm_dbus_manager_obj_emit_signal (NMDBusObject *obj,
|
||||||
self = obj->internal.bus_manager;
|
self = obj->internal.bus_manager;
|
||||||
priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
|
priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
|
||||||
|
|
||||||
if (!priv->connection || !priv->started) {
|
if (!priv->main_dbus_connection || !priv->started) {
|
||||||
nm_g_variant_unref_floating (args);
|
nm_g_variant_unref_floating (args);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_dbus_connection_emit_signal (priv->connection,
|
g_dbus_connection_emit_signal (priv->main_dbus_connection,
|
||||||
NULL,
|
NULL,
|
||||||
obj->internal.path,
|
obj->internal.path,
|
||||||
interface_info->parent.name,
|
interface_info->parent.name,
|
||||||
|
|
@ -1473,7 +1553,7 @@ nm_dbus_manager_get_dbus_connection (NMDBusManager *self)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (NM_IS_DBUS_MANAGER (self), NULL);
|
g_return_val_if_fail (NM_IS_DBUS_MANAGER (self), NULL);
|
||||||
|
|
||||||
return NM_DBUS_MANAGER_GET_PRIVATE (self)->connection;
|
return NM_DBUS_MANAGER_GET_PRIVATE (self)->main_dbus_connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -1487,7 +1567,7 @@ nm_dbus_manager_start (NMDBusManager *self,
|
||||||
g_return_if_fail (NM_IS_DBUS_MANAGER (self));
|
g_return_if_fail (NM_IS_DBUS_MANAGER (self));
|
||||||
priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
|
priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
|
||||||
|
|
||||||
if (!priv->connection) {
|
if (!priv->main_dbus_connection) {
|
||||||
/* Do nothing. We're presumably in the configure-and-quit mode. */
|
/* Do nothing. We're presumably in the configure-and-quit mode. */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1507,7 +1587,6 @@ nm_dbus_manager_acquire_bus (NMDBusManager *self)
|
||||||
gs_free_error GError *error = NULL;
|
gs_free_error GError *error = NULL;
|
||||||
gs_unref_variant GVariant *ret = NULL;
|
gs_unref_variant GVariant *ret = NULL;
|
||||||
gs_unref_object GDBusConnection *connection = NULL;
|
gs_unref_object GDBusConnection *connection = NULL;
|
||||||
gs_unref_object GDBusProxy *proxy = NULL;
|
|
||||||
guint32 result;
|
guint32 result;
|
||||||
guint registration_id;
|
guint registration_id;
|
||||||
|
|
||||||
|
|
@ -1530,20 +1609,6 @@ nm_dbus_manager_acquire_bus (NMDBusManager *self)
|
||||||
|
|
||||||
g_dbus_connection_set_exit_on_close (connection, FALSE);
|
g_dbus_connection_set_exit_on_close (connection, FALSE);
|
||||||
|
|
||||||
proxy = g_dbus_proxy_new_sync (connection,
|
|
||||||
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES
|
|
||||||
| G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
|
|
||||||
NULL,
|
|
||||||
DBUS_SERVICE_DBUS,
|
|
||||||
DBUS_PATH_DBUS,
|
|
||||||
DBUS_INTERFACE_DBUS,
|
|
||||||
NULL,
|
|
||||||
&error);
|
|
||||||
if (!proxy) {
|
|
||||||
_LOGE ("fatal failure to initialize D-Bus: %s", error->message);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
registration_id = g_dbus_connection_register_object (connection,
|
registration_id = g_dbus_connection_register_object (connection,
|
||||||
OBJECT_MANAGER_SERVER_BASE_PATH,
|
OBJECT_MANAGER_SERVER_BASE_PATH,
|
||||||
NM_UNCONST_PTR (GDBusInterfaceInfo, &interface_info_objmgr),
|
NM_UNCONST_PTR (GDBusInterfaceInfo, &interface_info_objmgr),
|
||||||
|
|
@ -1556,15 +1621,22 @@ nm_dbus_manager_acquire_bus (NMDBusManager *self)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = _nm_dbus_proxy_call_sync (proxy,
|
ret = g_dbus_connection_call_sync (connection,
|
||||||
"RequestName",
|
DBUS_SERVICE_DBUS,
|
||||||
g_variant_new ("(su)",
|
DBUS_PATH_DBUS,
|
||||||
NM_DBUS_SERVICE,
|
DBUS_INTERFACE_DBUS,
|
||||||
DBUS_NAME_FLAG_DO_NOT_QUEUE),
|
"RequestName",
|
||||||
G_VARIANT_TYPE ("(u)"),
|
g_variant_new ("(su)",
|
||||||
G_DBUS_CALL_FLAGS_NONE, -1,
|
NM_DBUS_SERVICE,
|
||||||
NULL,
|
DBUS_NAME_FLAG_DO_NOT_QUEUE),
|
||||||
&error);
|
G_VARIANT_TYPE ("(u)"),
|
||||||
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
-1,
|
||||||
|
NULL,
|
||||||
|
&error);
|
||||||
|
if (!ret)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
_LOGE ("fatal failure to acquire D-Bus service \"%s"": %s",
|
_LOGE ("fatal failure to acquire D-Bus service \"%s"": %s",
|
||||||
NM_DBUS_SERVICE, error->message);
|
NM_DBUS_SERVICE, error->message);
|
||||||
|
|
@ -1581,8 +1653,7 @@ nm_dbus_manager_acquire_bus (NMDBusManager *self)
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->objmgr_registration_id = registration_id;
|
priv->objmgr_registration_id = registration_id;
|
||||||
priv->connection = g_steal_pointer (&connection);
|
priv->main_dbus_connection = g_steal_pointer (&connection);
|
||||||
priv->proxy = g_steal_pointer (&proxy);
|
|
||||||
|
|
||||||
_LOGI ("acquired D-Bus service \"%s\"", NM_DBUS_SERVICE);
|
_LOGI ("acquired D-Bus service \"%s\"", NM_DBUS_SERVICE);
|
||||||
|
|
||||||
|
|
@ -1620,6 +1691,8 @@ nm_dbus_manager_init (NMDBusManager *self)
|
||||||
c_list_init (&priv->private_servers_lst_head);
|
c_list_init (&priv->private_servers_lst_head);
|
||||||
c_list_init (&priv->objects_lst_head);
|
c_list_init (&priv->objects_lst_head);
|
||||||
priv->objects_by_path = g_hash_table_new ((GHashFunc) _objects_by_path_hash, (GEqualFunc) _objects_by_path_equal);
|
priv->objects_by_path = g_hash_table_new ((GHashFunc) _objects_by_path_hash, (GEqualFunc) _objects_by_path_equal);
|
||||||
|
|
||||||
|
c_list_init (&priv->caller_info_lst_head);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -1628,6 +1701,7 @@ dispose (GObject *object)
|
||||||
NMDBusManager *self = NM_DBUS_MANAGER (object);
|
NMDBusManager *self = NM_DBUS_MANAGER (object);
|
||||||
NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
|
NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
|
||||||
PrivateServer *s, *s_safe;
|
PrivateServer *s, *s_safe;
|
||||||
|
CallerInfo *caller_info;
|
||||||
|
|
||||||
/* All exported NMDBusObject instances keep the manager alive, so we don't
|
/* All exported NMDBusObject instances keep the manager alive, so we don't
|
||||||
* expect any remaining objects. */
|
* expect any remaining objects. */
|
||||||
|
|
@ -1640,14 +1714,16 @@ dispose (GObject *object)
|
||||||
private_server_free (s);
|
private_server_free (s);
|
||||||
|
|
||||||
if (priv->objmgr_registration_id) {
|
if (priv->objmgr_registration_id) {
|
||||||
g_dbus_connection_unregister_object (priv->connection,
|
g_dbus_connection_unregister_object (priv->main_dbus_connection,
|
||||||
nm_steal_int (&priv->objmgr_registration_id));
|
nm_steal_int (&priv->objmgr_registration_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
g_clear_object (&priv->proxy);
|
g_clear_object (&priv->main_dbus_connection);
|
||||||
g_clear_object (&priv->connection);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (nm_dbus_manager_parent_class)->dispose (object);
|
G_OBJECT_CLASS (nm_dbus_manager_parent_class)->dispose (object);
|
||||||
|
|
||||||
|
while ((caller_info = c_list_first_entry (&priv->caller_info_lst_head, CallerInfo, caller_info_lst)))
|
||||||
|
_caller_info_free (caller_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
||||||
|
|
@ -61,8 +61,6 @@ void nm_dbus_manager_stop (NMDBusManager *self);
|
||||||
|
|
||||||
gboolean nm_dbus_manager_is_stopping (NMDBusManager *self);
|
gboolean nm_dbus_manager_is_stopping (NMDBusManager *self);
|
||||||
|
|
||||||
GDBusConnection *nm_dbus_manager_get_connection (NMDBusManager *self);
|
|
||||||
|
|
||||||
gpointer nm_dbus_manager_lookup_object (NMDBusManager *self, const char *path);
|
gpointer nm_dbus_manager_lookup_object (NMDBusManager *self, const char *path);
|
||||||
|
|
||||||
void _nm_dbus_manager_obj_export (NMDBusObject *obj);
|
void _nm_dbus_manager_obj_export (NMDBusObject *obj);
|
||||||
|
|
@ -77,7 +75,7 @@ void _nm_dbus_manager_obj_emit_signal (NMDBusObject *obj,
|
||||||
|
|
||||||
gboolean nm_dbus_manager_get_caller_info (NMDBusManager *self,
|
gboolean nm_dbus_manager_get_caller_info (NMDBusManager *self,
|
||||||
GDBusMethodInvocation *context,
|
GDBusMethodInvocation *context,
|
||||||
char **out_sender,
|
const char **out_sender,
|
||||||
gulong *out_uid,
|
gulong *out_uid,
|
||||||
gulong *out_pid);
|
gulong *out_pid);
|
||||||
|
|
||||||
|
|
@ -97,7 +95,7 @@ gboolean nm_dbus_manager_get_unix_user (NMDBusManager *self,
|
||||||
gboolean nm_dbus_manager_get_caller_info_from_message (NMDBusManager *self,
|
gboolean nm_dbus_manager_get_caller_info_from_message (NMDBusManager *self,
|
||||||
GDBusConnection *connection,
|
GDBusConnection *connection,
|
||||||
GDBusMessage *message,
|
GDBusMessage *message,
|
||||||
char **out_sender,
|
const char **out_sender,
|
||||||
gulong *out_uid,
|
gulong *out_uid,
|
||||||
gulong *out_pid);
|
gulong *out_pid);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue