mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-25 11:50:14 +01:00
core: merge branch 'th/async-bgo781643'
https://bugzilla.gnome.org/show_bug.cgi?id=781643
This commit is contained in:
commit
36e7a1f8a0
20 changed files with 1999 additions and 1215 deletions
|
|
@ -1391,6 +1391,9 @@ src_libNetworkManager_la_SOURCES = \
|
|||
src/ppp/nm-ppp-manager.h \
|
||||
src/ppp/nm-ppp-status.h \
|
||||
\
|
||||
src/nm-hostname-manager.c \
|
||||
src/nm-hostname-manager.h \
|
||||
\
|
||||
src/settings/nm-agent-manager.c \
|
||||
src/settings/nm-agent-manager.h \
|
||||
src/settings/nm-inotify-helper.c \
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ static guint signals[LAST_SIGNAL] = { 0 };
|
|||
typedef struct {
|
||||
char *path;
|
||||
GDBusProxy *proxy;
|
||||
GCancellable *proxy_cancellable;
|
||||
gboolean initialized;
|
||||
|
||||
char *address;
|
||||
|
|
@ -73,6 +74,11 @@ G_DEFINE_TYPE (NMBluez4Adapter, nm_bluez4_adapter, G_TYPE_OBJECT)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define _NMLOG_DOMAIN LOGD_BT
|
||||
#define _NMLOG(level, ...) __NMLOG_DEFAULT (level, _NMLOG_DOMAIN, "bluez4-adapter", __VA_ARGS__)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void device_do_remove (NMBluez4Adapter *self, NMBluezDevice *device);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -119,8 +125,8 @@ nm_bluez4_adapter_get_devices (NMBluez4Adapter *self)
|
|||
static void
|
||||
emit_device_removed (NMBluez4Adapter *self, NMBluezDevice *device)
|
||||
{
|
||||
nm_log_dbg (LOGD_BT, "(%s): bluez device now unusable",
|
||||
nm_bluez_device_get_path (device));
|
||||
_LOGD ("(%s): bluez device now unusable",
|
||||
nm_bluez_device_get_path (device));
|
||||
g_signal_emit (self, signals[DEVICE_REMOVED], 0, device);
|
||||
}
|
||||
|
||||
|
|
@ -130,9 +136,9 @@ device_usable (NMBluezDevice *device, GParamSpec *pspec, gpointer user_data)
|
|||
NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (user_data);
|
||||
|
||||
if (nm_bluez_device_get_usable (device)) {
|
||||
nm_log_dbg (LOGD_BT, "(%s): bluez device now usable (device address is %s)",
|
||||
nm_bluez_device_get_path (device),
|
||||
nm_bluez_device_get_address (device));
|
||||
_LOGD ("(%s): bluez device now usable (device address is %s)",
|
||||
nm_bluez_device_get_path (device),
|
||||
nm_bluez_device_get_address (device));
|
||||
g_signal_emit (self, signals[DEVICE_ADDED], 0, device);
|
||||
} else
|
||||
emit_device_removed (self, device);
|
||||
|
|
@ -143,9 +149,9 @@ device_initialized (NMBluezDevice *device, gboolean success, gpointer user_data)
|
|||
{
|
||||
NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (user_data);
|
||||
|
||||
nm_log_dbg (LOGD_BT, "(%s): bluez device %s",
|
||||
nm_bluez_device_get_path (device),
|
||||
success ? "initialized" : "failed to initialize");
|
||||
_LOGD ("(%s): bluez device %s",
|
||||
nm_bluez_device_get_path (device),
|
||||
success ? "initialized" : "failed to initialize");
|
||||
if (!success)
|
||||
device_do_remove (self, device);
|
||||
}
|
||||
|
|
@ -178,7 +184,7 @@ device_created (GDBusProxy *proxy, const char *path, gpointer user_data)
|
|||
g_signal_connect (device, "notify::usable", G_CALLBACK (device_usable), self);
|
||||
g_hash_table_insert (priv->devices, (gpointer) nm_bluez_device_get_path (device), device);
|
||||
|
||||
nm_log_dbg (LOGD_BT, "(%s): new bluez device found", path);
|
||||
_LOGD ("(%s): new bluez device found", path);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -188,7 +194,7 @@ device_removed (GDBusProxy *proxy, const char *path, gpointer user_data)
|
|||
NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self);
|
||||
NMBluezDevice *device;
|
||||
|
||||
nm_log_dbg (LOGD_BT, "(%s): bluez device removed", path);
|
||||
_LOGD ("(%s): bluez device removed", path);
|
||||
|
||||
device = g_hash_table_lookup (priv->devices, path);
|
||||
if (device)
|
||||
|
|
@ -198,19 +204,28 @@ device_removed (GDBusProxy *proxy, const char *path, gpointer user_data)
|
|||
static void
|
||||
get_properties_cb (GObject *proxy, GAsyncResult *result, gpointer user_data)
|
||||
{
|
||||
NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (user_data);
|
||||
NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self);
|
||||
GError *err = NULL;
|
||||
NMBluez4Adapter *self;
|
||||
NMBluez4AdapterPrivate *priv;
|
||||
gs_free_error GError *error = NULL;
|
||||
GVariant *ret, *properties;
|
||||
char **devices;
|
||||
int i;
|
||||
|
||||
ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result,
|
||||
G_VARIANT_TYPE ("(a{sv})"), &err);
|
||||
G_VARIANT_TYPE ("(a{sv})"), &error);
|
||||
|
||||
if ( !ret
|
||||
&& g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
|
||||
self = NM_BLUEZ4_ADAPTER (user_data);
|
||||
priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self);
|
||||
|
||||
g_clear_object (&priv->proxy_cancellable);
|
||||
|
||||
if (!ret) {
|
||||
g_dbus_error_strip_remote_error (err);
|
||||
nm_log_warn (LOGD_BT, "bluez error getting adapter properties: %s", err->message);
|
||||
g_error_free (err);
|
||||
g_dbus_error_strip_remote_error (error);
|
||||
_LOGW ("bluez error getting adapter properties: %s", error->message);
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
|
@ -233,15 +248,43 @@ done:
|
|||
}
|
||||
|
||||
static void
|
||||
query_properties (NMBluez4Adapter *self)
|
||||
_proxy_new_cb (GObject *source_object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self);
|
||||
NMBluez4Adapter *self;
|
||||
NMBluez4AdapterPrivate *priv;
|
||||
gs_free_error GError *error = NULL;
|
||||
GDBusProxy *proxy;
|
||||
|
||||
proxy = g_dbus_proxy_new_for_bus_finish (result, &error);
|
||||
if ( !proxy
|
||||
&& g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
|
||||
self = user_data;
|
||||
priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self);
|
||||
|
||||
if (!proxy) {
|
||||
_LOGW ("bluez error creating D-Bus proxy: %s", error->message);
|
||||
g_clear_object (&priv->proxy_cancellable);
|
||||
g_signal_emit (self, signals[INITIALIZED], 0, priv->initialized);
|
||||
return;
|
||||
}
|
||||
|
||||
priv->proxy = proxy;
|
||||
|
||||
_nm_dbus_signal_connect (priv->proxy, "DeviceCreated", G_VARIANT_TYPE ("(o)"),
|
||||
G_CALLBACK (device_created), self);
|
||||
_nm_dbus_signal_connect (priv->proxy, "DeviceRemoved", G_VARIANT_TYPE ("(o)"),
|
||||
G_CALLBACK (device_removed), self);
|
||||
|
||||
g_dbus_proxy_call (priv->proxy, "GetProperties",
|
||||
NULL,
|
||||
G_DBUS_CALL_FLAGS_NONE, -1,
|
||||
NULL,
|
||||
get_properties_cb, self);
|
||||
priv->proxy_cancellable,
|
||||
get_properties_cb,
|
||||
self);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -316,19 +359,17 @@ nm_bluez4_adapter_new (const char *path, NMSettings *settings)
|
|||
|
||||
priv->settings = g_object_ref (settings);
|
||||
|
||||
priv->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
|
||||
NULL,
|
||||
BLUEZ_SERVICE,
|
||||
priv->path,
|
||||
BLUEZ4_ADAPTER_INTERFACE,
|
||||
NULL, NULL);
|
||||
_nm_dbus_signal_connect (priv->proxy, "DeviceCreated", G_VARIANT_TYPE ("(o)"),
|
||||
G_CALLBACK (device_created), self);
|
||||
_nm_dbus_signal_connect (priv->proxy, "DeviceRemoved", G_VARIANT_TYPE ("(o)"),
|
||||
G_CALLBACK (device_removed), self);
|
||||
priv->proxy_cancellable = g_cancellable_new ();
|
||||
|
||||
query_properties (self);
|
||||
g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
|
||||
NULL,
|
||||
BLUEZ_SERVICE,
|
||||
priv->path,
|
||||
BLUEZ4_ADAPTER_INTERFACE,
|
||||
priv->proxy_cancellable,
|
||||
_proxy_new_cb,
|
||||
self);
|
||||
return self;
|
||||
}
|
||||
|
||||
|
|
@ -339,21 +380,28 @@ dispose (GObject *object)
|
|||
NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self);
|
||||
NMBluezDevice *device;
|
||||
|
||||
nm_clear_g_cancellable (&priv->proxy_cancellable);
|
||||
|
||||
while ((device = g_hash_table_find (priv->devices, _find_all, NULL)))
|
||||
device_do_remove (self, device);
|
||||
|
||||
if (priv->proxy) {
|
||||
g_signal_handlers_disconnect_by_data (priv->proxy, self);
|
||||
g_clear_object (&priv->proxy);
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (nm_bluez4_adapter_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
finalize (GObject *object)
|
||||
{
|
||||
NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE ((NMBluez4Adapter *) object);
|
||||
NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (object);
|
||||
NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self);
|
||||
|
||||
g_hash_table_destroy (priv->devices);
|
||||
g_free (priv->address);
|
||||
g_free (priv->path);
|
||||
g_object_unref (priv->proxy);
|
||||
|
||||
G_OBJECT_CLASS (nm_bluez4_adapter_parent_class)->finalize (object);
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ typedef struct {
|
|||
NMSettings *settings;
|
||||
|
||||
GDBusProxy *proxy;
|
||||
GCancellable *proxy_cancellable;
|
||||
|
||||
NMBluez4Adapter *adapter;
|
||||
} NMBluez4ManagerPrivate;
|
||||
|
|
@ -66,6 +67,11 @@ G_DEFINE_TYPE (NMBluez4Manager, nm_bluez4_manager, G_TYPE_OBJECT)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define _NMLOG_DOMAIN LOGD_BT
|
||||
#define _NMLOG(level, ...) __NMLOG_DEFAULT (level, _NMLOG_DOMAIN, "bluez4-manager", __VA_ARGS__)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
emit_bdaddr_added (NMBluez4Manager *self, NMBluezDevice *device)
|
||||
{
|
||||
|
|
@ -176,42 +182,62 @@ default_adapter_changed (GDBusProxy *proxy, const char *path, NMBluez4Manager *s
|
|||
static void
|
||||
default_adapter_cb (GObject *proxy, GAsyncResult *result, gpointer user_data)
|
||||
{
|
||||
NMBluez4Manager *self = NM_BLUEZ4_MANAGER (user_data);
|
||||
NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self);
|
||||
GVariant *ret;
|
||||
GError *err = NULL;
|
||||
NMBluez4Manager *self;
|
||||
NMBluez4ManagerPrivate *priv;
|
||||
gs_unref_variant GVariant *ret = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
const char *default_adapter;
|
||||
|
||||
ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result,
|
||||
G_VARIANT_TYPE ("(o)"), &err);
|
||||
if (ret) {
|
||||
const char *default_adapter;
|
||||
G_VARIANT_TYPE ("(o)"), &error);
|
||||
if ( !ret
|
||||
&& g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
|
||||
g_variant_get (ret, "(&o)", &default_adapter);
|
||||
default_adapter_changed (priv->proxy, default_adapter, self);
|
||||
g_variant_unref (ret);
|
||||
} else {
|
||||
self = NM_BLUEZ4_MANAGER (user_data);
|
||||
priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
g_clear_object (&priv->proxy_cancellable);
|
||||
|
||||
if (!ret) {
|
||||
/* Ignore "No such adapter" errors; just means bluetooth isn't active */
|
||||
if ( !_nm_dbus_error_has_name (err, "org.bluez.Error.NoSuchAdapter")
|
||||
&& !_nm_dbus_error_has_name (err, "org.freedesktop.systemd1.LoadFailed")
|
||||
&& !g_error_matches (err, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) {
|
||||
g_dbus_error_strip_remote_error (err);
|
||||
nm_log_warn (LOGD_BT, "bluez error getting default adapter: %s",
|
||||
err->message);
|
||||
if ( !_nm_dbus_error_has_name (error, "org.bluez.Error.NoSuchAdapter")
|
||||
&& !_nm_dbus_error_has_name (error, "org.freedesktop.systemd1.LoadFailed")
|
||||
&& !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) {
|
||||
g_dbus_error_strip_remote_error (error);
|
||||
_LOGW ("bluez error getting default adapter: %s",
|
||||
error->message);
|
||||
}
|
||||
g_error_free (err);
|
||||
return;
|
||||
}
|
||||
|
||||
g_variant_get (ret, "(&o)", &default_adapter);
|
||||
default_adapter_changed (priv->proxy, default_adapter, self);
|
||||
}
|
||||
|
||||
static void
|
||||
query_default_adapter (NMBluez4Manager *self)
|
||||
name_owner_changed (NMBluez4Manager *self)
|
||||
{
|
||||
NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self);
|
||||
gs_free char *owner = NULL;
|
||||
|
||||
nm_clear_g_cancellable (&priv->proxy_cancellable);
|
||||
|
||||
owner = g_dbus_proxy_get_name_owner (priv->proxy);
|
||||
if (!owner) {
|
||||
/* Throwing away the adapter removes all devices too */
|
||||
g_clear_object (&priv->adapter);
|
||||
return;
|
||||
}
|
||||
|
||||
priv->proxy_cancellable = g_cancellable_new ();
|
||||
|
||||
g_dbus_proxy_call (priv->proxy, "DefaultAdapter",
|
||||
NULL,
|
||||
G_DBUS_CALL_FLAGS_NONE, -1,
|
||||
NULL,
|
||||
default_adapter_cb, self);
|
||||
priv->proxy_cancellable,
|
||||
default_adapter_cb,
|
||||
self);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -219,18 +245,43 @@ name_owner_changed_cb (GObject *object,
|
|||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMBluez4Manager *self = NM_BLUEZ4_MANAGER (user_data);
|
||||
NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self);
|
||||
char *owner;
|
||||
name_owner_changed (user_data);
|
||||
}
|
||||
|
||||
owner = g_dbus_proxy_get_name_owner (priv->proxy);
|
||||
if (owner) {
|
||||
query_default_adapter (self);
|
||||
g_free (owner);
|
||||
} else {
|
||||
/* Throwing away the adapter removes all devices too */
|
||||
g_clear_object (&priv->adapter);
|
||||
static void
|
||||
_proxy_new_cb (GObject *source_object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMBluez4Manager *self;
|
||||
NMBluez4ManagerPrivate *priv;
|
||||
gs_free_error GError *error = NULL;
|
||||
GDBusProxy *proxy;
|
||||
|
||||
proxy = g_dbus_proxy_new_for_bus_finish (result, &error);
|
||||
if ( !proxy
|
||||
&& g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
|
||||
self = user_data;
|
||||
priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
if (!proxy) {
|
||||
_LOGW ("bluez error creating D-Bus proxy: %s", error->message);
|
||||
g_clear_object (&priv->proxy_cancellable);
|
||||
return;
|
||||
}
|
||||
|
||||
priv->proxy = proxy;
|
||||
|
||||
_nm_dbus_signal_connect (priv->proxy, "AdapterRemoved", G_VARIANT_TYPE ("(o)"),
|
||||
G_CALLBACK (adapter_removed), self);
|
||||
_nm_dbus_signal_connect (priv->proxy, "DefaultAdapterChanged", G_VARIANT_TYPE ("(o)"),
|
||||
G_CALLBACK (default_adapter_changed), self);
|
||||
g_signal_connect (priv->proxy, "notify::g-name-owner",
|
||||
G_CALLBACK (name_owner_changed_cb), self);
|
||||
|
||||
name_owner_changed (self);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -240,21 +291,17 @@ nm_bluez4_manager_init (NMBluez4Manager *self)
|
|||
{
|
||||
NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
priv->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
|
||||
NULL,
|
||||
BLUEZ_SERVICE,
|
||||
BLUEZ_MANAGER_PATH,
|
||||
BLUEZ4_MANAGER_INTERFACE,
|
||||
NULL, NULL);
|
||||
_nm_dbus_signal_connect (priv->proxy, "AdapterRemoved", G_VARIANT_TYPE ("(o)"),
|
||||
G_CALLBACK (adapter_removed), self);
|
||||
_nm_dbus_signal_connect (priv->proxy, "DefaultAdapterChanged", G_VARIANT_TYPE ("(o)"),
|
||||
G_CALLBACK (default_adapter_changed), self);
|
||||
g_signal_connect (priv->proxy, "notify::g-name-owner",
|
||||
G_CALLBACK (name_owner_changed_cb), self);
|
||||
priv->proxy_cancellable = g_cancellable_new ();
|
||||
|
||||
query_default_adapter (self);
|
||||
g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
|
||||
NULL,
|
||||
BLUEZ_SERVICE,
|
||||
BLUEZ_MANAGER_PATH,
|
||||
BLUEZ4_MANAGER_INTERFACE,
|
||||
priv->proxy_cancellable,
|
||||
_proxy_new_cb,
|
||||
self);
|
||||
}
|
||||
|
||||
NMBluez4Manager *
|
||||
|
|
@ -275,7 +322,13 @@ dispose (GObject *object)
|
|||
NMBluez4Manager *self = NM_BLUEZ4_MANAGER (object);
|
||||
NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
g_clear_object (&priv->proxy);
|
||||
nm_clear_g_cancellable (&priv->proxy_cancellable);
|
||||
|
||||
if (priv->proxy) {
|
||||
g_signal_handlers_disconnect_by_data (priv->proxy, self);
|
||||
g_clear_object (&priv->proxy);
|
||||
}
|
||||
|
||||
g_clear_object (&priv->adapter);
|
||||
|
||||
G_OBJECT_CLASS (nm_bluez4_manager_parent_class)->dispose (object);
|
||||
|
|
|
|||
|
|
@ -40,15 +40,14 @@
|
|||
#include "nm-bt-error.h"
|
||||
#include "platform/nm-platform.h"
|
||||
|
||||
#include "devices/wwan/nm-modem-manager.h"
|
||||
#include "devices/wwan/nm-modem.h"
|
||||
|
||||
#include "introspection/org.freedesktop.NetworkManager.Device.Bluetooth.h"
|
||||
|
||||
#include "devices/nm-device-logging.h"
|
||||
_LOG_DECLARE_SELF(NMDeviceBt);
|
||||
|
||||
#define MM_DBUS_SERVICE "org.freedesktop.ModemManager1"
|
||||
#define MM_DBUS_PATH "/org/freedesktop/ModemManager1"
|
||||
#define MM_DBUS_INTERFACE "org.freedesktop.ModemManager1"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NM_GOBJECT_PROPERTIES_DEFINE_BASE (
|
||||
|
|
@ -65,7 +64,8 @@ enum {
|
|||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
typedef struct {
|
||||
GDBusProxy *mm_proxy;
|
||||
NMModemManager *modem_manager;
|
||||
|
||||
gboolean mm_running;
|
||||
|
||||
NMBluezDevice *bt_device;
|
||||
|
|
@ -967,9 +967,12 @@ is_available (NMDevice *dev, NMDeviceCheckDevAvailableFlags flags)
|
|||
}
|
||||
|
||||
static void
|
||||
set_mm_running (NMDeviceBt *self, gboolean running)
|
||||
set_mm_running (NMDeviceBt *self)
|
||||
{
|
||||
NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self);
|
||||
gboolean running;
|
||||
|
||||
running = (nm_modem_manager_name_owner_get (priv->modem_manager) != NULL);
|
||||
|
||||
if (priv->mm_running != running) {
|
||||
_LOGD (LOGD_BT, "ModemManager now %s",
|
||||
|
|
@ -983,18 +986,11 @@ set_mm_running (NMDeviceBt *self, gboolean running)
|
|||
}
|
||||
|
||||
static void
|
||||
mm_name_owner_changed (GObject *object,
|
||||
GParamSpec *pspec,
|
||||
NMDeviceBt *self)
|
||||
mm_name_owner_changed_cb (GObject *object,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
char *owner;
|
||||
|
||||
owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (object));
|
||||
if (owner) {
|
||||
set_mm_running (self, TRUE);
|
||||
g_free (owner);
|
||||
} else
|
||||
set_mm_running (self, FALSE);
|
||||
set_mm_running (user_data);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -1039,7 +1035,8 @@ set_property (GObject *object, guint prop_id,
|
|||
case PROP_BT_DEVICE:
|
||||
/* construct-only */
|
||||
priv->bt_device = g_value_dup_object (value);
|
||||
g_signal_connect (priv->bt_device, "removed", G_CALLBACK (bluez_device_removed), object);
|
||||
if (!priv->bt_device)
|
||||
g_return_if_reached ();
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
|
|
@ -1052,46 +1049,41 @@ set_property (GObject *object, guint prop_id,
|
|||
static void
|
||||
nm_device_bt_init (NMDeviceBt *self)
|
||||
{
|
||||
NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self);
|
||||
GError *error = NULL;
|
||||
|
||||
priv->mm_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS |
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
|
||||
NULL,
|
||||
MM_DBUS_SERVICE,
|
||||
MM_DBUS_PATH,
|
||||
MM_DBUS_INTERFACE,
|
||||
NULL, &error);
|
||||
if (priv->mm_proxy) {
|
||||
g_signal_connect (priv->mm_proxy, "notify::g-name-owner",
|
||||
G_CALLBACK (mm_name_owner_changed),
|
||||
self);
|
||||
mm_name_owner_changed (G_OBJECT (priv->mm_proxy), NULL, self);
|
||||
} else {
|
||||
_LOGW (LOGD_MB, "Could not create proxy for '%s': %s",
|
||||
MM_DBUS_SERVICE, error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
constructed (GObject *object)
|
||||
{
|
||||
NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE ((NMDeviceBt *) object);
|
||||
NMDeviceBt *self = NM_DEVICE_BT (object);
|
||||
NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self);
|
||||
const char *my_hwaddr;
|
||||
|
||||
G_OBJECT_CLASS (nm_device_bt_parent_class)->constructed (object);
|
||||
|
||||
my_hwaddr = nm_device_get_hw_address (NM_DEVICE (object));
|
||||
g_assert (my_hwaddr);
|
||||
priv->bdaddr = g_strdup (my_hwaddr);
|
||||
priv->modem_manager = g_object_ref (nm_modem_manager_get ());
|
||||
|
||||
/* Watch for BT device property changes */
|
||||
g_signal_connect (priv->bt_device, "notify::" NM_BLUEZ_DEVICE_CONNECTED,
|
||||
G_CALLBACK (bluez_connected_changed),
|
||||
object);
|
||||
nm_modem_manager_name_owner_ref (priv->modem_manager);
|
||||
|
||||
g_signal_connect (priv->modem_manager,
|
||||
"notify::"NM_MODEM_MANAGER_NAME_OWNER,
|
||||
G_CALLBACK (mm_name_owner_changed_cb),
|
||||
self);
|
||||
|
||||
if (priv->bt_device) {
|
||||
/* Watch for BT device property changes */
|
||||
g_signal_connect (priv->bt_device, "notify::" NM_BLUEZ_DEVICE_CONNECTED,
|
||||
G_CALLBACK (bluez_connected_changed),
|
||||
object);
|
||||
g_signal_connect (priv->bt_device, "removed", G_CALLBACK (bluez_device_removed), object);
|
||||
}
|
||||
|
||||
my_hwaddr = nm_device_get_hw_address (NM_DEVICE (object));
|
||||
if (my_hwaddr)
|
||||
priv->bdaddr = g_strdup (my_hwaddr);
|
||||
else
|
||||
g_warn_if_reached ();
|
||||
|
||||
set_mm_running (self);
|
||||
}
|
||||
|
||||
NMDevice *
|
||||
|
|
@ -1129,9 +1121,10 @@ dispose (GObject *object)
|
|||
|
||||
g_signal_handlers_disconnect_matched (priv->bt_device, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, object);
|
||||
|
||||
if (priv->mm_proxy) {
|
||||
g_signal_handlers_disconnect_by_func (priv->mm_proxy, G_CALLBACK (mm_name_owner_changed), object);
|
||||
g_clear_object (&priv->mm_proxy);
|
||||
if (priv->modem_manager) {
|
||||
g_signal_handlers_disconnect_by_func (priv->modem_manager, G_CALLBACK (mm_name_owner_changed_cb), object);
|
||||
nm_modem_manager_name_owner_unref (priv->modem_manager);
|
||||
g_clear_object (&priv->modem_manager);
|
||||
}
|
||||
|
||||
modem_cleanup (NM_DEVICE_BT (object));
|
||||
|
|
|
|||
|
|
@ -24,8 +24,6 @@
|
|||
#include "devices/nm-device.h"
|
||||
#include "nm-bluez-device.h"
|
||||
|
||||
#include "devices/wwan/nm-modem.h"
|
||||
|
||||
#define NM_TYPE_DEVICE_BT (nm_device_bt_get_type ())
|
||||
#define NM_DEVICE_BT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_BT, NMDeviceBt))
|
||||
#define NM_DEVICE_BT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_BT, NMDeviceBtClass))
|
||||
|
|
@ -52,8 +50,10 @@ NMDevice *nm_device_bt_new (NMBluezDevice *bt_device,
|
|||
|
||||
guint32 nm_device_bt_get_capabilities (NMDeviceBt *device);
|
||||
|
||||
struct _NMModem;
|
||||
|
||||
gboolean nm_device_bt_modem_added (NMDeviceBt *device,
|
||||
NMModem *modem,
|
||||
struct _NMModem *modem,
|
||||
const char *driver);
|
||||
|
||||
#endif /* __NETWORKMANAGER_DEVICE_BT_H__ */
|
||||
|
|
|
|||
|
|
@ -20,7 +20,11 @@ global:
|
|||
nm_modem_get_type;
|
||||
nm_modem_get_uid;
|
||||
nm_modem_ip4_pre_commit;
|
||||
nm_modem_manager_get;
|
||||
nm_modem_manager_get_type;
|
||||
nm_modem_manager_name_owner_get;
|
||||
nm_modem_manager_name_owner_ref;
|
||||
nm_modem_manager_name_owner_unref;
|
||||
nm_modem_owns_port;
|
||||
nm_modem_set_mm_enabled;
|
||||
nm_modem_stage3_ip4_config_start;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -34,9 +34,22 @@
|
|||
|
||||
#define NM_MODEM_MANAGER_MODEM_ADDED "modem-added"
|
||||
|
||||
#define NM_MODEM_MANAGER_NAME_OWNER "name-owner"
|
||||
|
||||
#define NM_MODEM_MANAGER_MM_DBUS_SERVICE "org.freedesktop.ModemManager1"
|
||||
#define NM_MODEM_MANAGER_MM_DBUS_PATH "/org/freedesktop/ModemManager1"
|
||||
#define NM_MODEM_MANAGER_MM_DBUS_INTERFACE "org.freedesktop.ModemManager1"
|
||||
|
||||
typedef struct _NMModemManager NMModemManager;
|
||||
typedef struct _NMModemManagerClass NMModemManagerClass;
|
||||
|
||||
GType nm_modem_manager_get_type (void);
|
||||
|
||||
NMModemManager *nm_modem_manager_get (void);
|
||||
|
||||
void nm_modem_manager_name_owner_ref (NMModemManager *self);
|
||||
void nm_modem_manager_name_owner_unref (NMModemManager *self);
|
||||
|
||||
const char *nm_modem_manager_name_owner_get (NMModemManager *self);
|
||||
|
||||
#endif /* __NETWORKMANAGER_MODEM_MANAGER_H__ */
|
||||
|
|
|
|||
|
|
@ -46,6 +46,11 @@ typedef struct {
|
|||
GDBusProxy *context_proxy;
|
||||
GDBusProxy *sim_proxy;
|
||||
|
||||
GCancellable *modem_proxy_cancellable;
|
||||
GCancellable *connman_proxy_cancellable;
|
||||
GCancellable *context_proxy_cancellable;
|
||||
GCancellable *sim_proxy_cancellable;
|
||||
|
||||
GError *property_error;
|
||||
|
||||
char *context_path;
|
||||
|
|
@ -165,28 +170,16 @@ typedef struct {
|
|||
static void
|
||||
disconnect_context_complete (DisconnectContext *ctx)
|
||||
{
|
||||
g_simple_async_result_complete_in_idle (ctx->result);
|
||||
if (ctx->cancellable)
|
||||
g_object_unref (ctx->cancellable);
|
||||
g_object_unref (ctx->result);
|
||||
if (ctx->result) {
|
||||
g_simple_async_result_complete_in_idle (ctx->result);
|
||||
g_object_unref (ctx->result);
|
||||
}
|
||||
g_object_unref (ctx->self);
|
||||
g_slice_free (DisconnectContext, ctx);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
disconnect_context_complete_if_cancelled (DisconnectContext *ctx)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (g_cancellable_set_error_if_cancelled (ctx->cancellable, &error)) {
|
||||
g_simple_async_result_take_error (ctx->result, error);
|
||||
disconnect_context_complete (ctx);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
disconnect_finish (NMModem *self,
|
||||
GAsyncResult *result,
|
||||
|
|
@ -196,25 +189,25 @@ disconnect_finish (NMModem *self,
|
|||
}
|
||||
|
||||
static void
|
||||
disconnect_done (GDBusProxy *proxy,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
disconnect_done (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
DisconnectContext *ctx = (DisconnectContext*) user_data;
|
||||
NMModemOfono *self = ctx->self;
|
||||
GError *error = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
gs_unref_variant GVariant *v = NULL;
|
||||
|
||||
g_dbus_proxy_call_finish (proxy, result, &error);
|
||||
v = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), result, &error);
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
||||
_LOGD ("disconnect cancelled");
|
||||
if (ctx->result)
|
||||
g_simple_async_result_take_error (ctx->result, g_steal_pointer (&error));
|
||||
disconnect_context_complete (ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
if (ctx->warn)
|
||||
_LOGW ("failed to disconnect modem: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
if (error && ctx->warn)
|
||||
_LOGW ("failed to disconnect modem: %s", error->message);
|
||||
|
||||
_LOGD ("modem disconnected");
|
||||
|
||||
|
|
@ -233,18 +226,15 @@ disconnect (NMModem *modem,
|
|||
NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self);
|
||||
DisconnectContext *ctx;
|
||||
NMModemState state = nm_modem_get_state (NM_MODEM (self));
|
||||
GError *error = NULL;
|
||||
|
||||
_LOGD ("warn: %s modem_state: %s",
|
||||
warn ? "TRUE" : "FALSE",
|
||||
nm_modem_state_to_string (state));
|
||||
|
||||
if (state != NM_MODEM_STATE_CONNECTED)
|
||||
return;
|
||||
|
||||
ctx = g_slice_new (DisconnectContext);
|
||||
ctx = g_slice_new0 (DisconnectContext);
|
||||
ctx->self = g_object_ref (self);
|
||||
ctx->warn = warn;
|
||||
|
||||
if (callback) {
|
||||
ctx->result = g_simple_async_result_new (G_OBJECT (self),
|
||||
callback,
|
||||
|
|
@ -252,9 +242,28 @@ disconnect (NMModem *modem,
|
|||
disconnect);
|
||||
}
|
||||
|
||||
ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
|
||||
if (disconnect_context_complete_if_cancelled (ctx))
|
||||
if (state != NM_MODEM_STATE_CONNECTED) {
|
||||
if (ctx->result) {
|
||||
g_set_error_literal (&error,
|
||||
NM_UTILS_ERROR,
|
||||
NM_UTILS_ERROR_UNKNOWN,
|
||||
("modem is currently not connected"));
|
||||
g_simple_async_result_take_error (ctx->result, error);
|
||||
}
|
||||
disconnect_context_complete (ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_cancellable_set_error_if_cancelled (cancellable, &error)) {
|
||||
if (ctx->result)
|
||||
g_simple_async_result_take_error (ctx->result, error);
|
||||
else
|
||||
g_clear_error (&error);
|
||||
disconnect_context_complete (ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->cancellable = nm_g_object_ref (cancellable);
|
||||
|
||||
nm_modem_set_state (NM_MODEM (self),
|
||||
NM_MODEM_STATE_DISCONNECTING,
|
||||
|
|
@ -267,8 +276,8 @@ disconnect (NMModem *modem,
|
|||
g_variant_new ("b", warn)),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
20000,
|
||||
NULL,
|
||||
(GAsyncReadyCallback) disconnect_done,
|
||||
ctx->cancellable,
|
||||
disconnect_done,
|
||||
ctx);
|
||||
}
|
||||
|
||||
|
|
@ -375,22 +384,35 @@ sim_property_changed (GDBusProxy *proxy,
|
|||
}
|
||||
|
||||
static void
|
||||
sim_get_properties_done (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
|
||||
sim_get_properties_done (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
gs_unref_object NMModemOfono *self = NM_MODEM_OFONO (user_data);
|
||||
GError *error = NULL;
|
||||
GVariant *v_properties, *v_dict, *v;
|
||||
NMModemOfono *self;
|
||||
NMModemOfonoPrivate *priv;
|
||||
gs_free_error GError *error = NULL;
|
||||
gs_unref_variant GVariant *v_properties = NULL;
|
||||
gs_unref_variant GVariant *v_dict = NULL;
|
||||
GVariant *v;
|
||||
GVariantIter i;
|
||||
const char *property;
|
||||
|
||||
v_properties = _nm_dbus_proxy_call_finish (proxy,
|
||||
v_properties = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (source),
|
||||
result,
|
||||
G_VARIANT_TYPE ("(a{sv})"),
|
||||
&error);
|
||||
if ( !v_properties
|
||||
&& g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
|
||||
self = NM_MODEM_OFONO (user_data);
|
||||
priv = NM_MODEM_OFONO_GET_PRIVATE (self);
|
||||
|
||||
g_clear_object (&priv->sim_proxy_cancellable);
|
||||
|
||||
if (!v_properties) {
|
||||
g_dbus_error_strip_remote_error (error);
|
||||
_LOGW ("error getting sim properties: %s", error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -418,9 +440,49 @@ sim_get_properties_done (GDBusProxy *proxy, GAsyncResult *result, gpointer user_
|
|||
handle_sim_property (NULL, property, v, self);
|
||||
g_variant_unref (v);
|
||||
}
|
||||
}
|
||||
|
||||
g_variant_unref (v_dict);
|
||||
g_variant_unref (v_properties);
|
||||
static void
|
||||
_sim_proxy_new_cb (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMModemOfono *self;
|
||||
NMModemOfonoPrivate *priv;
|
||||
gs_free_error GError *error = NULL;
|
||||
GDBusProxy *proxy;
|
||||
|
||||
proxy = g_dbus_proxy_new_for_bus_finish (result, &error);
|
||||
if ( !proxy
|
||||
&& g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
|
||||
self = user_data;
|
||||
priv = NM_MODEM_OFONO_GET_PRIVATE (self);
|
||||
|
||||
if (!proxy) {
|
||||
_LOGW ("failed to create SimManager proxy: %s", error->message);
|
||||
g_clear_object (&priv->sim_proxy_cancellable);
|
||||
return;
|
||||
}
|
||||
|
||||
priv->sim_proxy = proxy;
|
||||
|
||||
/* Watch for custom ofono PropertyChanged signals */
|
||||
_nm_dbus_signal_connect (priv->sim_proxy,
|
||||
"PropertyChanged",
|
||||
G_VARIANT_TYPE ("(sv)"),
|
||||
G_CALLBACK (sim_property_changed),
|
||||
self);
|
||||
|
||||
g_dbus_proxy_call (priv->sim_proxy,
|
||||
"GetProperties",
|
||||
NULL,
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
20000,
|
||||
priv->sim_proxy_cancellable,
|
||||
sim_get_properties_done,
|
||||
self);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -430,47 +492,30 @@ handle_sim_iface (NMModemOfono *self, gboolean found)
|
|||
|
||||
_LOGD ("SimManager interface %sfound", found ? "" : "not ");
|
||||
|
||||
if (!found && priv->sim_proxy) {
|
||||
if (!found && (priv->sim_proxy || priv->sim_proxy_cancellable)) {
|
||||
_LOGI ("SimManager interface disappeared");
|
||||
g_signal_handlers_disconnect_by_data (priv->sim_proxy, NM_MODEM_OFONO (self));
|
||||
g_clear_object (&priv->sim_proxy);
|
||||
nm_clear_g_cancellable (&priv->sim_proxy_cancellable);
|
||||
if (priv->sim_proxy) {
|
||||
g_signal_handlers_disconnect_by_data (priv->sim_proxy, self);
|
||||
g_clear_object (&priv->sim_proxy);
|
||||
}
|
||||
g_clear_pointer (&priv->imsi, g_free);
|
||||
update_modem_state (self);
|
||||
} else if (found && !priv->sim_proxy) {
|
||||
GError *error = NULL;
|
||||
|
||||
} else if (found && (!priv->sim_proxy && !priv->sim_proxy_cancellable)) {
|
||||
_LOGI ("found new SimManager interface");
|
||||
|
||||
priv->sim_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES
|
||||
| G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
|
||||
NULL, /* GDBusInterfaceInfo */
|
||||
OFONO_DBUS_SERVICE,
|
||||
nm_modem_get_path (NM_MODEM (self)),
|
||||
OFONO_DBUS_INTERFACE_SIM_MANAGER,
|
||||
NULL, /* GCancellable */
|
||||
&error);
|
||||
if (priv->sim_proxy == NULL) {
|
||||
_LOGW ("failed to create SimManager proxy: %s", error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
priv->sim_proxy_cancellable = g_cancellable_new ();
|
||||
|
||||
/* Watch for custom ofono PropertyChanged signals */
|
||||
_nm_dbus_signal_connect (priv->sim_proxy,
|
||||
"PropertyChanged",
|
||||
G_VARIANT_TYPE ("(sv)"),
|
||||
G_CALLBACK (sim_property_changed),
|
||||
self);
|
||||
|
||||
g_dbus_proxy_call (priv->sim_proxy,
|
||||
"GetProperties",
|
||||
NULL,
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
20000,
|
||||
NULL,
|
||||
(GAsyncReadyCallback) sim_get_properties_done,
|
||||
g_object_ref (self));
|
||||
g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES
|
||||
| G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
|
||||
NULL, /* GDBusInterfaceInfo */
|
||||
OFONO_DBUS_SERVICE,
|
||||
nm_modem_get_path (NM_MODEM (self)),
|
||||
OFONO_DBUS_INTERFACE_SIM_MANAGER,
|
||||
priv->sim_proxy_cancellable, /* GCancellable */
|
||||
_sim_proxy_new_cb,
|
||||
self);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -514,22 +559,35 @@ connman_property_changed (GDBusProxy *proxy,
|
|||
}
|
||||
|
||||
static void
|
||||
connman_get_properties_done (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
|
||||
connman_get_properties_done (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
gs_unref_object NMModemOfono *self = NM_MODEM_OFONO (user_data);
|
||||
GError *error = NULL;
|
||||
GVariant *v_properties, *v_dict, *v;
|
||||
NMModemOfono *self;
|
||||
NMModemOfonoPrivate *priv;
|
||||
gs_free_error GError *error = NULL;
|
||||
gs_unref_variant GVariant *v_properties = NULL;
|
||||
gs_unref_variant GVariant *v_dict = NULL;
|
||||
GVariant *v;
|
||||
GVariantIter i;
|
||||
const char *property;
|
||||
|
||||
v_properties = _nm_dbus_proxy_call_finish (proxy,
|
||||
result,
|
||||
G_VARIANT_TYPE ("(a{sv})"),
|
||||
&error);
|
||||
v_properties = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (source),
|
||||
result,
|
||||
G_VARIANT_TYPE ("(a{sv})"),
|
||||
&error);
|
||||
if ( !v_properties
|
||||
&& g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
|
||||
self = NM_MODEM_OFONO (user_data);
|
||||
priv = NM_MODEM_OFONO_GET_PRIVATE (self);
|
||||
|
||||
g_clear_object (&priv->connman_proxy_cancellable);
|
||||
|
||||
if (!v_properties) {
|
||||
g_dbus_error_strip_remote_error (error);
|
||||
_LOGW ("error getting connman properties: %s", error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -549,9 +607,48 @@ connman_get_properties_done (GDBusProxy *proxy, GAsyncResult *result, gpointer u
|
|||
handle_connman_property (NULL, property, v, self);
|
||||
g_variant_unref (v);
|
||||
}
|
||||
}
|
||||
|
||||
g_variant_unref (v_dict);
|
||||
g_variant_unref (v_properties);
|
||||
static void
|
||||
_connman_proxy_new_cb (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMModemOfono *self;
|
||||
NMModemOfonoPrivate *priv;
|
||||
gs_free_error GError *error = NULL;
|
||||
GDBusProxy *proxy;
|
||||
|
||||
proxy = g_dbus_proxy_new_for_bus_finish (result, &error);
|
||||
if ( !proxy
|
||||
&& g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
|
||||
self = user_data;
|
||||
priv = NM_MODEM_OFONO_GET_PRIVATE (self);
|
||||
|
||||
if (!proxy) {
|
||||
_LOGW ("failed to create ConnectionManager proxy: %s", error->message);
|
||||
g_clear_object (&priv->connman_proxy_cancellable);
|
||||
return;
|
||||
}
|
||||
|
||||
priv->connman_proxy = proxy;
|
||||
|
||||
_nm_dbus_signal_connect (priv->connman_proxy,
|
||||
"PropertyChanged",
|
||||
G_VARIANT_TYPE ("(sv)"),
|
||||
G_CALLBACK (connman_property_changed),
|
||||
self);
|
||||
|
||||
g_dbus_proxy_call (priv->connman_proxy,
|
||||
"GetProperties",
|
||||
NULL,
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
20000,
|
||||
priv->connman_proxy_cancellable,
|
||||
connman_get_properties_done,
|
||||
self);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -561,11 +658,13 @@ handle_connman_iface (NMModemOfono *self, gboolean found)
|
|||
|
||||
_LOGD ("ConnectionManager interface %sfound", found ? "" : "not ");
|
||||
|
||||
if (!found && priv->connman_proxy) {
|
||||
if (!found && (priv->connman_proxy || priv->connman_proxy_cancellable)) {
|
||||
_LOGI ("ConnectionManager interface disappeared");
|
||||
|
||||
g_signal_handlers_disconnect_by_data (priv->connman_proxy, NM_MODEM_OFONO (self));
|
||||
g_clear_object (&priv->connman_proxy);
|
||||
nm_clear_g_cancellable (&priv->connman_proxy_cancellable);
|
||||
if (priv->connman_proxy) {
|
||||
g_signal_handlers_disconnect_by_data (priv->connman_proxy, self);
|
||||
g_clear_object (&priv->connman_proxy);
|
||||
}
|
||||
|
||||
/* The connection manager proxy disappeared, we should
|
||||
* consider the modem disabled.
|
||||
|
|
@ -573,41 +672,21 @@ handle_connman_iface (NMModemOfono *self, gboolean found)
|
|||
priv->gprs_attached = FALSE;
|
||||
|
||||
update_modem_state (self);
|
||||
} else if (found && !priv->connman_proxy) {
|
||||
GError *error = NULL;
|
||||
|
||||
} else if (found && (!priv->connman_proxy && !priv->connman_proxy_cancellable)) {
|
||||
_LOGI ("found new ConnectionManager interface");
|
||||
|
||||
priv->connman_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES
|
||||
| G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
|
||||
NULL, /* GDBusInterfaceInfo */
|
||||
OFONO_DBUS_SERVICE,
|
||||
nm_modem_get_path (NM_MODEM (self)),
|
||||
OFONO_DBUS_INTERFACE_CONNECTION_MANAGER,
|
||||
NULL, /* GCancellable */
|
||||
&error);
|
||||
if (priv->connman_proxy == NULL) {
|
||||
_LOGW ("failed to create ConnectionManager proxy: %s", error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
priv->connman_proxy_cancellable = g_cancellable_new ();
|
||||
|
||||
/* Watch for custom ofono PropertyChanged signals */
|
||||
_nm_dbus_signal_connect (priv->connman_proxy,
|
||||
"PropertyChanged",
|
||||
G_VARIANT_TYPE ("(sv)"),
|
||||
G_CALLBACK (connman_property_changed),
|
||||
self);
|
||||
|
||||
g_dbus_proxy_call (priv->connman_proxy,
|
||||
"GetProperties",
|
||||
NULL,
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
20000,
|
||||
NULL,
|
||||
(GAsyncReadyCallback) connman_get_properties_done,
|
||||
g_object_ref (self));
|
||||
g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES
|
||||
| G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
|
||||
NULL, /* GDBusInterfaceInfo */
|
||||
OFONO_DBUS_SERVICE,
|
||||
nm_modem_get_path (NM_MODEM (self)),
|
||||
OFONO_DBUS_INTERFACE_CONNECTION_MANAGER,
|
||||
priv->connman_proxy_cancellable,
|
||||
_connman_proxy_new_cb,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -667,22 +746,35 @@ modem_property_changed (GDBusProxy *proxy,
|
|||
}
|
||||
|
||||
static void
|
||||
modem_get_properties_done (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
|
||||
modem_get_properties_done (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
gs_unref_object NMModemOfono *self = NM_MODEM_OFONO (user_data);
|
||||
GError *error = NULL;
|
||||
GVariant *v_properties, *v_dict, *v;
|
||||
NMModemOfono *self;
|
||||
NMModemOfonoPrivate *priv;
|
||||
gs_free_error GError *error = NULL;
|
||||
gs_unref_variant GVariant *v_properties = NULL;
|
||||
gs_unref_variant GVariant *v_dict = NULL;
|
||||
GVariant *v;
|
||||
GVariantIter i;
|
||||
const char *property;
|
||||
|
||||
v_properties = _nm_dbus_proxy_call_finish (proxy,
|
||||
v_properties = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (source),
|
||||
result,
|
||||
G_VARIANT_TYPE ("(a{sv})"),
|
||||
&error);
|
||||
if ( !v_properties
|
||||
&& g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
|
||||
self = NM_MODEM_OFONO (user_data);
|
||||
priv = NM_MODEM_OFONO_GET_PRIVATE (self);
|
||||
|
||||
g_clear_object (&priv->modem_proxy_cancellable);
|
||||
|
||||
if (!v_properties) {
|
||||
g_dbus_error_strip_remote_error (error);
|
||||
_LOGW ("error getting modem properties: %s", error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -706,21 +798,29 @@ modem_get_properties_done (GDBusProxy *proxy, GAsyncResult *result, gpointer use
|
|||
handle_modem_property (NULL, property, v, self);
|
||||
g_variant_unref (v);
|
||||
}
|
||||
|
||||
g_variant_unref (v_dict);
|
||||
g_variant_unref (v_properties);
|
||||
}
|
||||
|
||||
static void
|
||||
stage1_prepare_done (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
|
||||
stage1_prepare_done (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
gs_unref_object NMModemOfono *self = NM_MODEM_OFONO (user_data);
|
||||
NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self);
|
||||
GError *error = NULL;
|
||||
NMModemOfono *self;
|
||||
NMModemOfonoPrivate *priv;
|
||||
gs_free_error GError *error = NULL;
|
||||
gs_unref_variant GVariant *v = NULL;
|
||||
|
||||
v = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), result, &error);
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
|
||||
self = NM_MODEM_OFONO (user_data);
|
||||
priv = NM_MODEM_OFONO_GET_PRIVATE (self);
|
||||
|
||||
g_clear_object (&priv->context_proxy_cancellable);
|
||||
|
||||
g_clear_pointer (&priv->connect_properties, g_hash_table_destroy);
|
||||
|
||||
g_dbus_proxy_call_finish (proxy, result, &error);
|
||||
if (error) {
|
||||
_LOGW ("connection failed: %s", error->message);
|
||||
|
||||
|
|
@ -732,8 +832,6 @@ stage1_prepare_done (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data
|
|||
* leading to the connection being disabled, and a 5m
|
||||
* timeout...
|
||||
*/
|
||||
|
||||
g_clear_error (&error);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -946,21 +1044,33 @@ static_stage3_ip4_config_start (NMModem *modem,
|
|||
}
|
||||
|
||||
static void
|
||||
context_proxy_new_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
|
||||
context_proxy_new_cb (GObject *source, GAsyncResult *result, gpointer user_data)
|
||||
{
|
||||
gs_unref_object NMModemOfono *self = NM_MODEM_OFONO (user_data);
|
||||
NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self);
|
||||
GError *error = NULL;
|
||||
NMModemOfono *self;
|
||||
NMModemOfonoPrivate *priv;
|
||||
gs_free_error GError *error = NULL;
|
||||
GDBusProxy *proxy;
|
||||
|
||||
priv->context_proxy = g_dbus_proxy_new_for_bus_finish (result, &error);
|
||||
if (error) {
|
||||
proxy = g_dbus_proxy_new_for_bus_finish (result, &error);
|
||||
if ( !proxy
|
||||
|| g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
|
||||
self = NM_MODEM_OFONO (user_data);
|
||||
priv = NM_MODEM_OFONO_GET_PRIVATE (self);
|
||||
|
||||
if (!proxy) {
|
||||
_LOGE ("failed to create ofono ConnectionContext DBus proxy: %s", error->message);
|
||||
g_clear_object (&priv->context_proxy_cancellable);
|
||||
nm_modem_emit_prepare_result (NM_MODEM (self), FALSE,
|
||||
NM_DEVICE_STATE_REASON_MODEM_BUSY);
|
||||
return;
|
||||
}
|
||||
|
||||
priv->context_proxy = proxy;
|
||||
|
||||
if (!priv->gprs_attached) {
|
||||
g_clear_object (&priv->context_proxy_cancellable);
|
||||
nm_modem_emit_prepare_result (NM_MODEM (self), FALSE,
|
||||
NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER);
|
||||
return;
|
||||
|
|
@ -972,7 +1082,6 @@ context_proxy_new_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_dat
|
|||
*/
|
||||
g_clear_object (&priv->ip4_config);
|
||||
|
||||
/* Watch for custom ofono PropertyChanged signals */
|
||||
_nm_dbus_signal_connect (priv->context_proxy,
|
||||
"PropertyChanged",
|
||||
G_VARIANT_TYPE ("(sv)"),
|
||||
|
|
@ -986,9 +1095,9 @@ context_proxy_new_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_dat
|
|||
g_variant_new ("b", TRUE)),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
20000,
|
||||
NULL,
|
||||
(GAsyncReadyCallback) stage1_prepare_done,
|
||||
g_object_ref (self));
|
||||
priv->context_proxy_cancellable,
|
||||
stage1_prepare_done,
|
||||
self);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -998,16 +1107,20 @@ do_context_activate (NMModemOfono *self)
|
|||
|
||||
g_return_if_fail (NM_IS_MODEM_OFONO (self));
|
||||
|
||||
nm_clear_g_cancellable (&priv->context_proxy_cancellable);
|
||||
g_clear_object (&priv->context_proxy);
|
||||
|
||||
priv->context_proxy_cancellable = g_cancellable_new ();
|
||||
|
||||
g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
|
||||
NULL,
|
||||
OFONO_DBUS_SERVICE,
|
||||
priv->context_path,
|
||||
OFONO_DBUS_INTERFACE_CONNECTION_CONTEXT,
|
||||
NULL,
|
||||
(GAsyncReadyCallback) context_proxy_new_cb,
|
||||
g_object_ref (self));
|
||||
priv->context_proxy_cancellable,
|
||||
context_proxy_new_cb,
|
||||
self);
|
||||
}
|
||||
|
||||
static GHashTable *
|
||||
|
|
@ -1081,19 +1194,29 @@ act_stage1_prepare (NMModem *modem,
|
|||
}
|
||||
|
||||
static void
|
||||
modem_proxy_new_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
|
||||
modem_proxy_new_cb (GObject *source, GAsyncResult *result, gpointer user_data)
|
||||
{
|
||||
gs_unref_object NMModemOfono *self = NM_MODEM_OFONO (user_data);
|
||||
NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self);
|
||||
GError *error = NULL;
|
||||
NMModemOfono *self;
|
||||
NMModemOfonoPrivate *priv;
|
||||
gs_free_error GError *error = NULL;
|
||||
GDBusProxy *proxy;
|
||||
|
||||
priv->modem_proxy = g_dbus_proxy_new_for_bus_finish (result, &error);
|
||||
if (error) {
|
||||
proxy = g_dbus_proxy_new_for_bus_finish (result, &error);
|
||||
if ( !proxy
|
||||
&& g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
|
||||
self = NM_MODEM_OFONO (user_data);
|
||||
priv = NM_MODEM_OFONO_GET_PRIVATE (self);
|
||||
|
||||
if (!proxy) {
|
||||
_LOGE ("failed to create ofono modem DBus proxy: %s", error->message);
|
||||
g_clear_object (&priv->modem_proxy_cancellable);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Watch for custom ofono PropertyChanged signals */
|
||||
priv->modem_proxy = proxy;
|
||||
|
||||
_nm_dbus_signal_connect (priv->modem_proxy,
|
||||
"PropertyChanged",
|
||||
G_VARIANT_TYPE ("(sv)"),
|
||||
|
|
@ -1105,9 +1228,9 @@ modem_proxy_new_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
|
|||
NULL,
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
20000,
|
||||
NULL,
|
||||
(GAsyncReadyCallback) modem_get_properties_done,
|
||||
g_object_ref (self));
|
||||
priv->modem_proxy_cancellable,
|
||||
modem_get_properties_done,
|
||||
self);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -1121,6 +1244,9 @@ static void
|
|||
constructed (GObject *object)
|
||||
{
|
||||
NMModemOfono *self = NM_MODEM_OFONO (object);
|
||||
NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self);
|
||||
|
||||
priv->modem_proxy_cancellable = g_cancellable_new ();
|
||||
|
||||
g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
|
||||
|
|
@ -1128,9 +1254,11 @@ constructed (GObject *object)
|
|||
OFONO_DBUS_SERVICE,
|
||||
nm_modem_get_path (NM_MODEM (self)),
|
||||
OFONO_DBUS_INTERFACE_MODEM,
|
||||
NULL,
|
||||
(GAsyncReadyCallback) modem_proxy_new_cb,
|
||||
g_object_ref (self));
|
||||
priv->modem_proxy_cancellable,
|
||||
modem_proxy_new_cb,
|
||||
self);
|
||||
|
||||
G_OBJECT_CLASS (nm_modem_ofono_parent_class)->constructed (object);
|
||||
}
|
||||
|
||||
NMModem *
|
||||
|
|
@ -1163,6 +1291,11 @@ dispose (GObject *object)
|
|||
NMModemOfono *self = NM_MODEM_OFONO (object);
|
||||
NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self);
|
||||
|
||||
nm_clear_g_cancellable (&priv->modem_proxy_cancellable);
|
||||
nm_clear_g_cancellable (&priv->connman_proxy_cancellable);
|
||||
nm_clear_g_cancellable (&priv->context_proxy_cancellable);
|
||||
nm_clear_g_cancellable (&priv->sim_proxy_cancellable);
|
||||
|
||||
if (priv->connect_properties) {
|
||||
g_hash_table_destroy (priv->connect_properties);
|
||||
priv->connect_properties = NULL;
|
||||
|
|
@ -1171,15 +1304,22 @@ dispose (GObject *object)
|
|||
g_clear_object (&priv->ip4_config);
|
||||
|
||||
if (priv->modem_proxy) {
|
||||
g_signal_handlers_disconnect_by_data (priv->modem_proxy, NM_MODEM_OFONO (self));
|
||||
g_signal_handlers_disconnect_by_data (priv->modem_proxy, self);
|
||||
g_clear_object (&priv->modem_proxy);
|
||||
}
|
||||
|
||||
g_clear_object (&priv->connman_proxy);
|
||||
g_clear_object (&priv->context_proxy);
|
||||
if (priv->connman_proxy) {
|
||||
g_signal_handlers_disconnect_by_data (priv->connman_proxy, self);
|
||||
g_clear_object (&priv->connman_proxy);
|
||||
}
|
||||
|
||||
if (priv->context_proxy) {
|
||||
g_signal_handlers_disconnect_by_data (priv->context_proxy, self);
|
||||
g_clear_object (&priv->context_proxy);
|
||||
}
|
||||
|
||||
if (priv->sim_proxy) {
|
||||
g_signal_handlers_disconnect_by_data (priv->sim_proxy, NM_MODEM_OFONO (self));
|
||||
g_signal_handlers_disconnect_by_data (priv->sim_proxy, self);
|
||||
g_clear_object (&priv->sim_proxy);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1451,6 +1451,7 @@ set_property (GObject *object, guint prop_id,
|
|||
case PROP_PATH:
|
||||
/* construct-only */
|
||||
priv->path = g_value_dup_string (value);
|
||||
g_return_if_fail (priv->path);
|
||||
break;
|
||||
case PROP_DRIVER:
|
||||
/* construct-only */
|
||||
|
|
@ -1512,37 +1513,16 @@ nm_modem_init (NMModem *self)
|
|||
self->_priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_MODEM, NMModemPrivate);
|
||||
}
|
||||
|
||||
static GObject*
|
||||
constructor (GType type,
|
||||
guint n_construct_params,
|
||||
GObjectConstructParam *construct_params)
|
||||
static void
|
||||
constructed (GObject *object)
|
||||
{
|
||||
GObject *object;
|
||||
NMModemPrivate *priv;
|
||||
|
||||
object = G_OBJECT_CLASS (nm_modem_parent_class)->constructor (type,
|
||||
n_construct_params,
|
||||
construct_params);
|
||||
if (!object)
|
||||
return NULL;
|
||||
G_OBJECT_CLASS (nm_modem_parent_class)->constructed (object);
|
||||
|
||||
priv = NM_MODEM_GET_PRIVATE ((NMModem *) object);
|
||||
priv = NM_MODEM_GET_PRIVATE (NM_MODEM (object));
|
||||
|
||||
if (!priv->data_port && !priv->control_port) {
|
||||
nm_log_err (LOGD_PLATFORM, "neither modem command nor data interface provided");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!priv->path) {
|
||||
nm_log_err (LOGD_PLATFORM, "D-Bus path not provided");
|
||||
goto err;
|
||||
}
|
||||
|
||||
return object;
|
||||
|
||||
err:
|
||||
g_object_unref (object);
|
||||
return NULL;
|
||||
g_return_if_fail (priv->data_port || priv->control_port);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -1552,10 +1532,7 @@ dispose (GObject *object)
|
|||
{
|
||||
NMModemPrivate *priv = NM_MODEM_GET_PRIVATE ((NMModem *) object);
|
||||
|
||||
if (priv->act_request) {
|
||||
g_object_unref (priv->act_request);
|
||||
priv->act_request = NULL;
|
||||
}
|
||||
g_clear_object (&priv->act_request);
|
||||
|
||||
G_OBJECT_CLASS (nm_modem_parent_class)->dispose (object);
|
||||
}
|
||||
|
|
@ -1584,7 +1561,7 @@ nm_modem_class_init (NMModemClass *klass)
|
|||
|
||||
g_type_class_add_private (object_class, sizeof (NMModemPrivate));
|
||||
|
||||
object_class->constructor = constructor;
|
||||
object_class->constructed = constructed;
|
||||
object_class->set_property = set_property;
|
||||
object_class->get_property = get_property;
|
||||
object_class->dispose = dispose;
|
||||
|
|
|
|||
|
|
@ -105,10 +105,12 @@ typedef enum { /*< underscore_name=nm_modem_state >*/
|
|||
|
||||
struct _NMModemPrivate;
|
||||
|
||||
typedef struct {
|
||||
struct _NMModem {
|
||||
GObject parent;
|
||||
struct _NMModemPrivate *_priv;
|
||||
} NMModem;
|
||||
};
|
||||
|
||||
typedef struct _NMModem NMModem;
|
||||
|
||||
typedef struct {
|
||||
GObjectClass parent;
|
||||
|
|
|
|||
|
|
@ -127,8 +127,8 @@ start (NMDeviceFactory *factory)
|
|||
NMWwanFactory *self = NM_WWAN_FACTORY (factory);
|
||||
NMWwanFactoryPrivate *priv = NM_WWAN_FACTORY_GET_PRIVATE (self);
|
||||
|
||||
priv->mm = g_object_new (NM_TYPE_MODEM_MANAGER, NULL);
|
||||
g_assert (priv->mm);
|
||||
priv->mm = g_object_ref (nm_modem_manager_get ());
|
||||
|
||||
g_signal_connect (priv->mm,
|
||||
NM_MODEM_MANAGER_MODEM_ADDED,
|
||||
G_CALLBACK (modem_added_cb),
|
||||
|
|
|
|||
|
|
@ -1435,6 +1435,7 @@ nm_dns_manager_set_initial_hostname (NMDnsManager *self,
|
|||
{
|
||||
NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
g_free (priv->hostname);
|
||||
priv->hostname = g_strdup (hostname);
|
||||
}
|
||||
|
||||
|
|
|
|||
661
src/nm-hostname-manager.c
Normal file
661
src/nm-hostname-manager.c
Normal file
|
|
@ -0,0 +1,661 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
/* NetworkManager
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* (C) Copyright 2017 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#include "nm-default.h"
|
||||
|
||||
#include "nm-hostname-manager.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#if HAVE_SELINUX
|
||||
#include <selinux/selinux.h>
|
||||
#endif
|
||||
|
||||
#include "nm-common-macros.h"
|
||||
#include "nm-dbus-interface.h"
|
||||
#include "nm-connection.h"
|
||||
#include "nm-utils.h"
|
||||
#include "nm-core-internal.h"
|
||||
|
||||
#include "NetworkManagerUtils.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define HOSTNAMED_SERVICE_NAME "org.freedesktop.hostname1"
|
||||
#define HOSTNAMED_SERVICE_PATH "/org/freedesktop/hostname1"
|
||||
#define HOSTNAMED_SERVICE_INTERFACE "org.freedesktop.hostname1"
|
||||
|
||||
#define HOSTNAME_FILE_DEFAULT "/etc/hostname"
|
||||
#define HOSTNAME_FILE_UCASE_HOSTNAME "/etc/HOSTNAME"
|
||||
#define HOSTNAME_FILE_GENTOO "/etc/conf.d/hostname"
|
||||
|
||||
#if (defined(HOSTNAME_PERSIST_SUSE) + defined(HOSTNAME_PERSIST_SLACKWARE) + defined(HOSTNAME_PERSIST_GENTOO)) > 1
|
||||
#error "Can only define one of HOSTNAME_PERSIST_*"
|
||||
#endif
|
||||
|
||||
#if defined(HOSTNAME_PERSIST_SUSE)
|
||||
#define HOSTNAME_FILE HOSTNAME_FILE_UCASE_HOSTNAME
|
||||
#elif defined(HOSTNAME_PERSIST_SLACKWARE)
|
||||
#define HOSTNAME_FILE HOSTNAME_FILE_UCASE_HOSTNAME
|
||||
#elif defined(HOSTNAME_PERSIST_GENTOO)
|
||||
#define HOSTNAME_FILE HOSTNAME_FILE_GENTOO
|
||||
#else
|
||||
#define HOSTNAME_FILE HOSTNAME_FILE_DEFAULT
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NM_GOBJECT_PROPERTIES_DEFINE (NMHostnameManager,
|
||||
PROP_HOSTNAME,
|
||||
);
|
||||
|
||||
typedef struct {
|
||||
char *current_hostname;
|
||||
GFileMonitor *monitor;
|
||||
GFileMonitor *dhcp_monitor;
|
||||
gulong monitor_id;
|
||||
gulong dhcp_monitor_id;
|
||||
GDBusProxy *hostnamed_proxy;
|
||||
} NMHostnameManagerPrivate;
|
||||
|
||||
struct _NMHostnameManager {
|
||||
GObject parent;
|
||||
NMHostnameManagerPrivate _priv;
|
||||
};
|
||||
|
||||
struct _NMHostnameManagerClass {
|
||||
GObjectClass parent;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (NMHostnameManager, nm_hostname_manager, G_TYPE_OBJECT);
|
||||
|
||||
#define NM_HOSTNAME_MANAGER_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMHostnameManager, NM_IS_HOSTNAME_MANAGER)
|
||||
|
||||
NM_DEFINE_SINGLETON_GETTER (NMHostnameManager, nm_hostname_manager_get, NM_TYPE_HOSTNAME_MANAGER);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define _NMLOG_DOMAIN LOGD_CORE
|
||||
#define _NMLOG(level, ...) __NMLOG_DEFAULT (level, _NMLOG_DOMAIN, "hostname", __VA_ARGS__)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#if defined(HOSTNAME_PERSIST_GENTOO)
|
||||
static gchar *
|
||||
read_hostname_gentoo (const char *path)
|
||||
{
|
||||
gs_free char *contents = NULL;
|
||||
gs_strfreev char **all_lines = NULL;
|
||||
const char *tmp;
|
||||
guint i;
|
||||
|
||||
if (!g_file_get_contents (path, &contents, NULL, NULL))
|
||||
return NULL;
|
||||
|
||||
all_lines = g_strsplit (contents, "\n", 0);
|
||||
for (i = 0; all_lines[i]; i++) {
|
||||
g_strstrip (all_lines[i]);
|
||||
if (all_lines[i][0] == '#' || all_lines[i][0] == '\0')
|
||||
continue;
|
||||
if (g_str_has_prefix (all_lines[i], "hostname=")) {
|
||||
tmp = &all_lines[i][NM_STRLEN ("hostname=")];
|
||||
return g_shell_unquote (tmp, NULL);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HOSTNAME_PERSIST_SLACKWARE)
|
||||
static gchar *
|
||||
read_hostname_slackware (const char *path)
|
||||
{
|
||||
gs_free char *contents = NULL;
|
||||
gs_strfreev char **all_lines = NULL;
|
||||
char *tmp;
|
||||
guint i, j = 0;
|
||||
|
||||
if (!g_file_get_contents (path, &contents, NULL, NULL))
|
||||
return NULL;
|
||||
|
||||
all_lines = g_strsplit (contents, "\n", 0);
|
||||
for (i = 0; all_lines[i]; i++) {
|
||||
g_strstrip (all_lines[i]);
|
||||
if (all_lines[i][0] == '#' || all_lines[i][0] == '\0')
|
||||
continue;
|
||||
tmp = &all_lines[i][0];
|
||||
/* We only want up to the first '.' -- the rest of the */
|
||||
/* fqdn is defined in /etc/hosts */
|
||||
while (tmp[j] != '\0') {
|
||||
if (tmp[j] == '.') {
|
||||
tmp[j] = '\0';
|
||||
break;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
return g_shell_unquote (tmp, NULL);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HOSTNAME_PERSIST_SUSE)
|
||||
static gboolean
|
||||
hostname_is_dynamic (void)
|
||||
{
|
||||
GIOChannel *channel;
|
||||
char *str = NULL;
|
||||
gboolean dynamic = FALSE;
|
||||
|
||||
channel = g_io_channel_new_file (CONF_DHCP, "r", NULL);
|
||||
if (!channel)
|
||||
return dynamic;
|
||||
|
||||
while (g_io_channel_read_line (channel, &str, NULL, NULL, NULL) != G_IO_STATUS_EOF) {
|
||||
if (str) {
|
||||
g_strstrip (str);
|
||||
if (g_str_has_prefix (str, "DHCLIENT_SET_HOSTNAME="))
|
||||
dynamic = strcmp (&str[NM_STRLEN ("DHCLIENT_SET_HOSTNAME=")], "\"yes\"") == 0;
|
||||
g_free (str);
|
||||
}
|
||||
}
|
||||
|
||||
g_io_channel_shutdown (channel, FALSE, NULL);
|
||||
g_io_channel_unref (channel);
|
||||
|
||||
return dynamic;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Returns an allocated string which the caller owns and must eventually free */
|
||||
char *
|
||||
nm_hostname_manager_read_hostname (NMHostnameManager *self)
|
||||
{
|
||||
NMHostnameManagerPrivate *priv = NM_HOSTNAME_MANAGER_GET_PRIVATE (self);
|
||||
char *hostname = NULL;
|
||||
|
||||
if (priv->hostnamed_proxy) {
|
||||
hostname = g_strdup (priv->current_hostname);
|
||||
goto out;
|
||||
}
|
||||
|
||||
#if defined(HOSTNAME_PERSIST_SUSE)
|
||||
if (priv->dhcp_monitor_id && hostname_is_dynamic ())
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
#if defined(HOSTNAME_PERSIST_GENTOO)
|
||||
hostname = read_hostname_gentoo (HOSTNAME_FILE);
|
||||
#elif defined(HOSTNAME_PERSIST_SLACKWARE)
|
||||
hostname = read_hostname_slackware (HOSTNAME_FILE);
|
||||
#else
|
||||
if (g_file_get_contents (HOSTNAME_FILE, &hostname, NULL, NULL))
|
||||
g_strchomp (hostname);
|
||||
#endif
|
||||
|
||||
out:
|
||||
if (hostname && !hostname[0]) {
|
||||
g_free (hostname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return hostname;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const char *
|
||||
nm_hostname_manager_get_hostname (NMHostnameManager *self)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_HOSTNAME_MANAGER (self), NULL);
|
||||
return NM_HOSTNAME_MANAGER_GET_PRIVATE (self)->current_hostname;
|
||||
}
|
||||
|
||||
static void
|
||||
_set_hostname_take (NMHostnameManager *self, char *hostname)
|
||||
{
|
||||
NMHostnameManagerPrivate *priv = NM_HOSTNAME_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
_LOGI ("hostname changed from %s%s%s to %s%s%s",
|
||||
NM_PRINT_FMT_QUOTED (priv->current_hostname, "\"", priv->current_hostname, "\"", "(none)"),
|
||||
NM_PRINT_FMT_QUOTED (hostname, "\"", hostname, "\"", "(none)"));
|
||||
|
||||
g_free (priv->current_hostname);
|
||||
priv->current_hostname = hostname;
|
||||
_notify (self, PROP_HOSTNAME);
|
||||
}
|
||||
|
||||
static void
|
||||
_set_hostname (NMHostnameManager *self, const char *hostname)
|
||||
{
|
||||
NMHostnameManagerPrivate *priv = NM_HOSTNAME_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
hostname = nm_str_not_empty (hostname);
|
||||
if (!nm_streq0 (hostname, priv->current_hostname))
|
||||
_set_hostname_take (self, g_strdup (hostname));
|
||||
}
|
||||
|
||||
static void
|
||||
_set_hostname_read (NMHostnameManager *self)
|
||||
{
|
||||
NMHostnameManagerPrivate *priv = NM_HOSTNAME_MANAGER_GET_PRIVATE (self);
|
||||
char *hostname;
|
||||
|
||||
if (priv->hostnamed_proxy) {
|
||||
/* read-hostname returns the current hostname with hostnamed. */
|
||||
return;
|
||||
}
|
||||
|
||||
hostname = nm_hostname_manager_read_hostname (self);
|
||||
|
||||
if (nm_streq0 (hostname, priv->current_hostname)) {
|
||||
g_free (hostname);
|
||||
return;
|
||||
}
|
||||
|
||||
_set_hostname_take (self, hostname);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
char *hostname;
|
||||
NMHostnameManagerSetHostnameCb cb;
|
||||
gpointer user_data;
|
||||
} SetHostnameInfo;
|
||||
|
||||
static void
|
||||
set_transient_hostname_done (GObject *object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
GDBusProxy *proxy = G_DBUS_PROXY (object);
|
||||
gs_free SetHostnameInfo *info = user_data;
|
||||
gs_unref_variant GVariant *result = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
result = g_dbus_proxy_call_finish (proxy, res, &error);
|
||||
|
||||
if (error) {
|
||||
_LOGW ("couldn't set the system hostname to '%s' using hostnamed: %s",
|
||||
info->hostname, error->message);
|
||||
}
|
||||
|
||||
info->cb (info->hostname, !error, info->user_data);
|
||||
g_free (info->hostname);
|
||||
}
|
||||
|
||||
void
|
||||
nm_hostname_manager_set_transient_hostname (NMHostnameManager *self,
|
||||
const char *hostname,
|
||||
NMHostnameManagerSetHostnameCb cb,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMHostnameManagerPrivate *priv;
|
||||
SetHostnameInfo *info;
|
||||
|
||||
g_return_if_fail (NM_IS_HOSTNAME_MANAGER (self));
|
||||
|
||||
priv = NM_HOSTNAME_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
if (!priv->hostnamed_proxy) {
|
||||
cb (hostname, FALSE, user_data);
|
||||
return;
|
||||
}
|
||||
|
||||
info = g_new0 (SetHostnameInfo, 1);
|
||||
info->hostname = g_strdup (hostname);
|
||||
info->cb = cb;
|
||||
info->user_data = user_data;
|
||||
|
||||
g_dbus_proxy_call (priv->hostnamed_proxy,
|
||||
"SetHostname",
|
||||
g_variant_new ("(sb)", hostname, FALSE),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
NULL,
|
||||
set_transient_hostname_done,
|
||||
info);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_hostname_manager_get_transient_hostname (NMHostnameManager *self, char **hostname)
|
||||
{
|
||||
NMHostnameManagerPrivate *priv = NM_HOSTNAME_MANAGER_GET_PRIVATE (self);
|
||||
GVariant *v_hostname;
|
||||
|
||||
if (!priv->hostnamed_proxy)
|
||||
return FALSE;
|
||||
|
||||
v_hostname = g_dbus_proxy_get_cached_property (priv->hostnamed_proxy,
|
||||
"Hostname");
|
||||
if (!v_hostname) {
|
||||
_LOGT ("transient hostname retrieval failed");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*hostname = g_variant_dup_string (v_hostname, NULL);
|
||||
g_variant_unref (v_hostname);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_hostname_manager_write_hostname (NMHostnameManager *self, const char *hostname)
|
||||
{
|
||||
NMHostnameManagerPrivate *priv;
|
||||
char *hostname_eol;
|
||||
gboolean ret;
|
||||
gs_free_error GError *error = NULL;
|
||||
const char *file = HOSTNAME_FILE;
|
||||
gs_free char *link_path = NULL;
|
||||
gs_unref_variant GVariant *var = NULL;
|
||||
struct stat file_stat;
|
||||
#if HAVE_SELINUX
|
||||
security_context_t se_ctx_prev = NULL, se_ctx = NULL;
|
||||
mode_t st_mode = 0;
|
||||
#endif
|
||||
|
||||
g_return_val_if_fail (NM_IS_HOSTNAME_MANAGER (self), FALSE);
|
||||
|
||||
priv = NM_HOSTNAME_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
if (priv->hostnamed_proxy) {
|
||||
var = g_dbus_proxy_call_sync (priv->hostnamed_proxy,
|
||||
"SetStaticHostname",
|
||||
g_variant_new ("(sb)", hostname, FALSE),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
NULL,
|
||||
&error);
|
||||
if (error)
|
||||
_LOGW ("could not set hostname: %s", error->message);
|
||||
|
||||
return !error;
|
||||
}
|
||||
|
||||
/* If the hostname file is a symbolic link, follow it to find where the
|
||||
* real file is located, otherwise g_file_set_contents will attempt to
|
||||
* replace the link with a plain file.
|
||||
*/
|
||||
if ( lstat (file, &file_stat) == 0
|
||||
&& S_ISLNK (file_stat.st_mode)
|
||||
&& (link_path = nm_utils_read_link_absolute (file, NULL)))
|
||||
file = link_path;
|
||||
|
||||
#if HAVE_SELINUX
|
||||
/* Get default context for hostname file and set it for fscreate */
|
||||
if (stat (file, &file_stat) == 0)
|
||||
st_mode = file_stat.st_mode;
|
||||
matchpathcon (file, st_mode, &se_ctx);
|
||||
matchpathcon_fini ();
|
||||
getfscreatecon (&se_ctx_prev);
|
||||
setfscreatecon (se_ctx);
|
||||
#endif
|
||||
|
||||
#if defined (HOSTNAME_PERSIST_GENTOO)
|
||||
hostname_eol = g_strdup_printf ("#Generated by NetworkManager\n"
|
||||
"hostname=\"%s\"\n", hostname);
|
||||
#else
|
||||
hostname_eol = g_strdup_printf ("%s\n", hostname);
|
||||
#endif
|
||||
|
||||
ret = g_file_set_contents (file, hostname_eol, -1, &error);
|
||||
|
||||
#if HAVE_SELINUX
|
||||
/* Restore previous context and cleanup */
|
||||
setfscreatecon (se_ctx_prev);
|
||||
freecon (se_ctx);
|
||||
freecon (se_ctx_prev);
|
||||
#endif
|
||||
|
||||
g_free (hostname_eol);
|
||||
|
||||
if (!ret) {
|
||||
_LOGW ("could not save hostname to %s: %s", file, error->message);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_hostname_manager_validate_hostname (const char *hostname)
|
||||
{
|
||||
const char *p;
|
||||
gboolean dot = TRUE;
|
||||
|
||||
if (!hostname || !hostname[0])
|
||||
return FALSE;
|
||||
|
||||
for (p = hostname; *p; p++) {
|
||||
if (*p == '.') {
|
||||
if (dot)
|
||||
return FALSE;
|
||||
dot = TRUE;
|
||||
} else {
|
||||
if (!g_ascii_isalnum (*p) && (*p != '-') && (*p != '_'))
|
||||
return FALSE;
|
||||
dot = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (dot)
|
||||
return FALSE;
|
||||
|
||||
return (p - hostname <= HOST_NAME_MAX);
|
||||
}
|
||||
|
||||
static void
|
||||
hostname_file_changed_cb (GFileMonitor *monitor,
|
||||
GFile *file,
|
||||
GFile *other_file,
|
||||
GFileMonitorEvent event_type,
|
||||
gpointer user_data)
|
||||
{
|
||||
_set_hostname_read (user_data);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
hostnamed_properties_changed (GDBusProxy *proxy,
|
||||
GVariant *changed_properties,
|
||||
char **invalidated_properties,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMHostnameManager *self = user_data;
|
||||
NMHostnameManagerPrivate *priv = NM_HOSTNAME_MANAGER_GET_PRIVATE (self);
|
||||
GVariant *v_hostname;
|
||||
|
||||
v_hostname = g_dbus_proxy_get_cached_property (priv->hostnamed_proxy,
|
||||
"StaticHostname");
|
||||
if (v_hostname) {
|
||||
_set_hostname (self, g_variant_get_string (v_hostname, NULL));
|
||||
g_variant_unref (v_hostname);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
setup_hostname_file_monitors (NMHostnameManager *self)
|
||||
{
|
||||
NMHostnameManagerPrivate *priv = NM_HOSTNAME_MANAGER_GET_PRIVATE (self);
|
||||
GFileMonitor *monitor;
|
||||
const char *path = HOSTNAME_FILE;
|
||||
char *link_path = NULL;
|
||||
struct stat file_stat;
|
||||
GFile *file;
|
||||
|
||||
/* resolve the path to the hostname file if it is a symbolic link */
|
||||
if ( lstat(path, &file_stat) == 0
|
||||
&& S_ISLNK (file_stat.st_mode)
|
||||
&& (link_path = nm_utils_read_link_absolute (path, NULL))) {
|
||||
path = link_path;
|
||||
if ( lstat(link_path, &file_stat) == 0
|
||||
&& S_ISLNK (file_stat.st_mode)) {
|
||||
_LOGW ("only one level of symbolic link indirection is allowed when monitoring "
|
||||
HOSTNAME_FILE);
|
||||
}
|
||||
}
|
||||
|
||||
/* monitor changes to hostname file */
|
||||
file = g_file_new_for_path (path);
|
||||
monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, NULL);
|
||||
g_object_unref (file);
|
||||
g_free(link_path);
|
||||
if (monitor) {
|
||||
priv->monitor_id = g_signal_connect (monitor, "changed",
|
||||
G_CALLBACK (hostname_file_changed_cb),
|
||||
self);
|
||||
priv->monitor = monitor;
|
||||
}
|
||||
|
||||
#if defined (HOSTNAME_PERSIST_SUSE)
|
||||
/* monitor changes to dhcp file to know whether the hostname is valid */
|
||||
file = g_file_new_for_path (CONF_DHCP);
|
||||
monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, NULL);
|
||||
g_object_unref (file);
|
||||
if (monitor) {
|
||||
priv->dhcp_monitor_id = g_signal_connect (monitor, "changed",
|
||||
G_CALLBACK (hostname_file_changed_cb),
|
||||
self);
|
||||
priv->dhcp_monitor = monitor;
|
||||
}
|
||||
#endif
|
||||
|
||||
_set_hostname_read (self);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
NMHostnameManager *self = NM_HOSTNAME_MANAGER (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_HOSTNAME:
|
||||
g_value_set_string (value, nm_hostname_manager_get_hostname (self));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
nm_hostname_manager_init (NMHostnameManager *self)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
constructed (GObject *object)
|
||||
{
|
||||
NMHostnameManager *self = NM_HOSTNAME_MANAGER (object);
|
||||
NMHostnameManagerPrivate *priv = NM_HOSTNAME_MANAGER_GET_PRIVATE (self);
|
||||
GDBusProxy *proxy;
|
||||
GVariant *variant;
|
||||
gs_free GError *error = NULL;
|
||||
|
||||
proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, 0, NULL,
|
||||
HOSTNAMED_SERVICE_NAME, HOSTNAMED_SERVICE_PATH,
|
||||
HOSTNAMED_SERVICE_INTERFACE, NULL, &error);
|
||||
if (proxy) {
|
||||
variant = g_dbus_proxy_get_cached_property (proxy, "StaticHostname");
|
||||
if (variant) {
|
||||
_LOGI ("hostname: using hostnamed");
|
||||
priv->hostnamed_proxy = proxy;
|
||||
g_signal_connect (proxy, "g-properties-changed",
|
||||
G_CALLBACK (hostnamed_properties_changed), self);
|
||||
hostnamed_properties_changed (proxy, NULL, NULL, self);
|
||||
g_variant_unref (variant);
|
||||
} else {
|
||||
_LOGI ("hostname: couldn't get property from hostnamed");
|
||||
g_object_unref (proxy);
|
||||
}
|
||||
} else {
|
||||
_LOGI ("hostname: hostnamed not used as proxy creation failed with: %s",
|
||||
error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
if (!priv->hostnamed_proxy)
|
||||
setup_hostname_file_monitors (self);
|
||||
|
||||
G_OBJECT_CLASS (nm_hostname_manager_parent_class)->constructed (object);
|
||||
}
|
||||
|
||||
static void
|
||||
dispose (GObject *object)
|
||||
{
|
||||
NMHostnameManager *self = NM_HOSTNAME_MANAGER (object);
|
||||
NMHostnameManagerPrivate *priv = NM_HOSTNAME_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
if (priv->hostnamed_proxy) {
|
||||
g_signal_handlers_disconnect_by_func (priv->hostnamed_proxy,
|
||||
G_CALLBACK (hostnamed_properties_changed),
|
||||
self);
|
||||
g_clear_object (&priv->hostnamed_proxy);
|
||||
}
|
||||
|
||||
if (priv->monitor) {
|
||||
if (priv->monitor_id)
|
||||
g_signal_handler_disconnect (priv->monitor, priv->monitor_id);
|
||||
|
||||
g_file_monitor_cancel (priv->monitor);
|
||||
g_clear_object (&priv->monitor);
|
||||
}
|
||||
|
||||
if (priv->dhcp_monitor) {
|
||||
if (priv->dhcp_monitor_id)
|
||||
g_signal_handler_disconnect (priv->dhcp_monitor,
|
||||
priv->dhcp_monitor_id);
|
||||
|
||||
g_file_monitor_cancel (priv->dhcp_monitor);
|
||||
g_clear_object (&priv->dhcp_monitor);
|
||||
}
|
||||
|
||||
nm_clear_g_free (&priv->current_hostname);
|
||||
|
||||
G_OBJECT_CLASS (nm_hostname_manager_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
nm_hostname_manager_class_init (NMHostnameManagerClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
|
||||
object_class->constructed = constructed;
|
||||
object_class->get_property = get_property;
|
||||
object_class->dispose = dispose;
|
||||
|
||||
obj_properties[PROP_HOSTNAME] =
|
||||
g_param_spec_string (NM_HOSTNAME_MANAGER_HOSTNAME, "", "",
|
||||
NULL,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
|
||||
}
|
||||
63
src/nm-hostname-manager.h
Normal file
63
src/nm-hostname-manager.h
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
/* NetworkManager
|
||||
*
|
||||
* Søren Sandmann <sandmann@daimi.au.dk>
|
||||
* Dan Williams <dcbw@redhat.com>
|
||||
* Tambet Ingo <tambet@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* (C) Copyright 2007 - 2011, 2017 Red Hat, Inc.
|
||||
* (C) Copyright 2008 Novell, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __NM_HOSTNAME_MANAGER_H__
|
||||
#define __NM_HOSTNAME_MANAGER_H__
|
||||
|
||||
#define NM_TYPE_HOSTNAME_MANAGER (nm_hostname_manager_get_type ())
|
||||
#define NM_HOSTNAME_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_HOSTNAME_MANAGER, NMHostnameManager))
|
||||
#define NM_HOSTNAME_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_HOSTNAME_MANAGER, NMHostnameManagerClass))
|
||||
#define NM_IS_HOSTNAME_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_HOSTNAME_MANAGER))
|
||||
#define NM_IS_HOSTNAME_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_HOSTNAME_MANAGER))
|
||||
#define NM_HOSTNAME_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_HOSTNAME_MANAGER, NMHostnameManagerClass))
|
||||
|
||||
#define NM_HOSTNAME_MANAGER_HOSTNAME "hostname"
|
||||
|
||||
typedef struct _NMHostnameManager NMHostnameManager;
|
||||
typedef struct _NMHostnameManagerClass NMHostnameManagerClass;
|
||||
|
||||
typedef void (*NMHostnameManagerSetHostnameCb) (const char *name, gboolean result, gpointer user_data);
|
||||
|
||||
GType nm_hostname_manager_get_type (void);
|
||||
|
||||
NMHostnameManager *nm_hostname_manager_get (void);
|
||||
|
||||
const char *nm_hostname_manager_get_hostname (NMHostnameManager *self);
|
||||
|
||||
char *nm_hostname_manager_read_hostname (NMHostnameManager *self);
|
||||
|
||||
gboolean nm_hostname_manager_write_hostname (NMHostnameManager *self, const char *hostname);
|
||||
|
||||
void nm_hostname_manager_set_transient_hostname (NMHostnameManager *self,
|
||||
const char *hostname,
|
||||
NMHostnameManagerSetHostnameCb cb,
|
||||
gpointer user_data);
|
||||
|
||||
gboolean nm_hostname_manager_get_transient_hostname (NMHostnameManager *self,
|
||||
char **hostname);
|
||||
|
||||
gboolean nm_hostname_manager_validate_hostname (const char *hostname);
|
||||
|
||||
#endif /* __NM_HOSTNAME_MANAGER_H__ */
|
||||
|
|
@ -35,6 +35,7 @@
|
|||
#include "devices/nm-device.h"
|
||||
#include "devices/nm-device-generic.h"
|
||||
#include "platform/nm-platform.h"
|
||||
#include "nm-hostname-manager.h"
|
||||
#include "nm-rfkill-manager.h"
|
||||
#include "dhcp/nm-dhcp-manager.h"
|
||||
#include "settings/nm-settings.h"
|
||||
|
|
@ -122,6 +123,8 @@ typedef struct {
|
|||
|
||||
NMPolicy *policy;
|
||||
|
||||
NMHostnameManager *hostname_manager;
|
||||
|
||||
NMBusManager *dbus_mgr;
|
||||
struct {
|
||||
GDBusConnection *connection;
|
||||
|
|
@ -132,7 +135,6 @@ typedef struct {
|
|||
NMCheckpointManager *checkpoint_mgr;
|
||||
|
||||
NMSettings *settings;
|
||||
char *hostname;
|
||||
|
||||
RadioState radio_states[RFKILL_TYPE_MAX];
|
||||
NMVpnManager *vpn_manager;
|
||||
|
|
@ -211,7 +213,6 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMManager,
|
|||
PROP_ALL_DEVICES,
|
||||
|
||||
/* Not exported */
|
||||
PROP_HOSTNAME,
|
||||
PROP_SLEEPING,
|
||||
);
|
||||
|
||||
|
|
@ -1404,35 +1405,17 @@ system_unmanaged_devices_changed_cb (NMSettings *settings,
|
|||
}
|
||||
|
||||
static void
|
||||
system_hostname_changed_cb (NMSettings *settings,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
hostname_changed_cb (NMHostnameManager *hostname_manager,
|
||||
GParamSpec *pspec,
|
||||
NMManager *self)
|
||||
{
|
||||
NMManager *self = NM_MANAGER (user_data);
|
||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
|
||||
char *hostname;
|
||||
const char *hostname;
|
||||
|
||||
hostname = nm_settings_get_hostname (priv->settings);
|
||||
hostname = nm_hostname_manager_get_hostname (priv->hostname_manager);
|
||||
|
||||
/* nm_settings_get_hostname() does not return an empty hostname. */
|
||||
nm_assert (!hostname || *hostname);
|
||||
|
||||
if (!hostname && !priv->hostname)
|
||||
return;
|
||||
if (hostname && priv->hostname && !strcmp (hostname, priv->hostname)) {
|
||||
g_free (hostname);
|
||||
return;
|
||||
}
|
||||
|
||||
/* realloc, to free possibly trailing data after NUL. */
|
||||
if (hostname)
|
||||
hostname = g_realloc (hostname, strlen (hostname) + 1);
|
||||
|
||||
g_free (priv->hostname);
|
||||
priv->hostname = hostname;
|
||||
_notify (self, PROP_HOSTNAME);
|
||||
|
||||
nm_dhcp_manager_set_default_hostname (nm_dhcp_manager_get (), priv->hostname);
|
||||
nm_dispatcher_call_hostname (NULL, NULL, NULL);
|
||||
nm_dhcp_manager_set_default_hostname (nm_dhcp_manager_get (), hostname);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -5087,7 +5070,7 @@ nm_manager_start (NMManager *self, GError **error)
|
|||
priv->net_enabled ? "enabled" : "disabled");
|
||||
|
||||
system_unmanaged_devices_changed_cb (priv->settings, NULL, self);
|
||||
system_hostname_changed_cb (priv->settings, NULL, self);
|
||||
hostname_changed_cb (priv->hostname_manager, NULL, self);
|
||||
|
||||
/* Start device factories */
|
||||
nm_device_factory_manager_load_factories (_register_device_factory, self);
|
||||
|
|
@ -5983,12 +5966,15 @@ constructed (GObject *object)
|
|||
G_CALLBACK (settings_startup_complete_changed), self);
|
||||
g_signal_connect (priv->settings, "notify::" NM_SETTINGS_UNMANAGED_SPECS,
|
||||
G_CALLBACK (system_unmanaged_devices_changed_cb), self);
|
||||
g_signal_connect (priv->settings, "notify::" NM_SETTINGS_HOSTNAME,
|
||||
G_CALLBACK (system_hostname_changed_cb), self);
|
||||
g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_ADDED,
|
||||
G_CALLBACK (connection_added_cb), self);
|
||||
g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED,
|
||||
G_CALLBACK (connection_updated_cb), self);
|
||||
|
||||
priv->hostname_manager = g_object_ref (nm_hostname_manager_get ());
|
||||
g_signal_connect (priv->hostname_manager, "notify::" NM_HOSTNAME_MANAGER_HOSTNAME,
|
||||
G_CALLBACK (hostname_changed_cb), self);
|
||||
|
||||
/*
|
||||
* Do not delete existing virtual devices to keep connectivity up.
|
||||
* Virtual devices are reused when NetworkManager is restarted.
|
||||
|
|
@ -6185,9 +6171,6 @@ get_property (GObject *object, guint prop_id,
|
|||
case PROP_ACTIVATING_CONNECTION:
|
||||
nm_utils_g_value_set_object_path (value, priv->activating_connection);
|
||||
break;
|
||||
case PROP_HOSTNAME:
|
||||
g_value_set_string (value, priv->hostname);
|
||||
break;
|
||||
case PROP_SLEEPING:
|
||||
g_value_set_boolean (value, priv->sleeping);
|
||||
break;
|
||||
|
|
@ -6296,8 +6279,6 @@ dispose (GObject *object)
|
|||
g_clear_object (&priv->config);
|
||||
}
|
||||
|
||||
g_free (priv->hostname);
|
||||
|
||||
if (priv->policy) {
|
||||
g_signal_handlers_disconnect_by_func (priv->policy, policy_default_device_changed, manager);
|
||||
g_signal_handlers_disconnect_by_func (priv->policy, policy_activating_device_changed, manager);
|
||||
|
|
@ -6307,12 +6288,16 @@ dispose (GObject *object)
|
|||
if (priv->settings) {
|
||||
g_signal_handlers_disconnect_by_func (priv->settings, settings_startup_complete_changed, manager);
|
||||
g_signal_handlers_disconnect_by_func (priv->settings, system_unmanaged_devices_changed_cb, manager);
|
||||
g_signal_handlers_disconnect_by_func (priv->settings, system_hostname_changed_cb, manager);
|
||||
g_signal_handlers_disconnect_by_func (priv->settings, connection_added_cb, manager);
|
||||
g_signal_handlers_disconnect_by_func (priv->settings, connection_updated_cb, manager);
|
||||
g_clear_object (&priv->settings);
|
||||
}
|
||||
|
||||
if (priv->hostname_manager) {
|
||||
g_signal_handlers_disconnect_by_func (priv->hostname_manager, hostname_changed_cb, manager);
|
||||
g_clear_object (&priv->hostname_manager);
|
||||
}
|
||||
|
||||
g_clear_object (&priv->vpn_manager);
|
||||
|
||||
/* Unregister property filter */
|
||||
|
|
@ -6474,13 +6459,6 @@ nm_manager_class_init (NMManagerClass *manager_class)
|
|||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/* Hostname is not exported over D-Bus */
|
||||
obj_properties[PROP_HOSTNAME] =
|
||||
g_param_spec_string (NM_MANAGER_HOSTNAME, "", "",
|
||||
NULL,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/* Sleeping is not exported over D-Bus */
|
||||
obj_properties[PROP_SLEEPING] =
|
||||
g_param_spec_boolean (NM_MANAGER_SLEEPING, "", "",
|
||||
|
|
|
|||
|
|
@ -54,7 +54,6 @@
|
|||
#define NM_MANAGER_ALL_DEVICES "all-devices"
|
||||
|
||||
/* Not exported */
|
||||
#define NM_MANAGER_HOSTNAME "hostname"
|
||||
#define NM_MANAGER_SLEEPING "sleeping"
|
||||
|
||||
/* signals */
|
||||
|
|
|
|||
160
src/nm-policy.c
160
src/nm-policy.c
|
|
@ -49,6 +49,7 @@
|
|||
#include "nm-dhcp6-config.h"
|
||||
#include "nm-config.h"
|
||||
#include "nm-netns.h"
|
||||
#include "nm-hostname-manager.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -73,12 +74,17 @@ typedef struct {
|
|||
|
||||
NMSettings *settings;
|
||||
|
||||
NMHostnameManager *hostname_manager;
|
||||
|
||||
NMDevice *default_device4, *activating_device4;
|
||||
NMDevice *default_device6, *activating_device6;
|
||||
|
||||
GResolver *resolver;
|
||||
GInetAddress *lookup_addr;
|
||||
GCancellable *lookup_cancellable;
|
||||
struct {
|
||||
GInetAddress *addr;
|
||||
GResolver *resolver;
|
||||
GCancellable *cancellable;
|
||||
} lookup;
|
||||
|
||||
NMDnsManager *dns_manager;
|
||||
gulong config_changed_id;
|
||||
|
||||
|
|
@ -443,50 +449,46 @@ settings_set_hostname_cb (const char *hostname,
|
|||
#define HOST_NAME_BUFSIZE (HOST_NAME_MAX + 2)
|
||||
|
||||
static char *
|
||||
_get_hostname (NMPolicy *self, char **hostname)
|
||||
_get_hostname (NMPolicy *self)
|
||||
{
|
||||
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
|
||||
char *buf;
|
||||
|
||||
g_assert (hostname && *hostname == NULL);
|
||||
char *hostname = NULL;
|
||||
|
||||
/* If there is an in-progress hostname change, return
|
||||
* the last hostname set as would be set soon...
|
||||
*/
|
||||
if (priv->changing_hostname) {
|
||||
_LOGT (LOGD_DNS, "get-hostname: \"%s\" (last on set)", priv->last_hostname);
|
||||
*hostname = g_strdup (priv->last_hostname);
|
||||
return *hostname;
|
||||
return g_strdup (priv->last_hostname);
|
||||
}
|
||||
|
||||
/* try to get the hostname via dbus... */
|
||||
if (nm_settings_get_transient_hostname (priv->settings, hostname)) {
|
||||
_LOGT (LOGD_DNS, "get-hostname: \"%s\" (from dbus)", *hostname);
|
||||
return *hostname;
|
||||
if (nm_hostname_manager_get_transient_hostname (priv->hostname_manager, &hostname)) {
|
||||
_LOGT (LOGD_DNS, "get-hostname: \"%s\" (from dbus)", hostname);
|
||||
return hostname;
|
||||
}
|
||||
|
||||
/* ...or retrieve it by yourself */
|
||||
buf = g_malloc (HOST_NAME_BUFSIZE);
|
||||
if (gethostname (buf, HOST_NAME_BUFSIZE -1) != 0) {
|
||||
hostname = g_malloc (HOST_NAME_BUFSIZE);
|
||||
if (gethostname (hostname, HOST_NAME_BUFSIZE -1) != 0) {
|
||||
int errsv = errno;
|
||||
|
||||
_LOGT (LOGD_DNS, "get-hostname: couldn't get the system hostname: (%d) %s",
|
||||
errsv, g_strerror (errsv));
|
||||
g_free (buf);
|
||||
g_free (hostname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* the name may be truncated... */
|
||||
buf[HOST_NAME_BUFSIZE - 1] = '\0';
|
||||
if (strlen (buf) >= HOST_NAME_BUFSIZE -1) {
|
||||
_LOGT (LOGD_DNS, "get-hostname: system hostname too long: \"%s\"", buf);
|
||||
g_free (buf);
|
||||
hostname[HOST_NAME_BUFSIZE - 1] = '\0';
|
||||
if (strlen (hostname) >= HOST_NAME_BUFSIZE -1) {
|
||||
_LOGT (LOGD_DNS, "get-hostname: system hostname too long: \"%s\"", hostname);
|
||||
g_free (hostname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_LOGT (LOGD_DNS, "get-hostname: \"%s\"", buf);
|
||||
*hostname = buf;
|
||||
return *hostname;
|
||||
_LOGT (LOGD_DNS, "get-hostname: \"%s\"", hostname);
|
||||
return hostname;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -508,7 +510,7 @@ _set_hostname (NMPolicy *self,
|
|||
* restart the reverse lookup thread later.
|
||||
*/
|
||||
if (new_hostname)
|
||||
g_clear_object (&priv->lookup_addr);
|
||||
g_clear_object (&priv->lookup.addr);
|
||||
|
||||
/* Update the DNS only if the hostname is actually
|
||||
* going to change.
|
||||
|
|
@ -534,7 +536,7 @@ _set_hostname (NMPolicy *self,
|
|||
name = new_hostname;
|
||||
|
||||
/* Don't set the hostname if it isn't actually changing */
|
||||
if ( _get_hostname (self, &old_hostname)
|
||||
if ( (old_hostname = _get_hostname (self))
|
||||
&& (nm_streq (name, old_hostname))) {
|
||||
_LOGT (LOGD_DNS, "set-hostname: hostname already set to '%s' (%s)", name, msg);
|
||||
return;
|
||||
|
|
@ -549,10 +551,10 @@ _set_hostname (NMPolicy *self,
|
|||
|
||||
/* Ask NMSettings to update the transient hostname using its
|
||||
* systemd-hostnamed proxy */
|
||||
nm_settings_set_transient_hostname (priv->settings,
|
||||
name,
|
||||
settings_set_hostname_cb,
|
||||
g_object_ref (self));
|
||||
nm_hostname_manager_set_transient_hostname (priv->hostname_manager,
|
||||
name,
|
||||
settings_set_hostname_cb,
|
||||
g_object_ref (self));
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -572,7 +574,7 @@ lookup_callback (GObject *source,
|
|||
self = user_data;
|
||||
priv = NM_POLICY_GET_PRIVATE (self);
|
||||
|
||||
g_clear_object (&priv->lookup_cancellable);
|
||||
g_clear_object (&priv->lookup.cancellable);
|
||||
|
||||
if (hostname)
|
||||
_set_hostname (self, hostname, "from address lookup");
|
||||
|
|
@ -580,11 +582,24 @@ lookup_callback (GObject *source,
|
|||
_set_hostname (self, NULL, error->message);
|
||||
}
|
||||
|
||||
static void
|
||||
lookup_by_address (NMPolicy *self)
|
||||
{
|
||||
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
|
||||
|
||||
nm_clear_g_cancellable (&priv->lookup.cancellable);
|
||||
priv->lookup.cancellable = g_cancellable_new ();
|
||||
g_resolver_lookup_by_address_async (priv->lookup.resolver,
|
||||
priv->lookup.addr,
|
||||
priv->lookup.cancellable,
|
||||
lookup_callback, self);
|
||||
}
|
||||
|
||||
static void
|
||||
update_system_hostname (NMPolicy *self, NMDevice *best4, NMDevice *best6, const char *msg)
|
||||
{
|
||||
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
|
||||
char *configured_hostname = NULL;
|
||||
const char *configured_hostname;
|
||||
gs_free char *temp_hostname = NULL;
|
||||
const char *dhcp_hostname, *p;
|
||||
NMIP4Config *ip4_config;
|
||||
|
|
@ -600,12 +615,12 @@ update_system_hostname (NMPolicy *self, NMDevice *best4, NMDevice *best6, const
|
|||
|
||||
_LOGT (LOGD_DNS, "set-hostname: updating hostname (%s)", msg);
|
||||
|
||||
nm_clear_g_cancellable (&priv->lookup_cancellable);
|
||||
nm_clear_g_cancellable (&priv->lookup.cancellable);
|
||||
|
||||
/* Check if the hostname was set externally to NM, so that in that case
|
||||
* we can avoid to fallback to the one we got when we started.
|
||||
* Consider "not specific" hostnames as equal. */
|
||||
if ( _get_hostname (self, &temp_hostname)
|
||||
if ( (temp_hostname = _get_hostname (self))
|
||||
&& !nm_streq0 (temp_hostname, priv->last_hostname)
|
||||
&& ( nm_utils_is_specific_hostname (temp_hostname)
|
||||
|| nm_utils_is_specific_hostname (priv->last_hostname))) {
|
||||
|
|
@ -614,14 +629,14 @@ update_system_hostname (NMPolicy *self, NMDevice *best4, NMDevice *best6, const
|
|||
temp_hostname);
|
||||
priv->dhcp_hostname = FALSE;
|
||||
|
||||
if (!nm_utils_is_specific_hostname (temp_hostname))
|
||||
nm_clear_g_free (&temp_hostname);
|
||||
if (!nm_streq0 (temp_hostname, priv->orig_hostname)) {
|
||||
/* Update original (fallback) hostname */
|
||||
g_free (priv->orig_hostname);
|
||||
if (nm_utils_is_specific_hostname (temp_hostname)) {
|
||||
priv->orig_hostname = temp_hostname;
|
||||
temp_hostname = NULL;
|
||||
} else
|
||||
priv->orig_hostname = NULL;
|
||||
priv->orig_hostname = g_steal_pointer (&temp_hostname);
|
||||
_LOGT (LOGD_DNS, "hostname-original: update to %s%s%s",
|
||||
NM_PRINT_FMT_QUOTE_STRING (priv->orig_hostname));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -635,14 +650,12 @@ update_system_hostname (NMPolicy *self, NMDevice *best4, NMDevice *best6, const
|
|||
*/
|
||||
|
||||
/* Try a persistent hostname first */
|
||||
g_object_get (G_OBJECT (priv->manager), NM_MANAGER_HOSTNAME, &configured_hostname, NULL);
|
||||
configured_hostname = nm_hostname_manager_get_hostname (priv->hostname_manager);
|
||||
if (configured_hostname && nm_utils_is_specific_hostname (configured_hostname)) {
|
||||
_set_hostname (self, configured_hostname, "from system configuration");
|
||||
priv->dhcp_hostname = FALSE;
|
||||
g_free (configured_hostname);
|
||||
return;
|
||||
}
|
||||
g_free (configured_hostname);
|
||||
|
||||
/* Try automatically determined hostname from the best device's IP config */
|
||||
if (!best4)
|
||||
|
|
@ -737,15 +750,15 @@ update_system_hostname (NMPolicy *self, NMDevice *best4, NMDevice *best6, const
|
|||
const NMPlatformIP4Address *addr4;
|
||||
|
||||
addr4 = nm_ip4_config_get_address (ip4_config, 0);
|
||||
g_clear_object (&priv->lookup_addr);
|
||||
priv->lookup_addr = g_inet_address_new_from_bytes ((guint8 *) &addr4->address,
|
||||
g_clear_object (&priv->lookup.addr);
|
||||
priv->lookup.addr = g_inet_address_new_from_bytes ((guint8 *) &addr4->address,
|
||||
G_SOCKET_FAMILY_IPV4);
|
||||
} else if (ip6_config && nm_ip6_config_get_num_addresses (ip6_config) > 0) {
|
||||
const NMPlatformIP6Address *addr6;
|
||||
|
||||
addr6 = nm_ip6_config_get_address (ip6_config, 0);
|
||||
g_clear_object (&priv->lookup_addr);
|
||||
priv->lookup_addr = g_inet_address_new_from_bytes ((guint8 *) &addr6->address,
|
||||
g_clear_object (&priv->lookup.addr);
|
||||
priv->lookup.addr = g_inet_address_new_from_bytes ((guint8 *) &addr6->address,
|
||||
G_SOCKET_FAMILY_IPV6);
|
||||
} else {
|
||||
/* No valid IP config; fall back to localhost.localdomain */
|
||||
|
|
@ -753,11 +766,7 @@ update_system_hostname (NMPolicy *self, NMDevice *best4, NMDevice *best6, const
|
|||
return;
|
||||
}
|
||||
|
||||
priv->lookup_cancellable = g_cancellable_new ();
|
||||
g_resolver_lookup_by_address_async (priv->resolver,
|
||||
priv->lookup_addr,
|
||||
priv->lookup_cancellable,
|
||||
lookup_callback, self);
|
||||
lookup_by_address (self);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1248,7 +1257,7 @@ process_secondaries (NMPolicy *self,
|
|||
}
|
||||
|
||||
static void
|
||||
hostname_changed (NMManager *manager, GParamSpec *pspec, gpointer user_data)
|
||||
hostname_changed (NMHostnameManager *hostname_manager, GParamSpec *pspec, gpointer user_data)
|
||||
{
|
||||
NMPolicyPrivate *priv = user_data;
|
||||
NMPolicy *self = _PRIV_TO_SELF (priv);
|
||||
|
|
@ -2088,30 +2097,26 @@ dns_config_changed (NMDnsManager *dns_manager, gpointer user_data)
|
|||
* (race in updating DNS and doing the reverse lookup).
|
||||
*/
|
||||
|
||||
nm_clear_g_cancellable (&priv->lookup_cancellable);
|
||||
nm_clear_g_cancellable (&priv->lookup.cancellable);
|
||||
|
||||
/* Re-start the hostname lookup thread if we don't have hostname yet. */
|
||||
if (priv->lookup_addr) {
|
||||
if (priv->lookup.addr) {
|
||||
char *str = NULL;
|
||||
gs_free char *hostname = NULL;
|
||||
|
||||
/* Check if the hostname was externally set */
|
||||
if ( _get_hostname (self, &hostname)
|
||||
if ( (hostname = _get_hostname (self))
|
||||
&& nm_utils_is_specific_hostname (hostname)
|
||||
&& !nm_streq0 (hostname, priv->last_hostname)) {
|
||||
g_clear_object (&priv->lookup_addr);
|
||||
g_clear_object (&priv->lookup.addr);
|
||||
return;
|
||||
}
|
||||
|
||||
_LOGD (LOGD_DNS, "restarting reverse-lookup thread for address %s",
|
||||
(str = g_inet_address_to_string (priv->lookup_addr)));
|
||||
(str = g_inet_address_to_string (priv->lookup.addr)));
|
||||
g_free (str);
|
||||
|
||||
priv->lookup_cancellable = g_cancellable_new ();
|
||||
g_resolver_lookup_by_address_async (priv->resolver,
|
||||
priv->lookup_addr,
|
||||
priv->lookup_cancellable,
|
||||
lookup_callback, self);
|
||||
lookup_by_address (self);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2240,6 +2245,15 @@ nm_policy_get_activating_ip6_device (NMPolicy *self)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_hostname_mode_to_string, NMPolicyHostnameMode,
|
||||
NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT ("unknown"),
|
||||
NM_UTILS_LOOKUP_STR_ITEM (NM_POLICY_HOSTNAME_MODE_NONE, "none"),
|
||||
NM_UTILS_LOOKUP_STR_ITEM (NM_POLICY_HOSTNAME_MODE_DHCP, "dhcp"),
|
||||
NM_UTILS_LOOKUP_STR_ITEM (NM_POLICY_HOSTNAME_MODE_FULL, "full"),
|
||||
);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec)
|
||||
|
|
@ -2300,6 +2314,8 @@ nm_policy_init (NMPolicy *self)
|
|||
|
||||
priv->netns = g_object_ref (nm_netns_get ());
|
||||
|
||||
priv->hostname_manager = g_object_ref (nm_hostname_manager_get ());
|
||||
|
||||
hostname_mode = nm_config_data_get_value (NM_CONFIG_GET_DATA_ORIG,
|
||||
NM_CONFIG_KEYFILE_GROUP_MAIN,
|
||||
NM_CONFIG_KEYFILE_KEY_MAIN_HOSTNAME_MODE,
|
||||
|
|
@ -2311,7 +2327,6 @@ nm_policy_init (NMPolicy *self)
|
|||
else /* default - full mode */
|
||||
priv->hostname_mode = NM_POLICY_HOSTNAME_MODE_FULL;
|
||||
|
||||
_LOGI (LOGD_DNS, "hostname management mode: %s", hostname_mode ? hostname_mode : "default");
|
||||
priv->devices = g_hash_table_new (NULL, NULL);
|
||||
priv->ip6_prefix_delegations = g_array_new (FALSE, FALSE, sizeof (IP6PrefixDelegation));
|
||||
g_array_set_clear_func (priv->ip6_prefix_delegations, clear_ip6_prefix_delegation);
|
||||
|
|
@ -2325,7 +2340,7 @@ constructed (GObject *object)
|
|||
char *hostname = NULL;
|
||||
|
||||
/* Grab hostname on startup and use that if nothing provides one */
|
||||
if (_get_hostname (self, &hostname)) {
|
||||
if ((hostname = _get_hostname (self))) {
|
||||
/* init last_hostname */
|
||||
priv->last_hostname = hostname;
|
||||
|
||||
|
|
@ -2333,6 +2348,8 @@ constructed (GObject *object)
|
|||
if (nm_utils_is_specific_hostname (hostname))
|
||||
priv->orig_hostname = g_strdup (hostname);
|
||||
}
|
||||
_LOGT (LOGD_DNS, "hostname-original: set to %s%s%s",
|
||||
NM_PRINT_FMT_QUOTE_STRING (priv->orig_hostname));
|
||||
|
||||
priv->firewall_manager = g_object_ref (nm_firewall_manager_get ());
|
||||
g_signal_connect (priv->firewall_manager, NM_FIREWALL_MANAGER_STATE_CHANGED,
|
||||
|
|
@ -2343,9 +2360,10 @@ constructed (GObject *object)
|
|||
priv->config_changed_id = g_signal_connect (priv->dns_manager, NM_DNS_MANAGER_CONFIG_CHANGED,
|
||||
G_CALLBACK (dns_config_changed), self);
|
||||
|
||||
priv->resolver = g_resolver_get_default ();
|
||||
priv->lookup.resolver = g_resolver_get_default ();
|
||||
|
||||
g_signal_connect (priv->hostname_manager, "notify::" NM_HOSTNAME_MANAGER_HOSTNAME, (GCallback) hostname_changed, priv);
|
||||
|
||||
g_signal_connect (priv->manager, "notify::" NM_MANAGER_HOSTNAME, (GCallback) hostname_changed, priv);
|
||||
g_signal_connect (priv->manager, "notify::" NM_MANAGER_SLEEPING, (GCallback) sleeping_changed, priv);
|
||||
g_signal_connect (priv->manager, "notify::" NM_MANAGER_NETWORKING_ENABLED, (GCallback) sleeping_changed, priv);
|
||||
g_signal_connect (priv->manager, NM_MANAGER_INTERNAL_DEVICE_ADDED, (GCallback) device_added, priv);
|
||||
|
|
@ -2360,6 +2378,8 @@ constructed (GObject *object)
|
|||
g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_AGENT_REGISTERED, (GCallback) secret_agent_registered, priv);
|
||||
|
||||
G_OBJECT_CLASS (nm_policy_parent_class)->constructed (object);
|
||||
|
||||
_LOGD (LOGD_DNS, "hostname-mode: %s", _hostname_mode_to_string (priv->hostname_mode));
|
||||
}
|
||||
|
||||
NMPolicy *
|
||||
|
|
@ -2383,10 +2403,9 @@ dispose (GObject *object)
|
|||
GHashTableIter h_iter;
|
||||
NMDevice *device;
|
||||
|
||||
nm_clear_g_cancellable (&priv->lookup_cancellable);
|
||||
|
||||
g_clear_object (&priv->lookup_addr);
|
||||
g_clear_object (&priv->resolver);
|
||||
nm_clear_g_cancellable (&priv->lookup.cancellable);
|
||||
g_clear_object (&priv->lookup.addr);
|
||||
g_clear_object (&priv->lookup.resolver);
|
||||
|
||||
while (priv->pending_activation_checks)
|
||||
activate_data_free (priv->pending_activation_checks->data);
|
||||
|
|
@ -2424,6 +2443,11 @@ dispose (GObject *object)
|
|||
g_clear_pointer (&priv->cur_hostname, g_free);
|
||||
g_clear_pointer (&priv->last_hostname, g_free);
|
||||
|
||||
if (priv->hostname_manager) {
|
||||
g_signal_handlers_disconnect_by_data (priv->hostname_manager, priv);
|
||||
g_clear_object (&priv->hostname_manager);
|
||||
}
|
||||
|
||||
if (priv->settings) {
|
||||
g_signal_handlers_disconnect_by_data (priv->settings, priv);
|
||||
g_clear_object (&priv->settings);
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@
|
|||
#include "NetworkManagerUtils.h"
|
||||
#include "nm-dispatcher.h"
|
||||
#include "nm-inotify-helper.h"
|
||||
#include "nm-hostname-manager.h"
|
||||
|
||||
#include "introspection/org.freedesktop.NetworkManager.Settings.h"
|
||||
|
||||
|
|
@ -94,13 +95,6 @@ EXPORT(nm_settings_connection_replace_and_commit)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define HOSTNAMED_SERVICE_NAME "org.freedesktop.hostname1"
|
||||
#define HOSTNAMED_SERVICE_PATH "/org/freedesktop/hostname1"
|
||||
#define HOSTNAMED_SERVICE_INTERFACE "org.freedesktop.hostname1"
|
||||
|
||||
#define HOSTNAME_FILE_DEFAULT "/etc/hostname"
|
||||
#define HOSTNAME_FILE_UCASE_HOSTNAME "/etc/HOSTNAME"
|
||||
#define HOSTNAME_FILE_GENTOO "/etc/conf.d/hostname"
|
||||
#define IFCFG_DIR SYSCONFDIR "/sysconfig/network"
|
||||
#define CONF_DHCP IFCFG_DIR "/dhcp"
|
||||
|
||||
|
|
@ -162,14 +156,8 @@ typedef struct {
|
|||
gboolean started;
|
||||
gboolean startup_complete;
|
||||
|
||||
struct {
|
||||
char *value;
|
||||
GFileMonitor *monitor;
|
||||
GFileMonitor *dhcp_monitor;
|
||||
gulong monitor_id;
|
||||
gulong dhcp_monitor_id;
|
||||
GDBusProxy *hostnamed_proxy;
|
||||
} hostname;
|
||||
NMHostnameManager *hostname_manager;
|
||||
|
||||
} NMSettingsPrivate;
|
||||
|
||||
struct _NMSettings {
|
||||
|
|
@ -568,131 +556,6 @@ get_plugin (NMSettings *self, guint32 capability)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#if defined(HOSTNAME_PERSIST_GENTOO)
|
||||
static gchar *
|
||||
read_hostname_gentoo (const char *path)
|
||||
{
|
||||
gs_free char *contents = NULL;
|
||||
gs_strfreev char **all_lines = NULL;
|
||||
const char *tmp;
|
||||
guint i;
|
||||
|
||||
if (!g_file_get_contents (path, &contents, NULL, NULL))
|
||||
return NULL;
|
||||
|
||||
all_lines = g_strsplit (contents, "\n", 0);
|
||||
for (i = 0; all_lines[i]; i++) {
|
||||
g_strstrip (all_lines[i]);
|
||||
if (all_lines[i][0] == '#' || all_lines[i][0] == '\0')
|
||||
continue;
|
||||
if (g_str_has_prefix (all_lines[i], "hostname=")) {
|
||||
tmp = &all_lines[i][NM_STRLEN ("hostname=")];
|
||||
return g_shell_unquote (tmp, NULL);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HOSTNAME_PERSIST_SLACKWARE)
|
||||
static gchar *
|
||||
read_hostname_slackware (const char *path)
|
||||
{
|
||||
gs_free char *contents = NULL;
|
||||
gs_strfreev char **all_lines = NULL;
|
||||
char *tmp;
|
||||
guint i, j = 0;
|
||||
|
||||
if (!g_file_get_contents (path, &contents, NULL, NULL))
|
||||
return NULL;
|
||||
|
||||
all_lines = g_strsplit (contents, "\n", 0);
|
||||
for (i = 0; all_lines[i]; i++) {
|
||||
g_strstrip (all_lines[i]);
|
||||
if (all_lines[i][0] == '#' || all_lines[i][0] == '\0')
|
||||
continue;
|
||||
tmp = &all_lines[i][0];
|
||||
/* We only want up to the first '.' -- the rest of the */
|
||||
/* fqdn is defined in /etc/hosts */
|
||||
while (tmp[j] != '\0') {
|
||||
if (tmp[j] == '.') {
|
||||
tmp[j] = '\0';
|
||||
break;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
return g_shell_unquote (tmp, NULL);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HOSTNAME_PERSIST_SUSE)
|
||||
static gboolean
|
||||
hostname_is_dynamic (void)
|
||||
{
|
||||
GIOChannel *channel;
|
||||
char *str = NULL;
|
||||
gboolean dynamic = FALSE;
|
||||
|
||||
channel = g_io_channel_new_file (CONF_DHCP, "r", NULL);
|
||||
if (!channel)
|
||||
return dynamic;
|
||||
|
||||
while (g_io_channel_read_line (channel, &str, NULL, NULL, NULL) != G_IO_STATUS_EOF) {
|
||||
if (str) {
|
||||
g_strstrip (str);
|
||||
if (g_str_has_prefix (str, "DHCLIENT_SET_HOSTNAME="))
|
||||
dynamic = strcmp (&str[NM_STRLEN ("DHCLIENT_SET_HOSTNAME=")], "\"yes\"") == 0;
|
||||
g_free (str);
|
||||
}
|
||||
}
|
||||
|
||||
g_io_channel_shutdown (channel, FALSE, NULL);
|
||||
g_io_channel_unref (channel);
|
||||
|
||||
return dynamic;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Returns an allocated string which the caller owns and must eventually free */
|
||||
char *
|
||||
nm_settings_get_hostname (NMSettings *self)
|
||||
{
|
||||
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
|
||||
char *hostname = NULL;
|
||||
|
||||
if (!priv->started)
|
||||
return NULL;
|
||||
|
||||
if (priv->hostname.hostnamed_proxy) {
|
||||
hostname = g_strdup (priv->hostname.value);
|
||||
goto out;
|
||||
}
|
||||
|
||||
#if defined(HOSTNAME_PERSIST_SUSE)
|
||||
if (priv->hostname.dhcp_monitor_id && hostname_is_dynamic ())
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
#if defined(HOSTNAME_PERSIST_GENTOO)
|
||||
hostname = read_hostname_gentoo (HOSTNAME_FILE);
|
||||
#elif defined(HOSTNAME_PERSIST_SLACKWARE)
|
||||
hostname = read_hostname_slackware (HOSTNAME_FILE);
|
||||
#else
|
||||
if (g_file_get_contents (HOSTNAME_FILE, &hostname, NULL, NULL))
|
||||
g_strchomp (hostname);
|
||||
#endif
|
||||
|
||||
out:
|
||||
if (hostname && !hostname[0]) {
|
||||
g_free (hostname);
|
||||
hostname = NULL;
|
||||
}
|
||||
|
||||
return hostname;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
find_spec (GSList *spec_list, const char *spec)
|
||||
{
|
||||
|
|
@ -1626,160 +1489,7 @@ impl_settings_reload_connections (NMSettings *self,
|
|||
g_dbus_method_invocation_return_value (context, g_variant_new ("(b)", TRUE));
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
char *hostname;
|
||||
NMSettingsSetHostnameCb cb;
|
||||
gpointer user_data;
|
||||
} SetHostnameInfo;
|
||||
|
||||
static void
|
||||
set_transient_hostname_done (GObject *object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
GDBusProxy *proxy = G_DBUS_PROXY (object);
|
||||
gs_free SetHostnameInfo *info = user_data;
|
||||
gs_unref_variant GVariant *result = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
result = g_dbus_proxy_call_finish (proxy, res, &error);
|
||||
|
||||
if (error) {
|
||||
_LOGW ("couldn't set the system hostname to '%s' using hostnamed: %s",
|
||||
info->hostname, error->message);
|
||||
}
|
||||
|
||||
info->cb (info->hostname, !error, info->user_data);
|
||||
g_free (info->hostname);
|
||||
}
|
||||
|
||||
void
|
||||
nm_settings_set_transient_hostname (NMSettings *self,
|
||||
const char *hostname,
|
||||
NMSettingsSetHostnameCb cb,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMSettingsPrivate *priv;
|
||||
SetHostnameInfo *info;
|
||||
|
||||
g_return_if_fail (NM_IS_SETTINGS (self));
|
||||
priv = NM_SETTINGS_GET_PRIVATE (self);
|
||||
|
||||
if (!priv->hostname.hostnamed_proxy) {
|
||||
cb (hostname, FALSE, user_data);
|
||||
return;
|
||||
}
|
||||
|
||||
info = g_new0 (SetHostnameInfo, 1);
|
||||
info->hostname = g_strdup (hostname);
|
||||
info->cb = cb;
|
||||
info->user_data = user_data;
|
||||
|
||||
g_dbus_proxy_call (priv->hostname.hostnamed_proxy,
|
||||
"SetHostname",
|
||||
g_variant_new ("(sb)", hostname, FALSE),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
NULL,
|
||||
set_transient_hostname_done,
|
||||
info);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_settings_get_transient_hostname (NMSettings *self, char **hostname)
|
||||
{
|
||||
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
|
||||
GVariant *v_hostname;
|
||||
|
||||
if (!priv->hostname.hostnamed_proxy)
|
||||
return FALSE;
|
||||
|
||||
v_hostname = g_dbus_proxy_get_cached_property (priv->hostname.hostnamed_proxy,
|
||||
"Hostname");
|
||||
if (!v_hostname) {
|
||||
_LOGT ("transient hostname retrieval failed");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*hostname = g_variant_dup_string (v_hostname, NULL);
|
||||
g_variant_unref (v_hostname);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
write_hostname (NMSettingsPrivate *priv, const char *hostname)
|
||||
{
|
||||
char *hostname_eol;
|
||||
gboolean ret;
|
||||
gs_free_error GError *error = NULL;
|
||||
const char *file = HOSTNAME_FILE;
|
||||
gs_free char *link_path = NULL;
|
||||
gs_unref_variant GVariant *var = NULL;
|
||||
struct stat file_stat;
|
||||
#if HAVE_SELINUX
|
||||
security_context_t se_ctx_prev = NULL, se_ctx = NULL;
|
||||
mode_t st_mode = 0;
|
||||
#endif
|
||||
|
||||
if (priv->hostname.hostnamed_proxy) {
|
||||
var = g_dbus_proxy_call_sync (priv->hostname.hostnamed_proxy,
|
||||
"SetStaticHostname",
|
||||
g_variant_new ("(sb)", hostname, FALSE),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
NULL,
|
||||
&error);
|
||||
if (error)
|
||||
_LOGW ("could not set hostname: %s", error->message);
|
||||
|
||||
return !error;
|
||||
}
|
||||
|
||||
/* If the hostname file is a symbolic link, follow it to find where the
|
||||
* real file is located, otherwise g_file_set_contents will attempt to
|
||||
* replace the link with a plain file.
|
||||
*/
|
||||
if ( lstat (file, &file_stat) == 0
|
||||
&& S_ISLNK (file_stat.st_mode)
|
||||
&& (link_path = nm_utils_read_link_absolute (file, NULL)))
|
||||
file = link_path;
|
||||
|
||||
#if HAVE_SELINUX
|
||||
/* Get default context for hostname file and set it for fscreate */
|
||||
if (stat (file, &file_stat) == 0)
|
||||
st_mode = file_stat.st_mode;
|
||||
matchpathcon (file, st_mode, &se_ctx);
|
||||
matchpathcon_fini ();
|
||||
getfscreatecon (&se_ctx_prev);
|
||||
setfscreatecon (se_ctx);
|
||||
#endif
|
||||
|
||||
#if defined (HOSTNAME_PERSIST_GENTOO)
|
||||
hostname_eol = g_strdup_printf ("#Generated by NetworkManager\n"
|
||||
"hostname=\"%s\"\n", hostname);
|
||||
#else
|
||||
hostname_eol = g_strdup_printf ("%s\n", hostname);
|
||||
#endif
|
||||
|
||||
ret = g_file_set_contents (file, hostname_eol, -1, &error);
|
||||
|
||||
#if HAVE_SELINUX
|
||||
/* Restore previous context and cleanup */
|
||||
setfscreatecon (se_ctx_prev);
|
||||
freecon (se_ctx);
|
||||
freecon (se_ctx_prev);
|
||||
#endif
|
||||
|
||||
g_free (hostname_eol);
|
||||
|
||||
if (!ret) {
|
||||
_LOGW ("could not save hostname to %s: %s", file, error->message);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
pk_hostname_cb (NMAuthChain *chain,
|
||||
|
|
@ -1812,7 +1522,7 @@ pk_hostname_cb (NMAuthChain *chain,
|
|||
} else {
|
||||
hostname = nm_auth_chain_get_data (chain, "hostname");
|
||||
|
||||
if (!write_hostname (priv, hostname)) {
|
||||
if (!nm_hostname_manager_write_hostname (priv->hostname_manager, hostname)) {
|
||||
error = g_error_new_literal (NM_SETTINGS_ERROR,
|
||||
NM_SETTINGS_ERROR_FAILED,
|
||||
"Saving the hostname failed.");
|
||||
|
|
@ -1827,33 +1537,6 @@ pk_hostname_cb (NMAuthChain *chain,
|
|||
nm_auth_chain_unref (chain);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
validate_hostname (const char *hostname)
|
||||
{
|
||||
const char *p;
|
||||
gboolean dot = TRUE;
|
||||
|
||||
if (!hostname || !hostname[0])
|
||||
return FALSE;
|
||||
|
||||
for (p = hostname; *p; p++) {
|
||||
if (*p == '.') {
|
||||
if (dot)
|
||||
return FALSE;
|
||||
dot = TRUE;
|
||||
} else {
|
||||
if (!g_ascii_isalnum (*p) && (*p != '-') && (*p != '_'))
|
||||
return FALSE;
|
||||
dot = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (dot)
|
||||
return FALSE;
|
||||
|
||||
return (p - hostname <= HOST_NAME_MAX);
|
||||
}
|
||||
|
||||
static void
|
||||
impl_settings_save_hostname (NMSettings *self,
|
||||
GDBusMethodInvocation *context,
|
||||
|
|
@ -1864,7 +1547,7 @@ impl_settings_save_hostname (NMSettings *self,
|
|||
GError *error = NULL;
|
||||
|
||||
/* Minimal validation of the hostname */
|
||||
if (!validate_hostname (hostname)) {
|
||||
if (!nm_hostname_manager_validate_hostname (hostname)) {
|
||||
error = g_error_new_literal (NM_SETTINGS_ERROR,
|
||||
NM_SETTINGS_ERROR_INVALID_HOSTNAME,
|
||||
"The hostname was too long or contained invalid characters.");
|
||||
|
|
@ -1888,37 +1571,7 @@ done:
|
|||
g_dbus_method_invocation_take_error (context, error);
|
||||
}
|
||||
|
||||
static void
|
||||
hostname_maybe_changed (NMSettings *settings)
|
||||
{
|
||||
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (settings);
|
||||
char *new_hostname;
|
||||
|
||||
new_hostname = nm_settings_get_hostname (settings);
|
||||
|
||||
if ( (new_hostname && !priv->hostname.value)
|
||||
|| (!new_hostname && priv->hostname.value)
|
||||
|| (priv->hostname.value && new_hostname && strcmp (priv->hostname.value, new_hostname))) {
|
||||
|
||||
_LOGI ("hostname changed from %s%s%s to %s%s%s",
|
||||
NM_PRINT_FMT_QUOTED (priv->hostname.value, "\"", priv->hostname.value, "\"", "(none)"),
|
||||
NM_PRINT_FMT_QUOTED (new_hostname, "\"", new_hostname, "\"", "(none)"));
|
||||
g_free (priv->hostname.value);
|
||||
priv->hostname.value = new_hostname;
|
||||
_notify (settings, PROP_HOSTNAME);
|
||||
} else
|
||||
g_free (new_hostname);
|
||||
}
|
||||
|
||||
static void
|
||||
hostname_file_changed_cb (GFileMonitor *monitor,
|
||||
GFile *file,
|
||||
GFile *other_file,
|
||||
GFileMonitorEvent event_type,
|
||||
gpointer user_data)
|
||||
{
|
||||
hostname_maybe_changed (user_data);
|
||||
}
|
||||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
have_connection_for_device (NMSettings *self, NMDevice *device)
|
||||
|
|
@ -2141,95 +1794,19 @@ nm_settings_get_startup_complete (NMSettings *self)
|
|||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
hostnamed_properties_changed (GDBusProxy *proxy,
|
||||
GVariant *changed_properties,
|
||||
char **invalidated_properties,
|
||||
gpointer user_data)
|
||||
_hostname_changed_cb (NMHostnameManager *hostname_manager,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMSettings *self = user_data;
|
||||
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
|
||||
GVariant *v_hostname;
|
||||
const char *hostname;
|
||||
|
||||
v_hostname = g_dbus_proxy_get_cached_property (priv->hostname.hostnamed_proxy,
|
||||
"StaticHostname");
|
||||
if (!v_hostname)
|
||||
return;
|
||||
|
||||
hostname = g_variant_get_string (v_hostname, NULL);
|
||||
|
||||
if (g_strcmp0 (priv->hostname.value, hostname) != 0) {
|
||||
_LOGI ("hostname changed from %s%s%s to %s%s%s",
|
||||
NM_PRINT_FMT_QUOTED (priv->hostname.value, "\"", priv->hostname.value, "\"", "(none)"),
|
||||
NM_PRINT_FMT_QUOTED (hostname, "\"", hostname, "\"", "(none)"));
|
||||
g_free (priv->hostname.value);
|
||||
priv->hostname.value = g_strdup (hostname);
|
||||
_notify (self, PROP_HOSTNAME);
|
||||
nm_dispatcher_call_hostname (NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
g_variant_unref (v_hostname);
|
||||
_notify (user_data, PROP_HOSTNAME);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_hostname_file_monitors (NMSettings *self)
|
||||
{
|
||||
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
|
||||
GFileMonitor *monitor;
|
||||
const char *path = HOSTNAME_FILE;
|
||||
char *link_path = NULL;
|
||||
struct stat file_stat;
|
||||
GFile *file;
|
||||
|
||||
priv->hostname.value = nm_settings_get_hostname (self);
|
||||
|
||||
/* resolve the path to the hostname file if it is a symbolic link */
|
||||
if ( lstat(path, &file_stat) == 0
|
||||
&& S_ISLNK (file_stat.st_mode)
|
||||
&& (link_path = nm_utils_read_link_absolute (path, NULL))) {
|
||||
path = link_path;
|
||||
if ( lstat(link_path, &file_stat) == 0
|
||||
&& S_ISLNK (file_stat.st_mode)) {
|
||||
_LOGW ("only one level of symbolic link indirection is allowed when monitoring "
|
||||
HOSTNAME_FILE);
|
||||
}
|
||||
}
|
||||
|
||||
/* monitor changes to hostname file */
|
||||
file = g_file_new_for_path (path);
|
||||
monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, NULL);
|
||||
g_object_unref (file);
|
||||
g_free(link_path);
|
||||
if (monitor) {
|
||||
priv->hostname.monitor_id = g_signal_connect (monitor, "changed",
|
||||
G_CALLBACK (hostname_file_changed_cb),
|
||||
self);
|
||||
priv->hostname.monitor = monitor;
|
||||
}
|
||||
|
||||
#if defined (HOSTNAME_PERSIST_SUSE)
|
||||
/* monitor changes to dhcp file to know whether the hostname is valid */
|
||||
file = g_file_new_for_path (CONF_DHCP);
|
||||
monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, NULL);
|
||||
g_object_unref (file);
|
||||
if (monitor) {
|
||||
priv->hostname.dhcp_monitor_id = g_signal_connect (monitor, "changed",
|
||||
G_CALLBACK (hostname_file_changed_cb),
|
||||
self);
|
||||
priv->hostname.dhcp_monitor = monitor;
|
||||
}
|
||||
#endif
|
||||
|
||||
hostname_maybe_changed (self);
|
||||
}
|
||||
/*****************************************************************************/
|
||||
|
||||
gboolean
|
||||
nm_settings_start (NMSettings *self, GError **error)
|
||||
{
|
||||
NMSettingsPrivate *priv;
|
||||
GDBusProxy *proxy;
|
||||
GVariant *variant;
|
||||
GError *local_error = NULL;
|
||||
gs_strfreev char **plugins = NULL;
|
||||
|
||||
priv = NM_SETTINGS_GET_PRIVATE (self);
|
||||
|
|
@ -2245,33 +1822,14 @@ nm_settings_start (NMSettings *self, GError **error)
|
|||
load_connections (self);
|
||||
check_startup_complete (self);
|
||||
|
||||
proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, 0, NULL,
|
||||
HOSTNAMED_SERVICE_NAME, HOSTNAMED_SERVICE_PATH,
|
||||
HOSTNAMED_SERVICE_INTERFACE, NULL, &local_error);
|
||||
if (proxy) {
|
||||
variant = g_dbus_proxy_get_cached_property (proxy, "StaticHostname");
|
||||
if (variant) {
|
||||
_LOGI ("hostname: using hostnamed");
|
||||
priv->hostname.hostnamed_proxy = proxy;
|
||||
g_signal_connect (proxy, "g-properties-changed",
|
||||
G_CALLBACK (hostnamed_properties_changed), self);
|
||||
hostnamed_properties_changed (proxy, NULL, NULL, self);
|
||||
g_variant_unref (variant);
|
||||
} else {
|
||||
_LOGI ("hostname: couldn't get property from hostnamed");
|
||||
g_object_unref (proxy);
|
||||
}
|
||||
} else {
|
||||
_LOGI ("hostname: hostnamed not used as proxy creation failed with: %s",
|
||||
local_error->message);
|
||||
g_clear_error (&local_error);
|
||||
}
|
||||
priv->hostname_manager = g_object_ref (nm_hostname_manager_get ());
|
||||
g_signal_connect (priv->hostname_manager,
|
||||
"notify::"NM_HOSTNAME_MANAGER_HOSTNAME,
|
||||
G_CALLBACK (_hostname_changed_cb),
|
||||
self);
|
||||
if (nm_hostname_manager_get_hostname (priv->hostname_manager))
|
||||
_notify (self, PROP_HOSTNAME);
|
||||
|
||||
if (!priv->hostname.hostnamed_proxy)
|
||||
setup_hostname_file_monitors (self);
|
||||
|
||||
priv->started = TRUE;
|
||||
_notify (self, PROP_HOSTNAME);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -2298,11 +1856,10 @@ get_property (GObject *object, guint prop_id,
|
|||
g_value_take_boxed (value, (char **) g_ptr_array_free (array, FALSE));
|
||||
break;
|
||||
case PROP_HOSTNAME:
|
||||
g_value_take_string (value, nm_settings_get_hostname (self));
|
||||
|
||||
/* Don't ever pass NULL through D-Bus */
|
||||
if (!g_value_get_string (value))
|
||||
g_value_set_static_string (value, "");
|
||||
g_value_set_string (value,
|
||||
priv->hostname_manager
|
||||
? nm_hostname_manager_get_hostname (priv->hostname_manager)
|
||||
: NULL);
|
||||
break;
|
||||
case PROP_CAN_MODIFY:
|
||||
g_value_set_boolean (value, !!get_plugin (self, NM_SETTINGS_PLUGIN_CAP_MODIFY_CONNECTIONS));
|
||||
|
|
@ -2362,32 +1919,13 @@ dispose (GObject *object)
|
|||
|
||||
g_object_unref (priv->agent_mgr);
|
||||
|
||||
if (priv->hostname.hostnamed_proxy) {
|
||||
g_signal_handlers_disconnect_by_func (priv->hostname.hostnamed_proxy,
|
||||
G_CALLBACK (hostnamed_properties_changed),
|
||||
if (priv->hostname_manager) {
|
||||
g_signal_handlers_disconnect_by_func (priv->hostname_manager,
|
||||
G_CALLBACK (_hostname_changed_cb),
|
||||
self);
|
||||
g_clear_object (&priv->hostname.hostnamed_proxy);
|
||||
g_clear_object (&priv->hostname_manager);
|
||||
}
|
||||
|
||||
if (priv->hostname.monitor) {
|
||||
if (priv->hostname.monitor_id)
|
||||
g_signal_handler_disconnect (priv->hostname.monitor, priv->hostname.monitor_id);
|
||||
|
||||
g_file_monitor_cancel (priv->hostname.monitor);
|
||||
g_clear_object (&priv->hostname.monitor);
|
||||
}
|
||||
|
||||
if (priv->hostname.dhcp_monitor) {
|
||||
if (priv->hostname.dhcp_monitor_id)
|
||||
g_signal_handler_disconnect (priv->hostname.dhcp_monitor,
|
||||
priv->hostname.dhcp_monitor_id);
|
||||
|
||||
g_file_monitor_cancel (priv->hostname.dhcp_monitor);
|
||||
g_clear_object (&priv->hostname.dhcp_monitor);
|
||||
}
|
||||
|
||||
g_clear_pointer (&priv->hostname.value, g_free);
|
||||
|
||||
G_OBJECT_CLASS (nm_settings_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -119,20 +119,10 @@ gboolean nm_settings_has_connection (NMSettings *self, NMSettingsConnection *con
|
|||
|
||||
const GSList *nm_settings_get_unmanaged_specs (NMSettings *self);
|
||||
|
||||
char *nm_settings_get_hostname (NMSettings *self);
|
||||
|
||||
void nm_settings_device_added (NMSettings *self, NMDevice *device);
|
||||
|
||||
void nm_settings_device_removed (NMSettings *self, NMDevice *device, gboolean quitting);
|
||||
|
||||
gboolean nm_settings_get_startup_complete (NMSettings *self);
|
||||
|
||||
void nm_settings_set_transient_hostname (NMSettings *self,
|
||||
const char *hostname,
|
||||
NMSettingsSetHostnameCb cb,
|
||||
gpointer user_data);
|
||||
|
||||
gboolean nm_settings_get_transient_hostname (NMSettings *self,
|
||||
char **hostname);
|
||||
|
||||
#endif /* __NM_SETTINGS_H__ */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue