libnm-glib: implement new settings interfaces

The old NMExportedConnection was used for both client and server-side classes,
which was a mistake and made the code very complicated to follow.  Additionally,
all PolicyKit operations were synchronous, and PK operations can block for a
long time (ie for user input) before returning, so they need to be async.  But
NMExportedConnection and NMSysconfigConnection didn't allow for async PK ops
at all.

Use this opportunity to clean up the mess and create GInterfaces that both
server and client objects implement, so that the connection editor and applet
can operate on generic objects like they did before (using the interfaces) but
can perform specific operations (like async PK verification of callers) depending
on whether they are local or remote or whatever.
This commit is contained in:
Dan Williams 2009-07-23 09:20:52 -04:00
parent 8f0652a9f0
commit 0d69dfe39e
49 changed files with 3999 additions and 3102 deletions

View file

@ -212,42 +212,10 @@ PKG_CHECK_MODULES(UUID, uuid)
AC_SUBST(UUID_CFLAGS)
AC_SUBST(UUID_LIBS)
PKG_CHECK_MODULES(POLKIT, polkit-dbus)
PKG_CHECK_MODULES(POLKIT, polkit-gobject-1)
##### Find out the version of PolicyKit we're using
polkit_version=`pkg-config --modversion polkit`
POLKIT_VERSION_MAJOR=`echo $polkit_version | awk -F. '{print $1}'`
POLKIT_VERSION_MINOR=`echo $polkit_version | awk -F. '{print $2}'`
POLKIT_VERSION_MICRO=`echo $polkit_version | awk -F. '{print $3}'`
if test "z$POLKIT_VERSION_MAJOR" = "z"; then
POLKIT_VERSION_MAJOR="0"
fi
if test "z$POLKIT_VERSION_MINOR" = "z"; then
POLKIT_VERSION_MINOR="0"
fi
if test "z$POLKIT_VERSION_MICRO" = "z"; then
POLKIT_VERSION_MICRO="0"
fi
if test "z$POLKIT_VERSION_MAJOR" = "z0" -a "z$POLKIT_VERSION_MINOR" = "z0" -a "z$POLKIT_VERSION_MICRO" = "z0"; then
echo "Error: Couldn't determine the version of your PolicyKit package."
echo " This is probably an error in this script, please report it"
echo " along with the following information:"
echo " Base PolicyKit version ='$polkit_version'"
echo " POLKIT_VERSION_MAJOR='$POLKIT_VERSION_MAJOR'"
echo " POLKIT_VERSION_MINOR='$POLKIT_VERSION_MINOR'"
echo " POLKIT_VERSION_MICRO='$POLKIT_VERSION_MICRO'"
exit 1
else
echo "Your PolicyKit version is $POLKIT_VERSION_MAJOR,$POLKIT_VERSION_MINOR,$POLKIT_VERSION_MICRO."
POLKIT_CFLAGS="$POLKIT_CFLAGS -DPOLKIT_VERSION_MAJOR=$POLKIT_VERSION_MAJOR"
POLKIT_CFLAGS="$POLKIT_CFLAGS -DPOLKIT_VERSION_MINOR=$POLKIT_VERSION_MINOR"
POLKIT_CFLAGS="$POLKIT_CFLAGS -DPOLKIT_VERSION_MICRO=$POLKIT_VERSION_MICRO"
fi
AC_SUBST(POLKIT_CFLAGS)
AC_PATH_PROG([POLKIT_POLICY_FILE_VALIDATE], [polkit-policy-file-validate], [false])
AC_ARG_WITH(crypto, AS_HELP_STRING([--with-crypto=nss | gnutls], [Cryptography library to use for certificate and key operations]),ac_crypto=$withval, ac_crypto=nss)
with_nss=no

View file

@ -8,7 +8,7 @@
<method name="AddConnection">
<tp:docstring>
Add new connection.
DEPRECATED. Adds new connection.
</tp:docstring>
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_settings_add_connection"/>
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>

View file

@ -18,9 +18,22 @@
</arg>
</method>
<method name="AddConnection">
<tp:docstring>
Add new connection.
</tp:docstring>
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_settings_add_connection"/>
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="connection" type="a{sa{sv}}" direction="in">
<tp:docstring>
Connection settings and properties.
</tp:docstring>
</arg>
</method>
<signal name="NewConnection">
<tp:docstring>
Emitted when a new connection has been configured.
Emitted when a new connection has been added.
</tp:docstring>
<arg name="connection" type="o">
<tp:docstring>

View file

@ -41,7 +41,6 @@ libnminclude_HEADERS = \
nm-device-bt.h \
nm-access-point.h \
nm-ip4-config.h \
nm-settings.h \
nm-gsm-device.h \
nm-cdma-device.h \
nm-serial-device.h \
@ -50,10 +49,15 @@ libnminclude_HEADERS = \
nm-vpn-plugin-ui-interface.h \
nm-types.h \
nm-active-connection.h \
nm-dbus-connection.h \
nm-dbus-settings.h \
nm-dbus-settings-system.h \
nm-dhcp4-config.h
nm-dhcp4-config.h \
nm-remote-connection.h \
nm-settings-interface.h \
nm-settings-system-interface.h \
nm-remote-settings.h \
nm-remote-settings-system.h \
nm-settings-connection-interface.h \
nm-exported-connection.h \
nm-settings-service.h
libnm_glib_la_SOURCES = \
libnm_glib.c \
@ -69,7 +73,6 @@ libnm_glib_la_SOURCES = \
nm-device-bt.c \
nm-access-point.c \
nm-ip4-config.c \
nm-settings.c \
nm-gsm-device.c \
nm-cdma-device.c \
nm-serial-device.c \
@ -79,10 +82,15 @@ libnm_glib_la_SOURCES = \
nm-object-cache.c \
nm-object-cache.h \
nm-active-connection.c \
nm-dbus-connection.c \
nm-dbus-settings.c \
nm-dbus-settings-system.c \
nm-dhcp4-config.c
nm-dhcp4-config.c \
nm-remote-connection.c \
nm-settings-interface.c \
nm-settings-system-interface.c \
nm-remote-settings.c \
nm-remote-settings-system.c \
nm-settings-connection-interface.c \
nm-exported-connection.c \
nm-settings-service.c
libnm_glib_la_LIBADD = \
$(top_builddir)/libnm-util/libnm-util.la \

View file

@ -40,8 +40,6 @@ global:
nm_client_wireless_get_enabled;
nm_client_wireless_hardware_get_enabled;
nm_client_wireless_set_enabled;
nm_dbus_connection_get_type;
nm_dbus_connection_new;
nm_dbus_settings_get_connection_by_path;
nm_dbus_settings_get_type;
nm_dbus_settings_new;
@ -85,14 +83,9 @@ global:
nm_dhcp4_config_get_options;
nm_dhcp4_config_get_type;
nm_dhcp4_config_new;
nm_exported_connection_delete;
nm_exported_connection_get_connection;
nm_exported_connection_export;
nm_exported_connection_get_type;
nm_exported_connection_new;
nm_exported_connection_register_object;
nm_exported_connection_signal_removed;
nm_exported_connection_signal_updated;
nm_exported_connection_update;
nm_gsm_device_get_type;
nm_gsm_device_new;
nm_ip4_config_get_addresses;
@ -107,9 +100,31 @@ global:
nm_object_get_connection;
nm_object_get_path;
nm_object_get_type;
nm_remote_connection_get_type;
nm_remote_connection_new;
nm_remote_settings_get_type;
nm_remote_settings_new;
nm_remote_settings_system_get_type;
nm_remote_settings_system_new;
nm_serial_device_get_bytes_received;
nm_serial_device_get_bytes_sent;
nm_serial_device_get_type;
nm_settings_connection_interface_delete;
nm_settings_connection_interface_emit_updated;
nm_settings_connection_interface_get_secrets;
nm_settings_connection_interface_get_type;
nm_settings_connection_interface_update;
nm_settings_interface_add_connection;
nm_settings_interface_error_quark;
nm_settings_interface_get_connection_by_path;
nm_settings_interface_get_type;
nm_settings_interface_list_connections;
nm_settings_service_export;
nm_settings_service_get_connection_by_path;
nm_settings_service_get_type;
nm_settings_system_interface_get_type;
nm_settings_system_interface_add_connection;
nm_settings_system_interface_save_hostname;
nm_settings_error_quark;
nm_settings_get_type;
nm_settings_list_connections;

View file

@ -1,323 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* libnm_glib -- Access network status & information from glib applications
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright (C) 2008 Novell, Inc.
* Copyright (C) 2008 Red Hat, Inc.
*/
#include <string.h>
#include <NetworkManager.h>
#include <nm-dbus-glib-types.h>
#include "nm-dbus-connection.h"
#include "nm-exported-connection-bindings.h"
#include "nm-utils.h"
G_DEFINE_TYPE (NMDBusConnection, nm_dbus_connection, NM_TYPE_EXPORTED_CONNECTION)
#define NM_DBUS_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DBUS_CONNECTION, NMDBusConnectionPrivate))
typedef struct {
DBusGConnection *dbus_connection;
NMConnectionScope scope;
char *path;
DBusGProxy *proxy;
gboolean disposed;
} NMDBusConnectionPrivate;
enum {
PROP_0,
PROP_BUS,
PROP_SCOPE,
PROP_PATH,
LAST_PROP
};
NMDBusConnection *
nm_dbus_connection_new (DBusGConnection *dbus_connection,
NMConnectionScope scope,
const char *path)
{
g_return_val_if_fail (dbus_connection != NULL, NULL);
g_return_val_if_fail (scope != NM_CONNECTION_SCOPE_UNKNOWN, NULL);
g_return_val_if_fail (path != NULL, NULL);
return (NMDBusConnection *) g_object_new (NM_TYPE_DBUS_CONNECTION,
NM_DBUS_CONNECTION_BUS, dbus_connection,
NM_DBUS_CONNECTION_SCOPE, scope,
NM_DBUS_CONNECTION_PATH, path,
NULL);
}
static GHashTable *
get_settings (NMExportedConnection *exported)
{
return nm_connection_to_hash (nm_exported_connection_get_connection (exported));
}
static gboolean
update (NMExportedConnection *exported, GHashTable *new_settings, GError **err)
{
NMDBusConnectionPrivate *priv = NM_DBUS_CONNECTION_GET_PRIVATE (exported);
return org_freedesktop_NetworkManagerSettings_Connection_update (priv->proxy, new_settings, err);
}
static gboolean
do_delete (NMExportedConnection *exported, GError **err)
{
NMDBusConnectionPrivate *priv = NM_DBUS_CONNECTION_GET_PRIVATE (exported);
return org_freedesktop_NetworkManagerSettings_Connection_delete (priv->proxy, err);
}
static void
connection_updated_cb (DBusGProxy *proxy, GHashTable *settings, gpointer user_data)
{
NMExportedConnection *exported = NM_EXPORTED_CONNECTION (user_data);
NMConnection *wrapped;
GError *error = NULL;
wrapped = nm_exported_connection_get_connection (exported);
if (nm_connection_replace_settings (wrapped, settings, &error))
nm_exported_connection_signal_updated (exported, settings);
else {
g_warning ("%s: '%s' / '%s' invalid: %d",
__func__,
error ? g_type_name (nm_connection_lookup_setting_type_by_quark (error->domain)) : "(none)",
(error && error->message) ? error->message : "(none)",
error ? error->code : -1);
g_clear_error (&error);
nm_exported_connection_signal_removed (exported);
}
}
static void
connection_removed_cb (DBusGProxy *proxy, gpointer user_data)
{
nm_exported_connection_signal_removed (NM_EXPORTED_CONNECTION (user_data));
}
/* GObject */
static void
nm_dbus_connection_init (NMDBusConnection *connection)
{
}
static GObject *
constructor (GType type,
guint n_construct_params,
GObjectConstructParam *construct_params)
{
GObject *object;
NMDBusConnectionPrivate *priv;
NMConnection *wrapped;
const char *service;
GHashTable *settings = NULL;
GError *error = NULL;
object = G_OBJECT_CLASS (nm_dbus_connection_parent_class)->constructor (type, n_construct_params, construct_params);
if (!object)
return NULL;
priv = NM_DBUS_CONNECTION_GET_PRIVATE (object);
if (!priv->dbus_connection) {
nm_warning ("DBusGConnection not provided.");
goto err;
}
if (!priv->path)
nm_warning ("DBus path not provided.");
service = (priv->scope == NM_CONNECTION_SCOPE_SYSTEM) ?
NM_DBUS_SERVICE_SYSTEM_SETTINGS : NM_DBUS_SERVICE_USER_SETTINGS;
priv->proxy = dbus_g_proxy_new_for_name (priv->dbus_connection,
service,
priv->path,
NM_DBUS_IFACE_SETTINGS_CONNECTION);
if (!org_freedesktop_NetworkManagerSettings_Connection_get_settings (priv->proxy, &settings, &error)) {
nm_warning ("Can not retrieve settings: %s", error->message);
g_error_free (error);
goto err;
}
wrapped = nm_connection_new_from_hash (settings, &error);
g_hash_table_destroy (settings);
if (!wrapped) {
nm_warning ("Invalid connection: '%s' / '%s' invalid: %d",
g_type_name (nm_connection_lookup_setting_type_by_quark (error->domain)),
error->message,
error->code);
g_error_free (error);
goto err;
}
nm_connection_set_scope (wrapped, priv->scope);
nm_connection_set_path (wrapped, priv->path);
g_object_set (object, NM_EXPORTED_CONNECTION_CONNECTION, wrapped, NULL);
g_object_unref (wrapped);
dbus_g_proxy_add_signal (priv->proxy, "Updated",
DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT,
G_TYPE_INVALID);
dbus_g_proxy_connect_signal (priv->proxy, "Updated",
G_CALLBACK (connection_updated_cb),
object, NULL);
dbus_g_proxy_add_signal (priv->proxy, "Removed", G_TYPE_INVALID, G_TYPE_INVALID);
dbus_g_proxy_connect_signal (priv->proxy, "Removed",
G_CALLBACK (connection_removed_cb),
object, NULL);
return object;
err:
g_object_unref (object);
return NULL;
}
static void
dispose (GObject *object)
{
NMDBusConnectionPrivate *priv = NM_DBUS_CONNECTION_GET_PRIVATE (object);
if (priv->disposed)
return;
priv->disposed = TRUE;
g_object_unref (priv->proxy);
dbus_g_connection_unref (priv->dbus_connection);
G_OBJECT_CLASS (nm_dbus_connection_parent_class)->dispose (object);
}
static void
finalize (GObject *object)
{
NMDBusConnectionPrivate *priv = NM_DBUS_CONNECTION_GET_PRIVATE (object);
g_free (priv->path);
G_OBJECT_CLASS (nm_dbus_connection_parent_class)->finalize (object);
}
static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
NMDBusConnectionPrivate *priv = NM_DBUS_CONNECTION_GET_PRIVATE (object);
switch (prop_id) {
case PROP_BUS:
/* Construct only */
priv->dbus_connection = dbus_g_connection_ref ((DBusGConnection *) g_value_get_boxed (value));
break;
case PROP_SCOPE:
/* Construct only */
priv->scope = (NMConnectionScope) g_value_get_uint (value);
break;
case PROP_PATH:
/* Construct only */
priv->path = g_value_dup_string (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
NMDBusConnectionPrivate *priv = NM_DBUS_CONNECTION_GET_PRIVATE (object);
switch (prop_id) {
case PROP_BUS:
g_value_set_boxed (value, priv->dbus_connection);
break;
case PROP_SCOPE:
g_value_set_uint (value, priv->scope);
break;
case PROP_PATH:
g_value_set_string (value, priv->path);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
nm_dbus_connection_class_init (NMDBusConnectionClass *dbus_connection_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (dbus_connection_class);
NMExportedConnectionClass *connection_class = NM_EXPORTED_CONNECTION_CLASS (dbus_connection_class);
g_type_class_add_private (dbus_connection_class, sizeof (NMDBusConnectionPrivate));
/* Virtual methods */
object_class->constructor = constructor;
object_class->set_property = set_property;
object_class->get_property = get_property;
object_class->dispose = dispose;
object_class->finalize = finalize;
connection_class->get_settings = get_settings;
connection_class->update = update;
connection_class->do_delete = do_delete;
/* Properties */
g_object_class_install_property
(object_class, PROP_BUS,
g_param_spec_boxed (NM_DBUS_CONNECTION_BUS,
"DBusGConnection",
"DBusGConnection",
DBUS_TYPE_G_CONNECTION,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property
(object_class, PROP_SCOPE,
g_param_spec_uint (NM_DBUS_CONNECTION_SCOPE,
"Scope",
"NMConnection scope",
NM_CONNECTION_SCOPE_UNKNOWN,
NM_CONNECTION_SCOPE_USER,
NM_CONNECTION_SCOPE_UNKNOWN,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property
(object_class, PROP_PATH,
g_param_spec_string (NM_DBUS_CONNECTION_PATH,
"DBus path",
"DBus path",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
}

View file

@ -1,59 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* libnm_glib -- Access network status & information from glib applications
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright (C) 2008 Novell, Inc.
* Copyright (C) 2008 Red Hat, Inc.
*/
#ifndef NM_DBUS_CONNECTION_H
#define NM_DBUS_CONNECTION_H
#include <dbus/dbus-glib.h>
#include <nm-settings.h>
G_BEGIN_DECLS
#define NM_TYPE_DBUS_CONNECTION (nm_dbus_connection_get_type ())
#define NM_DBUS_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DBUS_CONNECTION, NMDBusConnection))
#define NM_DBUS_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DBUS_CONNECTION, NMDBusConnectionClass))
#define NM_IS_DBUS_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DBUS_CONNECTION))
#define NM_IS_DBUS_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DBUS_CONNECTION))
#define NM_DBUS_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DBUS_CONNECTION, NMDBusConnectionClass))
#define NM_DBUS_CONNECTION_BUS "bus"
#define NM_DBUS_CONNECTION_SCOPE "scope"
#define NM_DBUS_CONNECTION_PATH "path"
typedef struct {
NMExportedConnection parent;
} NMDBusConnection;
typedef struct {
NMExportedConnectionClass parent;
} NMDBusConnectionClass;
GType nm_dbus_connection_get_type (void);
NMDBusConnection *nm_dbus_connection_new (DBusGConnection *dbus_connection,
NMConnectionScope scope,
const char *path);
G_END_DECLS
#endif /* NM_DBUS_CONNECTION_H */

View file

@ -1,391 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* libnm_glib -- Access network status & information from glib applications
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright (C) 2008 Novell, Inc.
* Copyright (C) 2008 Red Hat, Inc.
*/
#include <NetworkManager.h>
#include <nm-dbus-glib-types.h>
#include "nm-dbus-settings-system.h"
#include "nm-settings-system-bindings.h"
G_DEFINE_TYPE (NMDBusSettingsSystem, nm_dbus_settings_system, NM_TYPE_DBUS_SETTINGS)
#define NM_DBUS_SETTINGS_SYSTEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DBUS_SETTINGS_SYSTEM, NMDBusSettingsSystemPrivate))
typedef struct {
DBusGProxy *settings_proxy;
DBusGProxy *props_proxy;
gboolean got_unmanaged_devices;
GSList *unmanaged_devices;
gboolean got_hostname;
char *hostname;
gboolean got_can_modify;
gboolean can_modify;
gboolean disposed;
} NMDBusSettingsSystemPrivate;
enum {
PROP_0,
PROP_UNMANAGED_DEVICES,
PROP_HOSTNAME,
PROP_CAN_MODIFY,
LAST_PROP
};
NMDBusSettingsSystem *
nm_dbus_settings_system_new (DBusGConnection *dbus_connection)
{
g_return_val_if_fail (dbus_connection != NULL, NULL);
return (NMDBusSettingsSystem *) g_object_new (NM_TYPE_DBUS_SETTINGS_SYSTEM,
NM_DBUS_SETTINGS_DBUS_CONNECTION, dbus_connection,
NM_DBUS_SETTINGS_SCOPE, NM_CONNECTION_SCOPE_SYSTEM,
NULL);
}
gboolean
nm_dbus_settings_system_add_connection (NMDBusSettingsSystem *self,
NMConnection *connection,
GError **err)
{
NMDBusSettingsSystemPrivate *priv;
GHashTable *settings;
gboolean ret;
g_return_val_if_fail (NM_IS_DBUS_SETTINGS_SYSTEM (self), FALSE);
g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
priv = NM_DBUS_SETTINGS_SYSTEM_GET_PRIVATE (self);
settings = nm_connection_to_hash (connection);
ret = org_freedesktop_NetworkManagerSettings_System_add_connection (priv->settings_proxy, settings, err);
g_hash_table_destroy (settings);
return ret;
}
static void
update_unmanaged_devices (NMDBusSettingsSystem *self, GValue *value)
{
NMDBusSettingsSystemPrivate *priv = NM_DBUS_SETTINGS_SYSTEM_GET_PRIVATE (self);
if (priv->unmanaged_devices) {
g_slist_foreach (priv->unmanaged_devices, (GFunc) g_free, NULL);
g_slist_free (priv->unmanaged_devices);
priv->unmanaged_devices = NULL;
}
if (G_VALUE_TYPE (value) == DBUS_TYPE_G_OBJECT_ARRAY) {
GPtrArray *array;
int i;
array = (GPtrArray *) g_value_get_boxed (value);
for (i = 0; i < array->len; i++)
priv->unmanaged_devices = g_slist_prepend (priv->unmanaged_devices,
g_strdup ((const char *) g_ptr_array_index (array, i)));
priv->got_unmanaged_devices = TRUE;
} else
g_warning ("Invalid return value type: %s", G_VALUE_TYPE_NAME (value));
}
GSList *
nm_dbus_settings_system_get_unmanaged_devices (NMDBusSettingsSystem *self)
{
NMDBusSettingsSystemPrivate *priv;
GValue value = { 0, };
GError *err = NULL;
g_return_val_if_fail (NM_IS_DBUS_SETTINGS_SYSTEM (self), NULL);
priv = NM_DBUS_SETTINGS_SYSTEM_GET_PRIVATE (self);
if (priv->got_unmanaged_devices)
return priv->unmanaged_devices;
if (!dbus_g_proxy_call (priv->props_proxy, "Get", &err,
G_TYPE_STRING, NM_DBUS_SERVICE_SYSTEM_SETTINGS,
G_TYPE_STRING, "UnmanagedDevices",
G_TYPE_INVALID,
G_TYPE_VALUE, &value,
G_TYPE_INVALID)) {
g_warning ("Could not retrieve unmanaged devices: %s", err->message);
g_error_free (err);
return NULL;
}
update_unmanaged_devices (self, &value);
g_value_unset (&value);
return priv->unmanaged_devices;
}
gboolean
nm_dbus_settings_system_save_hostname (NMDBusSettingsSystem *self,
const char *hostname,
GError **err)
{
NMDBusSettingsSystemPrivate *priv;
g_return_val_if_fail (NM_IS_DBUS_SETTINGS_SYSTEM (self), FALSE);
priv = NM_DBUS_SETTINGS_SYSTEM_GET_PRIVATE (self);
return org_freedesktop_NetworkManagerSettings_System_save_hostname (priv->settings_proxy, hostname ? hostname : "", err);
}
static void
update_hostname (NMDBusSettingsSystem *self, GValue *value)
{
NMDBusSettingsSystemPrivate *priv = NM_DBUS_SETTINGS_SYSTEM_GET_PRIVATE (self);
if (priv->hostname) {
g_free (priv->hostname);
priv->hostname = NULL;
}
if (G_VALUE_TYPE (value) == G_TYPE_STRING) {
priv->hostname = g_value_dup_string (value);
priv->got_hostname = TRUE;
} else
g_warning ("%s: Invalid return value type: %s", __func__, G_VALUE_TYPE_NAME (value));
}
const char *
nm_dbus_settings_system_get_hostname (NMDBusSettingsSystem *self)
{
NMDBusSettingsSystemPrivate *priv;
GValue value = { 0, };
GError *err = NULL;
g_return_val_if_fail (NM_IS_DBUS_SETTINGS_SYSTEM (self), NULL);
priv = NM_DBUS_SETTINGS_SYSTEM_GET_PRIVATE (self);
if (priv->got_hostname)
return priv->hostname;
if (!dbus_g_proxy_call (priv->props_proxy, "Get", &err,
G_TYPE_STRING, NM_DBUS_SERVICE_SYSTEM_SETTINGS,
G_TYPE_STRING, "Hostname",
G_TYPE_INVALID,
G_TYPE_VALUE, &value,
G_TYPE_INVALID)) {
g_warning ("Could not retrieve hostname: %s", err->message);
g_error_free (err);
return NULL;
}
update_hostname (self, &value);
g_value_unset (&value);
return priv->hostname;
}
gboolean
nm_dbus_settings_system_get_can_modify (NMDBusSettingsSystem *self)
{
NMDBusSettingsSystemPrivate *priv;
GValue value = { 0, };
GError *err = NULL;
g_return_val_if_fail (NM_IS_DBUS_SETTINGS_SYSTEM (self), FALSE);
priv = NM_DBUS_SETTINGS_SYSTEM_GET_PRIVATE (self);
if (priv->got_can_modify)
return priv->can_modify;
if (!dbus_g_proxy_call (priv->props_proxy, "Get", &err,
G_TYPE_STRING, NM_DBUS_SERVICE_SYSTEM_SETTINGS,
G_TYPE_STRING, "CanModify",
G_TYPE_INVALID,
G_TYPE_VALUE, &value,
G_TYPE_INVALID)) {
g_warning ("Could not retrieve can-modify: %s", err->message);
g_error_free (err);
return FALSE;
}
priv->can_modify = g_value_get_boolean (&value);
g_value_unset (&value);
return priv->can_modify;
}
static void
proxy_properties_changed (DBusGProxy *proxy,
GHashTable *properties,
gpointer user_data)
{
NMDBusSettingsSystem *self = NM_DBUS_SETTINGS_SYSTEM (user_data);
NMDBusSettingsSystemPrivate * priv = NM_DBUS_SETTINGS_SYSTEM_GET_PRIVATE (self);
GValue *value;
value = (GValue *) g_hash_table_lookup (properties, "UnmanagedDevices");
if (value) {
update_unmanaged_devices (self, value);
g_object_notify (G_OBJECT (self), NM_DBUS_SETTINGS_SYSTEM_UNMANAGED_DEVICES);
}
value = (GValue *) g_hash_table_lookup (properties, "Hostname");
if (value) {
update_hostname (self, value);
g_object_notify (G_OBJECT (self), NM_DBUS_SETTINGS_SYSTEM_HOSTNAME);
}
value = (GValue *) g_hash_table_lookup (properties, "CanModify");
if (value) {
priv->can_modify = g_value_get_boolean (value);
g_object_notify (G_OBJECT (self), NM_DBUS_SETTINGS_SYSTEM_CAN_MODIFY);
}
}
static void
nm_dbus_settings_system_init (NMDBusSettingsSystem *self)
{
}
static GObject *
constructor (GType type,
guint n_construct_params,
GObjectConstructParam *construct_params)
{
GObject *object;
NMDBusSettingsSystemPrivate *priv;
DBusGConnection *dbus_connection = NULL;
object = G_OBJECT_CLASS (nm_dbus_settings_system_parent_class)->constructor (type, n_construct_params, construct_params);
if (!object)
return NULL;
priv = NM_DBUS_SETTINGS_SYSTEM_GET_PRIVATE (object);
g_object_get (object,
NM_DBUS_SETTINGS_DBUS_CONNECTION, &dbus_connection,
NULL);
priv->settings_proxy = dbus_g_proxy_new_for_name (dbus_connection,
NM_DBUS_SERVICE_SYSTEM_SETTINGS,
NM_DBUS_PATH_SETTINGS,
NM_DBUS_IFACE_SETTINGS_SYSTEM);
dbus_g_proxy_add_signal (priv->settings_proxy, "PropertiesChanged",
DBUS_TYPE_G_MAP_OF_VARIANT, G_TYPE_INVALID);
dbus_g_proxy_connect_signal (priv->settings_proxy, "PropertiesChanged",
G_CALLBACK (proxy_properties_changed),
object, NULL);
priv->props_proxy = dbus_g_proxy_new_for_name (dbus_connection,
NM_DBUS_SERVICE_SYSTEM_SETTINGS,
NM_DBUS_PATH_SETTINGS,
"org.freedesktop.DBus.Properties");
return object;
}
static void
dispose (GObject *object)
{
NMDBusSettingsSystemPrivate *priv = NM_DBUS_SETTINGS_SYSTEM_GET_PRIVATE (object);
if (priv->disposed)
return;
priv->disposed = TRUE;
g_free (priv->hostname);
if (priv->unmanaged_devices) {
g_slist_foreach (priv->unmanaged_devices, (GFunc) g_free, NULL);
g_slist_free (priv->unmanaged_devices);
}
g_object_unref (priv->settings_proxy);
g_object_unref (priv->props_proxy);
G_OBJECT_CLASS (nm_dbus_settings_system_parent_class)->dispose (object);
}
static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
NMDBusSettingsSystem *self = NM_DBUS_SETTINGS_SYSTEM (object);
switch (prop_id) {
case PROP_UNMANAGED_DEVICES:
g_value_set_pointer (value, nm_dbus_settings_system_get_unmanaged_devices (self));
break;
case PROP_HOSTNAME:
g_value_set_string (value, nm_dbus_settings_system_get_hostname (self));
break;
case PROP_CAN_MODIFY:
g_value_set_boolean (value, nm_dbus_settings_system_get_can_modify (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
nm_dbus_settings_system_class_init (NMDBusSettingsSystemClass *dbus_settings_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (dbus_settings_class);
g_type_class_add_private (dbus_settings_class, sizeof (NMDBusSettingsSystemPrivate));
/* Virtual methods */
object_class->constructor = constructor;
object_class->get_property = get_property;
object_class->dispose = dispose;
/* Properties */
g_object_class_install_property
(object_class, PROP_UNMANAGED_DEVICES,
g_param_spec_pointer (NM_DBUS_SETTINGS_SYSTEM_UNMANAGED_DEVICES,
"Unmanaged devices",
"Unmanaged devices",
G_PARAM_READABLE));
g_object_class_install_property
(object_class, PROP_HOSTNAME,
g_param_spec_string (NM_DBUS_SETTINGS_SYSTEM_HOSTNAME,
"Hostname",
"Configured hostname",
NULL,
G_PARAM_READABLE));
g_object_class_install_property
(object_class, PROP_HOSTNAME,
g_param_spec_boolean (NM_DBUS_SETTINGS_SYSTEM_CAN_MODIFY,
"Can modify",
"Can modify",
FALSE,
G_PARAM_READABLE));
}

View file

@ -1,70 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* libnm_glib -- Access network status & information from glib applications
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright (C) 2008 Novell, Inc.
* Copyright (C) 2008 Red Hat, Inc.
*/
#ifndef NM_DBUS_SETTINGS_SYSTEM_H
#define NM_DBUS_SETTINGS_SYSTEM_H
#include <nm-dbus-settings.h>
G_BEGIN_DECLS
#define NM_TYPE_DBUS_SETTINGS_SYSTEM (nm_dbus_settings_system_get_type ())
#define NM_DBUS_SETTINGS_SYSTEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DBUS_SETTINGS_SYSTEM, NMDBusSettingsSystem))
#define NM_DBUS_SETTINGS_SYSTEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DBUS_SETTINGS_SYSTEM, NMDBusSettingsSystemClass))
#define NM_IS_DBUS_SETTINGS_SYSTEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DBUS_SETTINGS_SYSTEM))
#define NM_IS_DBUS_SETTINGS_SYSTEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DBUS_SETTINGS_SYSTEM))
#define NM_DBUS_SETTINGS_SYSTEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DBUS_SETTINGS_SYSTEM, NMDBusSettingsSystemClass))
#define NM_DBUS_SETTINGS_SYSTEM_UNMANAGED_DEVICES "unmanaged-devices"
#define NM_DBUS_SETTINGS_SYSTEM_HOSTNAME "hostname"
#define NM_DBUS_SETTINGS_SYSTEM_CAN_MODIFY "can-modify"
typedef struct {
NMDBusSettings parent;
} NMDBusSettingsSystem;
typedef struct {
NMDBusSettingsClass parent;
} NMDBusSettingsSystemClass;
GType nm_dbus_settings_system_get_type (void);
NMDBusSettingsSystem *nm_dbus_settings_system_new (DBusGConnection *dbus_connection);
gboolean nm_dbus_settings_system_add_connection (NMDBusSettingsSystem *self,
NMConnection *connection,
GError **err);
GSList *nm_dbus_settings_system_get_unmanaged_devices (NMDBusSettingsSystem *self);
const char *nm_dbus_settings_system_get_hostname (NMDBusSettingsSystem *self);
gboolean nm_dbus_settings_system_save_hostname (NMDBusSettingsSystem *self,
const char *hostname,
GError **err);
gboolean nm_dbus_settings_system_get_can_modify (NMDBusSettingsSystem *self);
G_END_DECLS
#endif /* NM_DBUS_SETTINGS_SYSTEM_H */

View file

@ -1,373 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* libnm_glib -- Access network status & information from glib applications
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright (C) 2008 Novell, Inc.
*/
#include <string.h>
#include <NetworkManager.h>
#include <nm-connection.h>
#include "nm-dbus-settings.h"
#include "nm-settings-bindings.h"
G_DEFINE_TYPE (NMDBusSettings, nm_dbus_settings, NM_TYPE_SETTINGS)
#define NM_DBUS_SETTINGS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DBUS_SETTINGS, NMDBusSettingsPrivate))
typedef struct {
DBusGConnection *dbus_connection;
NMConnectionScope scope;
DBusGProxy *settings_proxy;
DBusGProxy *dbus_proxy;
GHashTable *connections;
gboolean disposed;
} NMDBusSettingsPrivate;
enum {
PROP_0,
PROP_DBUS_CONNECTION,
PROP_SCOPE,
LAST_PROP
};
NMDBusSettings *
nm_dbus_settings_new (DBusGConnection *dbus_connection)
{
g_return_val_if_fail (dbus_connection != NULL, NULL);
return (NMDBusSettings *) g_object_new (NM_TYPE_DBUS_SETTINGS,
NM_DBUS_SETTINGS_DBUS_CONNECTION, dbus_connection,
NM_DBUS_SETTINGS_SCOPE, NM_CONNECTION_SCOPE_USER,
NULL);
}
NMDBusConnection *
nm_dbus_settings_get_connection_by_path (NMDBusSettings *self, const char *path)
{
g_return_val_if_fail (NM_IS_DBUS_SETTINGS (self), NULL);
g_return_val_if_fail (path != NULL, NULL);
return g_hash_table_lookup (NM_DBUS_SETTINGS_GET_PRIVATE (self)->connections, path);
}
static void
connection_removed_cb (NMExportedConnection *exported, gpointer user_data)
{
NMDBusSettingsPrivate *priv = NM_DBUS_SETTINGS_GET_PRIVATE (user_data);
NMConnection *connection;
connection = nm_exported_connection_get_connection (exported);
g_hash_table_remove (priv->connections, nm_connection_get_path (connection));
}
static void
new_connection_cb (DBusGProxy *proxy,
const char *path,
gpointer user_data)
{
NMDBusSettingsPrivate *priv = NM_DBUS_SETTINGS_GET_PRIVATE (user_data);
NMDBusConnection *connection;
connection = nm_dbus_connection_new (priv->dbus_connection, priv->scope, path);
if (connection) {
g_signal_connect (connection, "removed",
G_CALLBACK (connection_removed_cb),
user_data);
g_hash_table_insert (priv->connections, g_strdup (path), connection);
nm_settings_signal_new_connection (NM_SETTINGS (user_data),
NM_EXPORTED_CONNECTION (connection));
}
}
static void
fetch_connections_done (DBusGProxy *proxy,
GPtrArray *connections,
GError *err,
gpointer user_data)
{
if (!err) {
int i;
for (i = 0; i < connections->len; i++) {
char *path = g_ptr_array_index (connections, i);
new_connection_cb (proxy, path, user_data);
g_free (path);
}
g_ptr_array_free (connections, TRUE);
} else {
g_warning ("Could not retrieve dbus connections: %s.", err->message);
g_error_free (err);
}
}
static void
settings_proxy_destroyed (gpointer data, GObject *destroyed_object)
{
NM_DBUS_SETTINGS_GET_PRIVATE (data)->settings_proxy = NULL;
}
static gboolean
fetch_connections (gpointer data)
{
NMDBusSettingsPrivate *priv = NM_DBUS_SETTINGS_GET_PRIVATE (data);
DBusGProxyCall *call;
if (!priv->settings_proxy) {
const char *service = (priv->scope == NM_CONNECTION_SCOPE_SYSTEM) ?
NM_DBUS_SERVICE_SYSTEM_SETTINGS : NM_DBUS_SERVICE_USER_SETTINGS;
priv->settings_proxy = dbus_g_proxy_new_for_name (priv->dbus_connection,
service,
NM_DBUS_PATH_SETTINGS,
NM_DBUS_IFACE_SETTINGS);
g_object_weak_ref (G_OBJECT (priv->settings_proxy), settings_proxy_destroyed, data);
dbus_g_proxy_add_signal (priv->settings_proxy, "NewConnection",
DBUS_TYPE_G_OBJECT_PATH,
G_TYPE_INVALID);
dbus_g_proxy_connect_signal (priv->settings_proxy, "NewConnection",
G_CALLBACK (new_connection_cb),
data,
NULL);
}
call = org_freedesktop_NetworkManagerSettings_list_connections_async (priv->settings_proxy,
fetch_connections_done,
data);
return FALSE;
}
static void
hash_values_to_slist (gpointer key, gpointer data, gpointer user_data)
{
GSList **list = (GSList **) user_data;
*list = g_slist_prepend (*list, data);
}
static GSList *
list_connections (NMSettings *settings)
{
GSList *list = NULL;
g_return_val_if_fail (NM_IS_DBUS_SETTINGS (settings), NULL);
g_hash_table_foreach (NM_DBUS_SETTINGS_GET_PRIVATE (settings)->connections, hash_values_to_slist, &list);
return list;
}
static void
remove_one_connection (gpointer key, gpointer value, gpointer user_data)
{
nm_exported_connection_signal_removed (NM_EXPORTED_CONNECTION (value));
}
static gboolean
remove_connections (gpointer data)
{
NMDBusSettings *self = NM_DBUS_SETTINGS (data);
NMDBusSettingsPrivate *priv = NM_DBUS_SETTINGS_GET_PRIVATE (self);
g_hash_table_foreach (priv->connections, remove_one_connection, NULL);
return FALSE;
}
static void
name_owner_changed (DBusGProxy *proxy,
const char *name,
const char *old_owner,
const char *new_owner,
gpointer user_data)
{
if (!strcmp (name, NM_DBUS_SERVICE_SYSTEM_SETTINGS)) {
if (new_owner && strlen (new_owner) > 0)
g_idle_add (fetch_connections, user_data);
else
g_idle_add (remove_connections, user_data);
}
}
/* GObject stuff */
static void
nm_dbus_settings_init (NMDBusSettings *settings)
{
NMDBusSettingsPrivate *priv = NM_DBUS_SETTINGS_GET_PRIVATE (settings);
priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
}
static GObject *
constructor (GType type,
guint n_construct_params,
GObjectConstructParam *construct_params)
{
GObject *object;
NMDBusSettingsPrivate *priv;
object = G_OBJECT_CLASS (nm_dbus_settings_parent_class)->constructor (type, n_construct_params, construct_params);
if (!object)
return NULL;
priv = NM_DBUS_SETTINGS_GET_PRIVATE (object);
if (!priv->dbus_connection) {
g_warning ("DBus connection not provided.");
goto err;
}
if (priv->scope == NM_CONNECTION_SCOPE_UNKNOWN) {
g_warning ("Connection scope not provided.");
goto err;
}
priv->dbus_proxy = dbus_g_proxy_new_for_name (priv->dbus_connection,
"org.freedesktop.DBus",
"/org/freedesktop/DBus",
"org.freedesktop.DBus");
dbus_g_proxy_add_signal (priv->dbus_proxy, "NameOwnerChanged",
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
G_TYPE_INVALID);
dbus_g_proxy_connect_signal (priv->dbus_proxy,
"NameOwnerChanged",
G_CALLBACK (name_owner_changed),
object, NULL);
g_idle_add (fetch_connections, object);
return object;
err:
g_object_unref (object);
return NULL;
}
static void
dispose (GObject *object)
{
NMDBusSettingsPrivate *priv = NM_DBUS_SETTINGS_GET_PRIVATE (object);
if (priv->disposed)
return;
priv->disposed = TRUE;
if (priv->connections)
g_hash_table_destroy (priv->connections);
if (priv->dbus_proxy)
g_object_unref (priv->dbus_proxy);
if (priv->settings_proxy)
g_object_unref (priv->settings_proxy);
dbus_g_connection_unref (priv->dbus_connection);
G_OBJECT_CLASS (nm_dbus_settings_parent_class)->dispose (object);
}
static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
NMDBusSettingsPrivate *priv = NM_DBUS_SETTINGS_GET_PRIVATE (object);
switch (prop_id) {
case PROP_DBUS_CONNECTION:
/* Construct only */
priv->dbus_connection = dbus_g_connection_ref ((DBusGConnection *) g_value_get_boxed (value));
break;
case PROP_SCOPE:
priv->scope = (NMConnectionScope) g_value_get_uint (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
NMDBusSettingsPrivate *priv = NM_DBUS_SETTINGS_GET_PRIVATE (object);
switch (prop_id) {
case PROP_DBUS_CONNECTION:
g_value_set_boxed (value, priv->dbus_connection);
break;
case PROP_SCOPE:
g_value_set_uint (value, priv->scope);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
nm_dbus_settings_class_init (NMDBusSettingsClass *dbus_settings_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (dbus_settings_class);
NMSettingsClass *settings_class = NM_SETTINGS_CLASS (dbus_settings_class);
g_type_class_add_private (dbus_settings_class, sizeof (NMDBusSettingsPrivate));
/* Virtual methods */
object_class->constructor = constructor;
object_class->set_property = set_property;
object_class->get_property = get_property;
object_class->dispose = dispose;
settings_class->list_connections = list_connections;
/* Properties */
g_object_class_install_property
(object_class, PROP_DBUS_CONNECTION,
g_param_spec_boxed (NM_DBUS_SETTINGS_DBUS_CONNECTION,
"DBusGConnection",
"DBusGConnection",
DBUS_TYPE_G_CONNECTION,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property
(object_class, PROP_SCOPE,
g_param_spec_uint (NM_DBUS_SETTINGS_SCOPE,
"Scope",
"NMConnection scope",
NM_CONNECTION_SCOPE_UNKNOWN,
NM_CONNECTION_SCOPE_USER,
NM_CONNECTION_SCOPE_USER,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
}

View file

@ -1,60 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* libnm_glib -- Access network status & information from glib applications
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright (C) 2008 Novell, Inc.
*/
#ifndef NM_DBUS_SETTINGS_H
#define NM_DBUS_SETTINGS_H
#include <dbus/dbus-glib.h>
#include <nm-connection.h>
#include <nm-settings.h>
#include <nm-dbus-connection.h>
G_BEGIN_DECLS
#define NM_TYPE_DBUS_SETTINGS (nm_dbus_settings_get_type ())
#define NM_DBUS_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DBUS_SETTINGS, NMDBusSettings))
#define NM_DBUS_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DBUS_SETTINGS, NMDBusSettingsClass))
#define NM_IS_DBUS_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DBUS_SETTINGS))
#define NM_IS_DBUS_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DBUS_SETTINGS))
#define NM_DBUS_SETTINGS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DBUS_SETTINGS, NMDBusSettingsClass))
#define NM_DBUS_SETTINGS_DBUS_CONNECTION "dbus-connection"
#define NM_DBUS_SETTINGS_SCOPE "scope"
typedef struct {
NMSettings parent;
} NMDBusSettings;
typedef struct {
NMSettingsClass parent;
} NMDBusSettingsClass;
GType nm_dbus_settings_get_type (void);
NMDBusSettings *nm_dbus_settings_new (DBusGConnection *dbus_connection);
NMDBusConnection *nm_dbus_settings_get_connection_by_path (NMDBusSettings *self,
const char *path);
G_END_DECLS
#endif /* NM_DBUS_SETTINGS_H */

View file

@ -0,0 +1,306 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager system settings service
*
* 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 2008 Novell, Inc.
* (C) Copyright 2008 - 2009 Red Hat, Inc.
*/
#include <NetworkManager.h>
#include <dbus/dbus-glib-lowlevel.h>
#include "nm-exported-connection.h"
#include "nm-settings-connection-interface.h"
static gboolean impl_exported_connection_get_settings (NMExportedConnection *connection,
GHashTable **settings,
GError **error);
static void impl_exported_connection_update (NMExportedConnection *connection,
GHashTable *new_settings,
DBusGMethodInvocation *context);
static void impl_exported_connection_delete (NMExportedConnection *connection,
DBusGMethodInvocation *context);
static void impl_exported_connection_get_secrets (NMExportedConnection *connection,
const gchar *setting_name,
const gchar **hints,
gboolean request_new,
DBusGMethodInvocation *context);
#include "nm-exported-connection-glue.h"
G_DEFINE_TYPE (NMExportedConnection, nm_exported_connection, NM_TYPE_CONNECTION)
#define NM_EXPORTED_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
NM_TYPE_EXPORTED_CONNECTION, \
NMExportedConnectionPrivate))
typedef struct {
DBusGConnection *bus;
gboolean disposed;
} NMExportedConnectionPrivate;
enum {
PROP_0,
PROP_BUS,
LAST_PROP
};
/**************************************************************/
void
nm_exported_connection_export (NMExportedConnection *self)
{
NMExportedConnectionPrivate *priv;
static guint32 ec_counter = 0;
char *path;
g_return_if_fail (self != NULL);
g_return_if_fail (NM_IS_EXPORTED_CONNECTION (self));
priv = NM_EXPORTED_CONNECTION_GET_PRIVATE (self);
/* Don't allow exporting twice */
g_return_if_fail (nm_connection_get_path (NM_CONNECTION (self)) == NULL);
path = g_strdup_printf ("%s/%u", NM_DBUS_PATH_SETTINGS, ec_counter++);
nm_connection_set_path (NM_CONNECTION (self), path);
dbus_g_connection_register_g_object (priv->bus, path, G_OBJECT (self));
g_free (path);
}
static GHashTable *
real_get_settings (NMExportedConnection *self, GError **error)
{
NMConnection *no_secrets;
GHashTable *settings;
/* Secrets should *never* be returned by the GetSettings method, they
* get returned by the GetSecrets method which can be better
* protected against leakage of secrets to unprivileged callers.
*/
no_secrets = nm_connection_duplicate (NM_CONNECTION (self));
g_assert (no_secrets);
nm_connection_clear_secrets (no_secrets);
settings = nm_connection_to_hash (no_secrets);
g_assert (settings);
g_object_unref (no_secrets);
return settings;
}
/**************************************************************/
static gboolean
impl_exported_connection_get_settings (NMExportedConnection *self,
GHashTable **settings,
GError **error)
{
/* Must always be implemented */
g_assert (NM_EXPORTED_CONNECTION_GET_CLASS (self)->get_settings);
*settings = NM_EXPORTED_CONNECTION_GET_CLASS (self)->get_settings (self, error);
return *settings ? TRUE : FALSE;
}
static void
impl_exported_connection_update (NMExportedConnection *self,
GHashTable *new_settings,
DBusGMethodInvocation *context)
{
NMConnection *tmp;
GError *error = NULL;
/* Check if the settings are valid first */
tmp = nm_connection_new_from_hash (new_settings, &error);
if (!tmp) {
g_assert (error);
dbus_g_method_return_error (context, error);
g_error_free (error);
return;
}
g_object_unref (tmp);
if (NM_EXPORTED_CONNECTION_GET_CLASS (self)->update)
NM_EXPORTED_CONNECTION_GET_CLASS (self)->update (self, new_settings, context);
else {
error = g_error_new (0, 0, "%s: %s:%d update() unimplemented", __func__, __FILE__, __LINE__);
dbus_g_method_return_error (context, error);
g_error_free (error);
}
}
static void
impl_exported_connection_delete (NMExportedConnection *self,
DBusGMethodInvocation *context)
{
GError *error = NULL;
if (NM_EXPORTED_CONNECTION_GET_CLASS (self)->delete)
NM_EXPORTED_CONNECTION_GET_CLASS (self)->delete (self, context);
else {
error = g_error_new (0, 0, "%s: %s:%d delete() unimplemented", __func__, __FILE__, __LINE__);
dbus_g_method_return_error (context, error);
g_error_free (error);
}
}
static void
impl_exported_connection_get_secrets (NMExportedConnection *self,
const gchar *setting_name,
const gchar **hints,
gboolean request_new,
DBusGMethodInvocation *context)
{
GError *error = NULL;
if (NM_EXPORTED_CONNECTION_GET_CLASS (self)->get_secrets)
NM_EXPORTED_CONNECTION_GET_CLASS (self)->get_secrets (self, setting_name, hints, request_new, context);
else {
error = g_error_new (0, 0, "%s: %s:%d get_secrets() unimplemented", __func__, __FILE__, __LINE__);
dbus_g_method_return_error (context, error);
g_error_free (error);
}
}
/**************************************************************/
/**
* nm_exported_connection_new:
* @bus: a valid and connected D-Bus connection
* @scope: the Connection scope (either user or system)
* @path: the D-Bus path of the connection as exported by the settings service
* indicated by @scope
*
* Creates a new object representing the remote connection.
*
* Returns: the new exported connection object on success, or %NULL on failure
**/
NMExportedConnection *
nm_exported_connection_new (DBusGConnection *bus,
NMConnectionScope scope)
{
g_return_val_if_fail (bus != NULL, NULL);
g_return_val_if_fail (scope != NM_CONNECTION_SCOPE_UNKNOWN, NULL);
return (NMExportedConnection *) g_object_new (NM_TYPE_EXPORTED_CONNECTION,
NM_EXPORTED_CONNECTION_BUS, bus,
NM_CONNECTION_SCOPE, scope,
NULL);
}
static GObject *
constructor (GType type,
guint n_construct_params,
GObjectConstructParam *construct_params)
{
GObject *object;
NMExportedConnectionPrivate *priv;
object = G_OBJECT_CLASS (nm_exported_connection_parent_class)->constructor (type, n_construct_params, construct_params);
if (!object)
return NULL;
priv = NM_EXPORTED_CONNECTION_GET_PRIVATE (object);
g_assert (priv->bus);
return object;
}
static void
nm_exported_connection_init (NMExportedConnection *self)
{
}
static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
NMExportedConnectionPrivate *priv = NM_EXPORTED_CONNECTION_GET_PRIVATE (object);
switch (prop_id) {
case PROP_BUS:
/* Construct only */
priv->bus = dbus_g_connection_ref ((DBusGConnection *) g_value_get_boxed (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
NMExportedConnectionPrivate *priv = NM_EXPORTED_CONNECTION_GET_PRIVATE (object);
switch (prop_id) {
case PROP_BUS:
g_value_set_boxed (value, priv->bus);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
dispose (GObject *object)
{
NMExportedConnectionPrivate *priv = NM_EXPORTED_CONNECTION_GET_PRIVATE (object);
if (!priv->disposed) {
priv->disposed = TRUE;
dbus_g_connection_unref (priv->bus);
}
G_OBJECT_CLASS (nm_exported_connection_parent_class)->dispose (object);
}
static void
nm_exported_connection_class_init (NMExportedConnectionClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
g_type_class_add_private (class, sizeof (NMExportedConnectionPrivate));
/* Virtual methods */
object_class->dispose = dispose;
object_class->constructor = constructor;
object_class->get_property = get_property;
object_class->set_property = set_property;
class->get_settings = real_get_settings;
/**
* NMExportedConnection:bus:
*
* The %DBusGConnection which this object is exported on
**/
g_object_class_install_property (object_class, PROP_BUS,
g_param_spec_boxed (NM_EXPORTED_CONNECTION_BUS,
"Bus",
"Bus",
DBUS_TYPE_G_CONNECTION,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (class),
&dbus_glib_nm_exported_connection_object_info);
}

View file

@ -0,0 +1,71 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager system settings service
*
* 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 2009 Red Hat, Inc.
*/
#ifndef NM_EXPORTED_CONNECTION_H
#define NM_EXPORTED_CONNECTION_H
#include <nm-connection.h>
#include <dbus/dbus-glib.h>
G_BEGIN_DECLS
#define NM_TYPE_EXPORTED_CONNECTION (nm_exported_connection_get_type ())
#define NM_EXPORTED_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_EXPORTED_CONNECTION, NMExportedConnection))
#define NM_EXPORTED_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_EXPORTED_CONNECTION, NMExportedConnectionClass))
#define NM_IS_EXPORTED_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_EXPORTED_CONNECTION))
#define NM_IS_EXPORTED_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_EXPORTED_CONNECTION))
#define NM_EXPORTED_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_EXPORTED_CONNECTION, NMExportedConnectionClass))
#define NM_EXPORTED_CONNECTION_BUS "bus"
typedef struct {
NMConnection parent;
} NMExportedConnection;
typedef struct {
NMConnectionClass parent;
GHashTable * (*get_settings) (NMExportedConnection *self,
GError **error);
void (*update) (NMExportedConnection *self,
GHashTable *new_settings,
DBusGMethodInvocation *context);
void (*delete) (NMExportedConnection *self,
DBusGMethodInvocation *context);
void (*get_secrets) (NMExportedConnection *self,
const gchar *setting_name,
const gchar **hints,
gboolean request_new,
DBusGMethodInvocation *context);
} NMExportedConnectionClass;
GType nm_exported_connection_get_type (void);
NMExportedConnection *nm_exported_connection_new (DBusGConnection *bus,
NMConnectionScope scope);
void nm_exported_connection_export (NMExportedConnection *self);
G_END_DECLS
#endif /* NM_EXPORTED_CONNECTION_H */

View file

@ -0,0 +1,419 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* libnm_glib -- Access network status & information from glib applications
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright (C) 2007 - 2008 Novell, Inc.
* Copyright (C) 2007 - 2009 Red Hat, Inc.
*/
#include <string.h>
#include <NetworkManager.h>
#include <nm-utils.h>
#include <nm-setting-connection.h>
#include "nm-remote-connection.h"
#include "nm-dbus-glib-types.h"
#include "nm-exported-connection-bindings.h"
#include "nm-settings-connection-interface.h"
#define NM_REMOTE_CONNECTION_BUS "bus"
static void settings_connection_interface_init (NMSettingsConnectionInterface *klass);
G_DEFINE_TYPE_EXTENDED (NMRemoteConnection, nm_remote_connection, NM_TYPE_CONNECTION, 0,
G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_CONNECTION_INTERFACE, settings_connection_interface_init))
enum {
PROP_0,
PROP_BUS,
LAST_PROP
};
typedef struct {
NMRemoteConnection *self;
DBusGProxy *proxy;
DBusGProxyCall *call;
GFunc callback;
gpointer user_data;
} RemoteCall;
typedef struct {
DBusGConnection *bus;
DBusGProxy *proxy;
DBusGProxy *secrets_proxy;
GSList *calls;
gboolean disposed;
} NMRemoteConnectionPrivate;
#define NM_REMOTE_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_REMOTE_CONNECTION, NMRemoteConnectionPrivate))
/****************************************************************/
static void
remote_call_complete (NMRemoteConnection *self, RemoteCall *call)
{
NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self);
priv->calls = g_slist_remove (priv->calls, call);
/* Don't need to cancel it since this function should only be called from
* the dispose handler (where the proxy will be destroyed immediately after)
* or from the call's completion callback.
*/
memset (call, 0, sizeof (RemoteCall));
g_free (call);
}
static void
update_cb (DBusGProxy *proxy, GError *error, gpointer user_data)
{
RemoteCall *call = user_data;
NMSettingsConnectionInterfaceUpdateFunc func = (NMSettingsConnectionInterfaceUpdateFunc) call->callback;
(*func)(NM_SETTINGS_CONNECTION_INTERFACE (call->self), error, call->user_data);
remote_call_complete (call->self, call);
}
static gboolean
update (NMSettingsConnectionInterface *connection,
NMSettingsConnectionInterfaceUpdateFunc callback,
gpointer user_data)
{
NMRemoteConnection *self = NM_REMOTE_CONNECTION (connection);
NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self);
GHashTable *settings = NULL;
RemoteCall *call;
call = g_malloc0 (sizeof (RemoteCall));
call->self = self;
call->callback = (GFunc) callback;
call->user_data = user_data;
call->proxy = priv->proxy;
settings = nm_connection_to_hash (NM_CONNECTION (self));
call->call = org_freedesktop_NetworkManagerSettings_Connection_update_async (priv->proxy,
settings,
update_cb,
call);
g_assert (call->call);
priv->calls = g_slist_append (priv->calls, call);
g_hash_table_destroy (settings);
return TRUE;
}
static void
delete_cb (DBusGProxy *proxy, GError *error, gpointer user_data)
{
RemoteCall *call = user_data;
NMSettingsConnectionInterfaceDeleteFunc func = (NMSettingsConnectionInterfaceDeleteFunc) call->callback;
(*func)(NM_SETTINGS_CONNECTION_INTERFACE (call->self), error, call->user_data);
remote_call_complete (call->self, call);
}
static gboolean
do_delete (NMSettingsConnectionInterface *connection,
NMSettingsConnectionInterfaceDeleteFunc callback,
gpointer user_data)
{
NMRemoteConnection *self = NM_REMOTE_CONNECTION (connection);
NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self);
RemoteCall *call;
call = g_malloc0 (sizeof (RemoteCall));
call->self = self;
call->callback = (GFunc) callback;
call->user_data = user_data;
call->proxy = priv->proxy;
call->call = org_freedesktop_NetworkManagerSettings_Connection_delete_async (priv->proxy,
delete_cb,
call);
g_assert (call->call);
priv->calls = g_slist_append (priv->calls, call);
return TRUE;
}
static void
get_secrets_cb (DBusGProxy *proxy, GHashTable *secrets, GError *error, gpointer user_data)
{
RemoteCall *call = user_data;
NMSettingsConnectionInterfaceGetSecretsFunc func = (NMSettingsConnectionInterfaceGetSecretsFunc) call->callback;
(*func)(NM_SETTINGS_CONNECTION_INTERFACE (call->self), secrets, error, call->user_data);
remote_call_complete (call->self, call);
}
static gboolean
get_secrets (NMSettingsConnectionInterface *connection,
const char *setting_name,
const char **hints,
gboolean request_new,
NMSettingsConnectionInterfaceGetSecretsFunc callback,
gpointer user_data)
{
NMRemoteConnection *self = NM_REMOTE_CONNECTION (connection);
NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self);
RemoteCall *call;
call = g_malloc0 (sizeof (RemoteCall));
call->self = self;
call->callback = (GFunc) callback;
call->user_data = user_data;
call->proxy = priv->secrets_proxy;
call->call = org_freedesktop_NetworkManagerSettings_Connection_Secrets_get_secrets_async (priv->proxy,
setting_name,
hints,
request_new,
get_secrets_cb,
call);
g_assert (call->call);
priv->calls = g_slist_append (priv->calls, call);
return TRUE;
}
/****************************************************************/
static gboolean
replace_settings (NMRemoteConnection *self, GHashTable *new_settings)
{
GError *error = NULL;
if (!nm_connection_replace_settings (NM_CONNECTION (self), new_settings, &error)) {
g_warning ("%s: error updating %s connection %s settings: (%d) %s",
__func__,
(nm_connection_get_scope (NM_CONNECTION (self)) == NM_CONNECTION_SCOPE_USER) ? "user" : "system",
nm_connection_get_path (NM_CONNECTION (self)),
error ? error->code : -1,
(error && error->message) ? error->message : "(unknown)");
g_clear_error (&error);
return FALSE;
}
/* Emit update irregardless to let listeners figure out what to do with
* the connection; whether to delete / ignore it or not.
*/
nm_settings_connection_interface_emit_updated (NM_SETTINGS_CONNECTION_INTERFACE (self));
return TRUE;
}
static void
get_settings_cb (DBusGProxy *proxy,
GHashTable *new_settings,
GError *error,
gpointer user_data)
{
NMRemoteConnection *self = user_data;
if (error) {
g_warning ("%s: error getting %s connection %s settings: (%d) %s",
__func__,
(nm_connection_get_scope (NM_CONNECTION (self)) == NM_CONNECTION_SCOPE_USER) ? "user" : "system",
nm_connection_get_path (NM_CONNECTION (self)),
error ? error->code : -1,
(error && error->message) ? error->message : "(unknown)");
g_error_free (error);
} else {
replace_settings (self, new_settings);
g_hash_table_destroy (new_settings);
}
}
static void
updated_cb (DBusGProxy *proxy, GHashTable *settings, gpointer user_data)
{
replace_settings (NM_REMOTE_CONNECTION (user_data), settings);
}
static void
removed_cb (DBusGProxy *proxy, gpointer user_data)
{
g_signal_emit_by_name (G_OBJECT (user_data), "removed");
}
/****************************************************************/
static void
settings_connection_interface_init (NMSettingsConnectionInterface *klass)
{
/* interface implementation */
klass->update = update;
klass->delete = do_delete;
klass->get_secrets = get_secrets;
}
/**
* nm_remote_connection_new:
* @bus: a valid and connected D-Bus connection
* @scope: the Connection scope (either user or system)
* @path: the D-Bus path of the connection as exported by the settings service
* indicated by @scope
*
* Creates a new object representing the remote connection.
*
* Returns: the new remote connection object on success, or %NULL on failure
**/
NMRemoteConnection *
nm_remote_connection_new (DBusGConnection *bus,
NMConnectionScope scope,
const char *path)
{
g_return_val_if_fail (bus != NULL, NULL);
g_return_val_if_fail (path != NULL, NULL);
return (NMRemoteConnection *) g_object_new (NM_TYPE_REMOTE_CONNECTION,
NM_REMOTE_CONNECTION_BUS, bus,
NM_CONNECTION_SCOPE, scope,
NM_CONNECTION_PATH, path,
NULL);
}
static GObject *
constructor (GType type,
guint n_construct_params,
GObjectConstructParam *construct_params)
{
GObject *object;
NMRemoteConnectionPrivate *priv;
const char *service = NM_DBUS_SERVICE_USER_SETTINGS;
object = G_OBJECT_CLASS (nm_remote_connection_parent_class)->constructor (type, n_construct_params, construct_params);
if (!object)
return NULL;
priv = NM_REMOTE_CONNECTION_GET_PRIVATE (object);
g_assert (priv->bus);
g_assert (nm_connection_get_path (NM_CONNECTION (object)));
if (nm_connection_get_scope (NM_CONNECTION (object)) == NM_CONNECTION_SCOPE_SYSTEM)
service = NM_DBUS_SERVICE_SYSTEM_SETTINGS;
priv->proxy = dbus_g_proxy_new_for_name (priv->bus,
service,
nm_connection_get_path (NM_CONNECTION (object)),
NM_DBUS_IFACE_SETTINGS_CONNECTION);
g_assert (priv->proxy);
priv->secrets_proxy = dbus_g_proxy_new_for_name (priv->bus,
service,
nm_connection_get_path (NM_CONNECTION (object)),
NM_DBUS_IFACE_SETTINGS_CONNECTION_SECRETS);
g_assert (priv->secrets_proxy);
dbus_g_proxy_add_signal (priv->proxy, "Updated", DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, G_TYPE_INVALID);
dbus_g_proxy_connect_signal (priv->proxy, "Updated", G_CALLBACK (updated_cb), object, NULL);
dbus_g_proxy_add_signal (priv->proxy, "Removed", G_TYPE_INVALID);
dbus_g_proxy_connect_signal (priv->proxy, "Removed", G_CALLBACK (removed_cb), object, NULL);
org_freedesktop_NetworkManagerSettings_Connection_get_settings_async (priv->proxy,
get_settings_cb,
object);
return object;
}
static void
nm_remote_connection_init (NMRemoteConnection *self)
{
}
static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (object);
switch (prop_id) {
case PROP_BUS:
/* Construct only */
priv->bus = dbus_g_connection_ref ((DBusGConnection *) g_value_get_boxed (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
NMRemoteConnection *self = NM_REMOTE_CONNECTION (object);
NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self);
switch (prop_id) {
case PROP_BUS:
g_value_set_boxed (value, priv->bus);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
dispose (GObject *object)
{
NMRemoteConnection *self = NM_REMOTE_CONNECTION (object);
NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (object);
if (!priv->disposed) {
priv->disposed = TRUE;
while (g_slist_length (priv->calls))
remote_call_complete (self, priv->calls->data);
g_object_unref (priv->proxy);
g_object_unref (priv->secrets_proxy);
dbus_g_connection_unref (priv->bus);
}
G_OBJECT_CLASS (nm_remote_connection_parent_class)->dispose (object);
}
static void
nm_remote_connection_class_init (NMRemoteConnectionClass *remote_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (remote_class);
g_type_class_add_private (object_class, sizeof (NMRemoteConnectionPrivate));
/* virtual methods */
object_class->set_property = set_property;
object_class->get_property = get_property;
object_class->dispose = dispose;
object_class->constructor = constructor;
/* Properties */
g_object_class_install_property
(object_class, PROP_BUS,
g_param_spec_boxed (NM_REMOTE_CONNECTION_BUS,
"DBusGConnection",
"DBusGConnection",
DBUS_TYPE_G_CONNECTION,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
}

View file

@ -0,0 +1,57 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* libnm_glib -- Access network status & information from glib applications
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright (C) 2007 - 2008 Novell, Inc.
* Copyright (C) 2007 - 2009 Red Hat, Inc.
*/
#ifndef __NM_REMOTE_CONNECTION_H__
#define __NM_REMOTE_CONNECTION_H__
#include <glib-object.h>
#include <dbus/dbus-glib.h>
#include <nm-connection.h>
G_BEGIN_DECLS
#define NM_TYPE_REMOTE_CONNECTION (nm_remote_connection_get_type ())
#define NM_REMOTE_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_REMOTE_CONNECTION, NMRemoteConnection))
#define NM_REMOTE_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_REMOTE_CONNECTION, NMRemoteConnectionClass))
#define NM_IS_REMOTE_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_REMOTE_CONNECTION))
#define NM_IS_REMOTE_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_REMOTE_CONNECTION))
#define NM_REMOTE_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_REMOTE_CONNECTION, NMRemoteConnectionClass))
typedef struct {
NMConnection parent;
} NMRemoteConnection;
typedef struct {
NMConnectionClass parent_class;
} NMRemoteConnectionClass;
GType nm_remote_connection_get_type (void);
NMRemoteConnection *nm_remote_connection_new (DBusGConnection *dbus_connection,
NMConnectionScope scope,
const char *path);
G_END_DECLS
#endif /* __NM_REMOTE_CONNECTION__ */

View file

@ -0,0 +1,259 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* libnm_glib -- Access network status & information from glib applications
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright (C) 2008 Novell, Inc.
* Copyright (C) 2009 Red Hat, Inc.
*/
#include <string.h>
#include <NetworkManager.h>
#include <nm-connection.h>
#include "nm-marshal.h"
#include "nm-dbus-glib-types.h"
#include "nm-remote-settings-system.h"
#include "nm-settings-system-bindings.h"
#include "nm-settings-system-interface.h"
static void settings_system_interface_init (NMSettingsSystemInterface *klass);
G_DEFINE_TYPE_EXTENDED (NMRemoteSettingsSystem, nm_remote_settings_system, NM_TYPE_REMOTE_SETTINGS, 0,
G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_SYSTEM_INTERFACE, settings_system_interface_init))
#define NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_REMOTE_SETTINGS_SYSTEM, NMRemoteSettingsSystemPrivate))
typedef struct {
DBusGProxy *proxy;
DBusGProxy *props_proxy;
char *hostname;
gboolean can_modify;
gboolean disposed;
} NMRemoteSettingsSystemPrivate;
static void
properties_changed_cb (DBusGProxy *proxy,
GHashTable *properties,
gpointer user_data)
{
NMRemoteSettingsSystem *self = NM_REMOTE_SETTINGS_SYSTEM (user_data);
NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (self);
GHashTableIter iter;
gpointer key, tmp;
g_hash_table_iter_init (&iter, properties);
while (g_hash_table_iter_next (&iter, &key, &tmp)) {
GValue *value = tmp;
if (!strcmp ((const char *) key, "Hostname")) {
g_free (priv->hostname);
priv->hostname = g_value_dup_string (value);
g_object_notify (G_OBJECT (self), NM_SETTINGS_SYSTEM_INTERFACE_HOSTNAME);
}
if (!strcmp ((const char *) key, "CanModify")) {
priv->can_modify = g_value_get_boolean (value);
g_object_notify (G_OBJECT (self), NM_SETTINGS_SYSTEM_INTERFACE_CAN_MODIFY);
}
}
}
static void
get_all_cb (DBusGProxy *proxy,
DBusGProxyCall *call,
gpointer user_data)
{
NMRemoteSettingsSystem *self = NM_REMOTE_SETTINGS_SYSTEM (user_data);
GHashTable *props = NULL;
GError *error = NULL;
if (!dbus_g_proxy_end_call (proxy, call, &error,
DBUS_TYPE_G_MAP_OF_VARIANT, &props,
G_TYPE_INVALID)) {
g_warning ("%s: couldn't retrieve system settings properties: (%d) %s.",
__func__,
error ? error->code : -1,
(error && error->message) ? error->message : "(unknown)");
g_clear_error (&error);
return;
}
properties_changed_cb (NULL, props, self);
g_hash_table_destroy (props);
}
static gboolean
save_hostname (NMSettingsSystemInterface *settings,
const char *hostname,
NMSettingsSystemSaveHostnameFunc callback,
gpointer user_data)
{
return FALSE;
}
/****************************************************************/
static void
settings_system_interface_init (NMSettingsSystemInterface *klass)
{
/* interface implementation */
klass->save_hostname = save_hostname;
}
/**
* nm_remote_settings_system_new:
* @bus: a valid and connected D-Bus connection
*
* Creates a new object representing the remote system settings service.
*
* Returns: the new remote system settings object on success, or %NULL on failure
**/
NMRemoteSettingsSystem *
nm_remote_settings_system_new (DBusGConnection *bus)
{
g_return_val_if_fail (bus != NULL, NULL);
return (NMRemoteSettingsSystem *) g_object_new (NM_TYPE_REMOTE_SETTINGS_SYSTEM,
NM_REMOTE_SETTINGS_BUS, bus,
NM_REMOTE_SETTINGS_SCOPE, NM_CONNECTION_SCOPE_SYSTEM,
NULL);
}
static void
nm_remote_settings_system_init (NMRemoteSettingsSystem *self)
{
}
static GObject *
constructor (GType type,
guint n_construct_params,
GObjectConstructParam *construct_params)
{
GObject *object;
NMRemoteSettingsSystemPrivate *priv;
DBusGConnection *bus = NULL;
object = G_OBJECT_CLASS (nm_remote_settings_system_parent_class)->constructor (type, n_construct_params, construct_params);
if (!object)
return NULL;
priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (object);
g_object_get (G_OBJECT (object), NM_REMOTE_SETTINGS_BUS, &bus, NULL);
g_assert (bus);
/* D-Bus properties proxy */
priv->props_proxy = dbus_g_proxy_new_for_name (bus,
NM_DBUS_SERVICE_SYSTEM_SETTINGS,
NM_DBUS_PATH_SETTINGS,
"org.freedesktop.DBus.Properties");
g_assert (priv->props_proxy);
/* System settings proxy */
priv->proxy = dbus_g_proxy_new_for_name (bus,
NM_DBUS_SERVICE_SYSTEM_SETTINGS,
NM_DBUS_PATH_SETTINGS,
NM_DBUS_IFACE_SETTINGS_SYSTEM);
g_assert (priv->proxy);
dbus_g_object_register_marshaller (_nm_marshal_VOID__STRING_BOXED,
G_TYPE_NONE,
DBUS_TYPE_G_MAP_OF_VARIANT,
G_TYPE_INVALID);
dbus_g_proxy_add_signal (priv->proxy, "PropertiesChanged",
DBUS_TYPE_G_MAP_OF_VARIANT,
G_TYPE_INVALID);
dbus_g_proxy_connect_signal (priv->proxy, "PropertiesChanged",
G_CALLBACK (properties_changed_cb),
object,
NULL);
/* Get properties */
dbus_g_proxy_begin_call (priv->props_proxy, "GetAll",
get_all_cb,
object,
NULL,
G_TYPE_STRING, NM_DBUS_IFACE_SETTINGS_SYSTEM,
G_TYPE_INVALID);
dbus_g_connection_unref (bus);
return object;
}
static void
dispose (GObject *object)
{
NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (object);
if (priv->disposed)
return;
priv->disposed = TRUE;
g_free (priv->hostname);
g_object_unref (priv->props_proxy);
g_object_unref (priv->proxy);
G_OBJECT_CLASS (nm_remote_settings_system_parent_class)->dispose (object);
}
static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (object);
switch (prop_id) {
case NM_SETTINGS_SYSTEM_INTERFACE_PROP_HOSTNAME:
g_value_set_string (value, priv->hostname);
break;
case NM_SETTINGS_SYSTEM_INTERFACE_PROP_CAN_MODIFY:
g_value_set_boolean (value, priv->can_modify);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
nm_remote_settings_system_class_init (NMRemoteSettingsSystemClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
g_type_class_add_private (klass, sizeof (NMRemoteSettingsSystemPrivate));
/* Virtual methods */
object_class->constructor = constructor;
object_class->get_property = get_property;
object_class->dispose = dispose;
/* Properties */
g_object_class_override_property (object_class,
NM_SETTINGS_SYSTEM_INTERFACE_PROP_HOSTNAME,
NM_SETTINGS_SYSTEM_INTERFACE_HOSTNAME);
g_object_class_override_property (object_class,
NM_SETTINGS_SYSTEM_INTERFACE_PROP_CAN_MODIFY,
NM_SETTINGS_SYSTEM_INTERFACE_CAN_MODIFY);
}

View file

@ -0,0 +1,55 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* libnm_glib -- Access network status & information from glib applications
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright (C) 2008 Novell, Inc.
* Copyright (C) 2009 Red Hat, Inc.
*/
#ifndef NM_REMOTE_SETTINGS_SYSTEM_H
#define NM_REMOTE_SETTINGS_SYSTEM_H
#include <glib.h>
#include <dbus/dbus-glib.h>
#include "nm-remote-settings.h"
G_BEGIN_DECLS
#define NM_TYPE_REMOTE_SETTINGS_SYSTEM (nm_remote_settings_system_get_type ())
#define NM_REMOTE_SETTINGS_SYSTEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_REMOTE_SETTINGS_SYSTEM, NMRemoteSettingsSystem))
#define NM_REMOTE_SETTINGS_SYSTEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_REMOTE_SETTINGS_SYSTEM, NMRemoteSettingsSystemClass))
#define NM_IS_REMOTE_SETTINGS_SYSTEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_REMOTE_SETTINGS_SYSTEM))
#define NM_IS_REMOTE_SETTINGS_SYSTEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_REMOTE_SETTINGS_SYSTEM))
#define NM_REMOTE_SETTINGS_SYSTEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_REMOTE_SETTINGS_SYSTEM, NMRemoteSettingsSystemClass))
typedef struct {
NMRemoteSettings parent;
} NMRemoteSettingsSystem;
typedef struct {
NMRemoteSettingsClass parent;
} NMRemoteSettingsSystemClass;
GType nm_remote_settings_system_get_type (void);
NMRemoteSettingsSystem *nm_remote_settings_system_new (DBusGConnection *bus);
G_END_DECLS
#endif /* NM_REMOTE_SETTINGS_SYSTEM_H */

View file

@ -0,0 +1,425 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* libnm_glib -- Access network status & information from glib applications
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright (C) 2008 Novell, Inc.
* Copyright (C) 2009 Red Hat, Inc.
*/
#include <string.h>
#include <NetworkManager.h>
#include <nm-connection.h>
#include "nm-marshal.h"
#include "nm-remote-settings.h"
#include "nm-settings-bindings.h"
#include "nm-settings-interface.h"
static void settings_interface_init (NMSettingsInterface *class);
G_DEFINE_TYPE_EXTENDED (NMRemoteSettings, nm_remote_settings, G_TYPE_OBJECT, 0,
G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_INTERFACE, settings_interface_init))
#define NM_REMOTE_SETTINGS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_REMOTE_SETTINGS, NMRemoteSettingsPrivate))
typedef struct {
DBusGConnection *bus;
NMConnectionScope scope;
DBusGProxy *proxy;
GHashTable *connections;
DBusGProxy *dbus_proxy;
guint fetch_id;
gboolean disposed;
} NMRemoteSettingsPrivate;
enum {
PROP_0,
PROP_BUS,
PROP_SCOPE,
LAST_PROP
};
static NMSettingsConnectionInterface *
get_connection_by_path (NMSettingsInterface *settings, const char *path)
{
return g_hash_table_lookup (NM_REMOTE_SETTINGS_GET_PRIVATE (settings)->connections, path);
}
static void
connection_removed_cb (NMRemoteConnection *remote, gpointer user_data)
{
g_hash_table_remove (NM_REMOTE_SETTINGS_GET_PRIVATE (user_data)->connections,
nm_connection_get_path (NM_CONNECTION (remote)));
}
static void
new_connection_cb (DBusGProxy *proxy, const char *path, gpointer user_data)
{
NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
NMRemoteConnection *connection;
connection = nm_remote_connection_new (priv->bus, priv->scope, path);
if (connection) {
g_signal_connect (connection, "removed",
G_CALLBACK (connection_removed_cb),
self);
g_hash_table_insert (priv->connections, g_strdup (path), connection);
g_signal_emit_by_name (self, "new-connection", connection);
}
}
static void
fetch_connections_done (DBusGProxy *proxy,
GPtrArray *connections,
GError *error,
gpointer user_data)
{
NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
int i;
if (error) {
g_warning ("%s: error fetching %s connections: (%d) %s.",
__func__,
priv->scope == NM_CONNECTION_SCOPE_USER ? "user" : "system",
error->code,
error->message ? error->message : "(unknown)");
g_clear_error (&error);
return;
}
for (i = 0; connections && (i < connections->len); i++) {
char *path = g_ptr_array_index (connections, i);
new_connection_cb (proxy, path, user_data);
g_free (path);
}
g_ptr_array_free (connections, TRUE);
}
static gboolean
fetch_connections (gpointer user_data)
{
NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
priv->fetch_id = 0;
org_freedesktop_NetworkManagerSettings_list_connections_async (priv->proxy,
fetch_connections_done,
self);
return FALSE;
}
static GSList *
list_connections (NMSettingsInterface *settings)
{
NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
GSList *list = NULL;
GHashTableIter iter;
gpointer value;
g_hash_table_iter_init (&iter, priv->connections);
while (g_hash_table_iter_next (&iter, NULL, &value))
list = g_slist_prepend (list, NM_REMOTE_CONNECTION (value));
return list;
}
typedef struct {
NMSettingsInterface *self;
NMSettingsAddConnectionFunc callback;
gpointer callback_data;
} AddConnectionInfo;
static void
add_connection_done (DBusGProxy *proxy,
GError *error,
gpointer user_data)
{
AddConnectionInfo *info = user_data;
info->callback (info->self, error, info->callback_data);
g_free (info);
}
static gboolean
add_connection (NMSettingsInterface *settings,
NMSettingsConnectionInterface *connection,
NMSettingsAddConnectionFunc callback,
gpointer user_data)
{
NMRemoteSettings *self = NM_REMOTE_SETTINGS (settings);
NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
AddConnectionInfo *info;
GHashTable *new_settings;
info = g_malloc0 (sizeof (AddConnectionInfo));
info->self = settings;
info->callback = callback;
info->callback_data = user_data;
new_settings = nm_connection_to_hash (NM_CONNECTION (connection));
org_freedesktop_NetworkManagerSettings_add_connection_async (priv->proxy,
new_settings,
add_connection_done,
info);
g_hash_table_destroy (new_settings);
return TRUE;
}
static gboolean
remove_connections (gpointer user_data)
{
NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
GHashTableIter iter;
gpointer value;
g_hash_table_iter_init (&iter, priv->connections);
while (g_hash_table_iter_next (&iter, NULL, &value))
g_signal_emit_by_name (NM_REMOTE_CONNECTION (value), "removed");
g_hash_table_remove_all (priv->connections);
return FALSE;
}
static void
name_owner_changed (DBusGProxy *proxy,
const char *name,
const char *old_owner,
const char *new_owner,
gpointer user_data)
{
NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
const char *sname = NM_DBUS_SERVICE_USER_SETTINGS;
if (priv->scope == NM_CONNECTION_SCOPE_SYSTEM)
sname = NM_DBUS_SERVICE_SYSTEM_SETTINGS;
if (!strcmp (name, sname)) {
if (priv->fetch_id)
g_source_remove (priv->fetch_id);
if (new_owner && strlen (new_owner) > 0)
priv->fetch_id = g_idle_add (fetch_connections, self);
else
priv->fetch_id = g_idle_add (remove_connections, self);
}
}
/****************************************************************/
static void
settings_interface_init (NMSettingsInterface *iface)
{
/* interface implementation */
iface->list_connections = list_connections;
iface->get_connection_by_path = get_connection_by_path;
iface->add_connection = add_connection;
}
/**
* nm_remote_settings_new:
* @bus: a valid and connected D-Bus connection
* @scope: the settings service scope (either user or system)
*
* Creates a new object representing the remote settings service.
*
* Returns: the new remote settings object on success, or %NULL on failure
**/
NMRemoteSettings *
nm_remote_settings_new (DBusGConnection *bus, NMConnectionScope scope)
{
g_return_val_if_fail (bus != NULL, NULL);
g_return_val_if_fail (scope != NM_CONNECTION_SCOPE_UNKNOWN, NULL);
return (NMRemoteSettings *) g_object_new (NM_TYPE_REMOTE_SETTINGS,
NM_REMOTE_SETTINGS_BUS, bus,
NM_REMOTE_SETTINGS_SCOPE, scope,
NULL);
}
static void
nm_remote_settings_init (NMRemoteSettings *self)
{
NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
}
static GObject *
constructor (GType type,
guint n_construct_params,
GObjectConstructParam *construct_params)
{
GObject *object;
NMRemoteSettingsPrivate *priv;
const char *service = NM_DBUS_SERVICE_USER_SETTINGS;
object = G_OBJECT_CLASS (nm_remote_settings_parent_class)->constructor (type, n_construct_params, construct_params);
if (!object)
return NULL;
priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object);
/* D-Bus proxy for clearing connections on NameOwnerChanged */
priv->dbus_proxy = dbus_g_proxy_new_for_name (priv->bus,
"org.freedesktop.DBus",
"/org/freedesktop/DBus",
"org.freedesktop.DBus");
g_assert (priv->dbus_proxy);
dbus_g_object_register_marshaller (_nm_marshal_VOID__STRING_STRING_STRING,
G_TYPE_NONE,
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
G_TYPE_INVALID);
dbus_g_proxy_add_signal (priv->dbus_proxy, "NameOwnerChanged",
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
G_TYPE_INVALID);
dbus_g_proxy_connect_signal (priv->dbus_proxy,
"NameOwnerChanged",
G_CALLBACK (name_owner_changed),
object, NULL);
/* Settings service proxy */
if (priv->scope == NM_CONNECTION_SCOPE_SYSTEM)
service = NM_DBUS_SERVICE_SYSTEM_SETTINGS;
priv->proxy = dbus_g_proxy_new_for_name (priv->bus,
service,
NM_DBUS_PATH_SETTINGS,
NM_DBUS_IFACE_SETTINGS);
g_assert (priv->proxy);
dbus_g_proxy_add_signal (priv->proxy, "NewConnection",
DBUS_TYPE_G_OBJECT_PATH,
G_TYPE_INVALID);
dbus_g_proxy_connect_signal (priv->proxy, "NewConnection",
G_CALLBACK (new_connection_cb),
object,
NULL);
priv->fetch_id = g_idle_add (fetch_connections, object);
return object;
}
static void
dispose (GObject *object)
{
NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object);
if (priv->disposed)
return;
priv->disposed = TRUE;
if (priv->fetch_id)
g_source_remove (priv->fetch_id);
if (priv->connections)
g_hash_table_destroy (priv->connections);
g_object_unref (priv->dbus_proxy);
g_object_unref (priv->proxy);
dbus_g_connection_unref (priv->bus);
G_OBJECT_CLASS (nm_remote_settings_parent_class)->dispose (object);
}
static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object);
switch (prop_id) {
case PROP_BUS:
/* Construct only */
priv->bus = dbus_g_connection_ref ((DBusGConnection *) g_value_get_boxed (value));
break;
case PROP_SCOPE:
priv->scope = (NMConnectionScope) g_value_get_uint (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object);
switch (prop_id) {
case PROP_BUS:
g_value_set_boxed (value, priv->bus);
break;
case PROP_SCOPE:
g_value_set_uint (value, priv->scope);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
nm_remote_settings_class_init (NMRemoteSettingsClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
g_type_class_add_private (class, sizeof (NMRemoteSettingsPrivate));
/* Virtual methods */
object_class->constructor = constructor;
object_class->set_property = set_property;
object_class->get_property = get_property;
object_class->dispose = dispose;
/* Properties */
g_object_class_install_property
(object_class, PROP_BUS,
g_param_spec_boxed (NM_REMOTE_SETTINGS_BUS,
"DBusGConnection",
"DBusGConnection",
DBUS_TYPE_G_CONNECTION,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property
(object_class, PROP_SCOPE,
g_param_spec_uint (NM_REMOTE_SETTINGS_SCOPE,
"Scope",
"NMConnection scope",
NM_CONNECTION_SCOPE_UNKNOWN,
NM_CONNECTION_SCOPE_USER,
NM_CONNECTION_SCOPE_USER,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
}

View file

@ -0,0 +1,58 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* libnm_glib -- Access network status & information from glib applications
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright (C) 2008 Novell, Inc.
* Copyright (C) 2009 Red Hat, Inc.
*/
#ifndef NM_REMOTE_SETTINGS_H
#define NM_REMOTE_SETTINGS_H
#include <glib.h>
#include <dbus/dbus-glib.h>
#include <nm-connection.h>
#include <nm-remote-connection.h>
G_BEGIN_DECLS
#define NM_TYPE_REMOTE_SETTINGS (nm_remote_settings_get_type ())
#define NM_REMOTE_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_REMOTE_SETTINGS, NMRemoteSettings))
#define NM_REMOTE_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_REMOTE_SETTINGS, NMRemoteSettingsClass))
#define NM_IS_REMOTE_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_REMOTE_SETTINGS))
#define NM_IS_REMOTE_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_REMOTE_SETTINGS))
#define NM_REMOTE_SETTINGS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_REMOTE_SETTINGS, NMRemoteSettingsClass))
#define NM_REMOTE_SETTINGS_BUS "bus"
#define NM_REMOTE_SETTINGS_SCOPE "scope"
typedef struct {
GObject parent;
} NMRemoteSettings;
typedef struct {
GObjectClass parent;
} NMRemoteSettingsClass;
GType nm_remote_settings_get_type (void);
NMRemoteSettings *nm_remote_settings_new (DBusGConnection *bus, NMConnectionScope scope);
G_END_DECLS
#endif /* NM_REMOTE_SETTINGS_H */

View file

@ -0,0 +1,210 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager -- Network link manager
*
* 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.
*
* Copyright (C) 2007 - 2008 Novell, Inc.
* Copyright (C) 2007 - 2009 Red Hat, Inc.
*/
#include "nm-settings-connection-interface.h"
#include "nm-dbus-glib-types.h"
/**
* nm_settings_connection_interface_update:
* @self: an object implementing #NMSettingsConnectionInterface
* @callback: a function to be called when the update completes
* @user_data: caller-specific data to be passed to @callback
*
* Update the connection with current settings and properties.
*
* Returns: TRUE on success, FALSE on failure
**/
gboolean
nm_settings_connection_interface_update (NMSettingsConnectionInterface *connection,
NMSettingsConnectionInterfaceUpdateFunc callback,
gpointer user_data)
{
g_return_val_if_fail (connection != NULL, FALSE);
g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION_INTERFACE (connection), FALSE);
g_return_val_if_fail (callback != NULL, FALSE);
if (NM_SETTINGS_CONNECTION_INTERFACE_GET_INTERFACE (connection)->update) {
return NM_SETTINGS_CONNECTION_INTERFACE_GET_INTERFACE (connection)->update (connection,
callback,
user_data);
}
return FALSE;
}
/**
* nm_settings_connection_interface_delete:
* @self: a objecting implementing #NMSettingsConnectionInterface
* @callback: a function to be called when the delete completes
* @user_data: caller-specific data to be passed to @callback
*
* Delete the connection.
*
* Returns: TRUE on success, FALSE on failure
**/
gboolean
nm_settings_connection_interface_delete (NMSettingsConnectionInterface *connection,
NMSettingsConnectionInterfaceDeleteFunc callback,
gpointer user_data)
{
g_return_val_if_fail (connection != NULL, FALSE);
g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION_INTERFACE (connection), FALSE);
g_return_val_if_fail (callback != NULL, FALSE);
if (NM_SETTINGS_CONNECTION_INTERFACE_GET_INTERFACE (connection)->delete) {
return NM_SETTINGS_CONNECTION_INTERFACE_GET_INTERFACE (connection)->delete (connection,
callback,
user_data);
}
return FALSE;
}
/**
* nm_settings_connection_interface_get_secrets:
* @self: a object implementing #NMSettingsConnectionInterface
* @setting_name: the #NMSetting object name to get secrets for
* @hints: #NMSetting key names to get secrets for (optional)
* @request_new: hint that new secrets (instead of cached or stored secrets)
* should be returned
* @callback: a function to be called when the update completes
* @user_data: caller-specific data to be passed to @callback
*
* Request the connection's secrets.
*
* Returns: TRUE on success, FALSE on failure
**/
gboolean
nm_settings_connection_interface_get_secrets (NMSettingsConnectionInterface *connection,
const char *setting_name,
const char **hints,
gboolean request_new,
NMSettingsConnectionInterfaceGetSecretsFunc callback,
gpointer user_data)
{
g_return_val_if_fail (connection != NULL, FALSE);
g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION_INTERFACE (connection), FALSE);
g_return_val_if_fail (callback != NULL, FALSE);
if (NM_SETTINGS_CONNECTION_INTERFACE_GET_INTERFACE (connection)->get_secrets) {
return NM_SETTINGS_CONNECTION_INTERFACE_GET_INTERFACE (connection)->get_secrets (connection,
setting_name,
hints,
request_new,
callback,
user_data);
}
return FALSE;
}
void
nm_settings_connection_interface_emit_updated (NMSettingsConnectionInterface *connection)
{
if (NM_SETTINGS_CONNECTION_INTERFACE_GET_INTERFACE (connection)->emit_updated)
NM_SETTINGS_CONNECTION_INTERFACE_GET_INTERFACE (connection)->emit_updated (connection);
else {
NMConnection *tmp;
GHashTable *settings;
tmp = nm_connection_duplicate (NM_CONNECTION (connection));
nm_connection_clear_secrets (tmp);
settings = nm_connection_to_hash (tmp);
g_object_unref (tmp);
g_signal_emit_by_name (connection, "updated", settings);
g_hash_table_destroy (settings);
}
}
static void
nm_settings_connection_interface_init (gpointer g_iface)
{
GType iface_type = G_TYPE_FROM_INTERFACE (g_iface);
static gboolean initialized = FALSE;
if (initialized)
return;
/* Properties */
g_object_interface_install_property
(g_iface,
g_param_spec_string (NM_SETTINGS_CONNECTION_INTERFACE_PATH,
"Path",
"D-Bus path",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_object_interface_install_property
(g_iface,
g_param_spec_uint (NM_SETTINGS_CONNECTION_INTERFACE_SCOPE,
"Scope",
"Connection scope (user, system)",
NM_CONNECTION_SCOPE_UNKNOWN,
NM_CONNECTION_SCOPE_USER,
NM_CONNECTION_SCOPE_USER,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
/* Signals */
g_signal_new ("updated",
iface_type,
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMSettingsConnectionInterface, updated),
NULL, NULL,
g_cclosure_marshal_VOID__BOXED,
G_TYPE_NONE, 1, DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT);
g_signal_new ("removed",
iface_type,
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMSettingsConnectionInterface, removed),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
initialized = TRUE;
}
GType
nm_settings_connection_interface_get_type (void)
{
static GType itype = 0;
if (!itype) {
const GTypeInfo iinfo = {
sizeof (NMSettingsConnectionInterface), /* class_size */
nm_settings_connection_interface_init, /* base_init */
NULL, /* base_finalize */
NULL,
NULL, /* class_finalize */
NULL, /* class_data */
0,
0, /* n_preallocs */
NULL
};
itype = g_type_register_static (G_TYPE_INTERFACE,
"NMSettingsConnectionInterface",
&iinfo, 0);
g_type_interface_add_prerequisite (itype, NM_TYPE_CONNECTION);
}
return itype;
}

View file

@ -0,0 +1,116 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* libnm_glib -- Access network status & information from glib applications
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright (C) 2007 - 2008 Novell, Inc.
* Copyright (C) 2007 - 2009 Red Hat, Inc.
*/
#ifndef __NM_SETTINGS_CONNECTION_INTERFACE_H__
#define __NM_SETTINGS_CONNECTION_INTERFACE_H__
#include <glib-object.h>
#include <dbus/dbus-glib.h>
#include <nm-connection.h>
G_BEGIN_DECLS
#define NM_TYPE_SETTINGS_CONNECTION_INTERFACE (nm_settings_connection_interface_get_type ())
#define NM_SETTINGS_CONNECTION_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTINGS_CONNECTION_INTERFACE, NMSettingsConnectionInterface))
#define NM_IS_SETTINGS_CONNECTION_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTINGS_CONNECTION_INTERFACE))
#define NM_SETTINGS_CONNECTION_INTERFACE_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_SETTINGS_CONNECTION_INTERFACE, NMSettingsConnectionInterface))
#define NM_SETTINGS_CONNECTION_INTERFACE_PATH "path"
#define NM_SETTINGS_CONNECTION_INTERFACE_SCOPE "scope"
typedef enum {
NM_SETTINGS_CONNECTION_INTERFACE_PROP_FIRST = 0x1000,
NM_SETTINGS_CONNECTION_INTERFACE_PROP_PATH = NM_SETTINGS_CONNECTION_INTERFACE_PROP_FIRST,
NM_SETTINGS_CONNECTION_INTERFACE_PROP_SCOPE
} NMSettingsConnectionInterfaceProp;
typedef struct _NMSettingsConnectionInterface NMSettingsConnectionInterface;
typedef void (*NMSettingsConnectionInterfaceUpdateFunc) (NMSettingsConnectionInterface *connection,
GError *error,
gpointer user_data);
typedef void (*NMSettingsConnectionInterfaceDeleteFunc) (NMSettingsConnectionInterface *connection,
GError *error,
gpointer user_data);
typedef void (*NMSettingsConnectionInterfaceGetSecretsFunc) (NMSettingsConnectionInterface *connection,
GHashTable *secrets,
GError *error,
gpointer user_data);
struct _NMSettingsConnectionInterface {
GTypeInterface g_iface;
/* Methods */
gboolean (*update) (NMSettingsConnectionInterface *connection,
NMSettingsConnectionInterfaceUpdateFunc callback,
gpointer user_data);
gboolean (*delete) (NMSettingsConnectionInterface *connection,
NMSettingsConnectionInterfaceDeleteFunc callback,
gpointer user_data);
gboolean (*get_secrets) (NMSettingsConnectionInterface *connection,
const char *setting_name,
const char **hints,
gboolean request_new,
NMSettingsConnectionInterfaceGetSecretsFunc callback,
gpointer user_data);
void (*emit_updated) (NMSettingsConnectionInterface *connection);
/* Signals */
/* 'new_settings' hash should *not* contain secrets */
void (*updated) (NMSettingsConnectionInterface *connection,
GHashTable *new_settings);
void (*removed) (NMSettingsConnectionInterface *connection);
};
GType nm_settings_connection_interface_get_type (void);
gboolean nm_settings_connection_interface_update (NMSettingsConnectionInterface *connection,
NMSettingsConnectionInterfaceUpdateFunc callback,
gpointer user_data);
gboolean nm_settings_connection_interface_delete (NMSettingsConnectionInterface *connection,
NMSettingsConnectionInterfaceDeleteFunc callback,
gpointer user_data);
gboolean nm_settings_connection_interface_get_secrets (NMSettingsConnectionInterface *connection,
const char *setting_name,
const char **hints,
gboolean request_new,
NMSettingsConnectionInterfaceGetSecretsFunc callback,
gpointer user_data);
void nm_settings_connection_interface_emit_updated (NMSettingsConnectionInterface *connection);
G_END_DECLS
#endif /* __NM_SETTINGS_CONNECTION_INTERFACE_H__ */

View file

@ -0,0 +1,195 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager -- Network link manager
*
* 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.
*
* Copyright (C) 2007 - 2008 Novell, Inc.
* Copyright (C) 2007 - 2008 Red Hat, Inc.
*/
#include "nm-settings-interface.h"
/**
* nm_settings_interface_error_quark:
*
* Setting error quark.
*
* Returns: the setting error quark
**/
GQuark
nm_settings_interface_error_quark (void)
{
static GQuark quark;
if (G_UNLIKELY (!quark))
quark = g_quark_from_static_string ("nm-settings-interface-error-quark");
return quark;
}
/* This should really be standard. */
#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
GType
nm_settings_interface_error_get_type (void)
{
static GType etype = 0;
if (etype == 0) {
static const GEnumValue values[] = {
/* The connection was invalid. */
ENUM_ENTRY (NM_SETTINGS_INTERFACE_ERROR_INVALID_CONNECTION, "InvalidConnection"),
/* The connection is read-only; modifications are not allowed. */
ENUM_ENTRY (NM_SETTINGS_INTERFACE_ERROR_READ_ONLY_CONNECTION, "ReadOnlyConnection"),
/* A bug in the settings service caused the error. */
ENUM_ENTRY (NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR, "InternalError"),
/* Retrieval or request of secrets failed. */
ENUM_ENTRY (NM_SETTINGS_INTERFACE_ERROR_SECRETS_UNAVAILABLE, "SecretsUnavailable"),
/* The request for secrets was canceled. */
ENUM_ENTRY (NM_SETTINGS_INTERFACE_ERROR_SECRETS_REQUEST_CANCELED, "SecretsRequestCanceled"),
/* The request could not be completed because permission was denied. */
ENUM_ENTRY (NM_SETTINGS_INTERFACE_ERROR_PERMISSION_DENIED, "PermissionDenied"),
{ 0, 0, 0 },
};
etype = g_enum_register_static ("NMSettingsInterfaceError", values);
}
return etype;
}
/**
* nm_settings_list_connections:
* @settings: a object implementing %NMSettingsInterface
*
* Returns: all connections known to the object.
**/
GSList *
nm_settings_interface_list_connections (NMSettingsInterface *settings)
{
g_return_val_if_fail (settings != NULL, NULL);
g_return_val_if_fail (NM_IS_SETTINGS_INTERFACE (settings), NULL);
if (NM_SETTINGS_INTERFACE_GET_INTERFACE (settings)->list_connections)
return NM_SETTINGS_INTERFACE_GET_INTERFACE (settings)->list_connections (settings);
return NULL;
}
/**
* nm_settings_get_connection_by_path:
* @settings: a object implementing %NMSettingsInterface
* @path: the D-Bus object path of the remote connection
*
* Returns the object implementing %NMSettingsConnectionInterface at @path.
*
* Returns: the remote connection object on success, or NULL if the object was
* not known
**/
NMSettingsConnectionInterface *
nm_settings_interface_get_connection_by_path (NMSettingsInterface *settings,
const char *path)
{
g_return_val_if_fail (settings != NULL, NULL);
g_return_val_if_fail (NM_IS_SETTINGS_INTERFACE (settings), NULL);
g_return_val_if_fail (path != NULL, NULL);
if (NM_SETTINGS_INTERFACE_GET_INTERFACE (settings)->get_connection_by_path)
return NM_SETTINGS_INTERFACE_GET_INTERFACE (settings)->get_connection_by_path (settings, path);
return NULL;
}
/**
* nm_settings_interface_add_connection:
* @settings: a object implementing %NMSettingsInterface
* @connection: the settings to add; note that this objects settings will be
* added, not the object itself
* @callback: callback to be called when the add operation completes
* @user_data: caller-specific data passed to @callback
*
* Requests that the settings service add the given settings to a new connection.
*
* Returns: TRUE if the request was successful, FALSE if it failed
**/
gboolean
nm_settings_interface_add_connection (NMSettingsInterface *settings,
NMSettingsConnectionInterface *connection,
NMSettingsAddConnectionFunc callback,
gpointer user_data)
{
g_return_val_if_fail (settings != NULL, FALSE);
g_return_val_if_fail (NM_IS_SETTINGS_INTERFACE (settings), FALSE);
g_return_val_if_fail (connection != NULL, FALSE);
g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION_INTERFACE (connection), FALSE);
g_return_val_if_fail (callback != NULL, FALSE);
if (NM_SETTINGS_INTERFACE_GET_INTERFACE (settings)->add_connection) {
return NM_SETTINGS_INTERFACE_GET_INTERFACE (settings)->add_connection (settings,
connection,
callback,
user_data);
}
return FALSE;
}
/*****************************************************************/
static void
nm_settings_interface_init (gpointer g_iface)
{
GType iface_type = G_TYPE_FROM_INTERFACE (g_iface);
static gboolean initialized = FALSE;
if (initialized)
return;
/* Signals */
g_signal_new (NM_SETTINGS_INTERFACE_NEW_CONNECTION,
iface_type,
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMSettingsInterface, new_connection),
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, G_TYPE_OBJECT);
initialized = TRUE;
}
GType
nm_settings_interface_get_type (void)
{
static GType settings_interface_type = 0;
if (!settings_interface_type) {
const GTypeInfo settings_interface_info = {
sizeof (NMSettingsInterface), /* class_size */
nm_settings_interface_init, /* base_init */
NULL, /* base_finalize */
NULL,
NULL, /* class_finalize */
NULL, /* class_data */
0,
0, /* n_preallocs */
NULL
};
settings_interface_type = g_type_register_static (G_TYPE_INTERFACE,
"NMSettingsInterface",
&settings_interface_info, 0);
g_type_interface_add_prerequisite (settings_interface_type, G_TYPE_OBJECT);
}
return settings_interface_type;
}

View file

@ -0,0 +1,93 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager -- Network link manager
*
* 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.
*
* Copyright (C) 2007 - 2008 Novell, Inc.
* Copyright (C) 2007 - 2009 Red Hat, Inc.
*/
#ifndef NM_SETTINGS_INTERFACE_H
#define NM_SETTINGS_INTERFACE_H
#include <glib-object.h>
#include "NetworkManager.h"
#include "nm-settings-connection-interface.h"
typedef enum {
NM_SETTINGS_INTERFACE_ERROR_INVALID_CONNECTION = 0,
NM_SETTINGS_INTERFACE_ERROR_READ_ONLY_CONNECTION,
NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR,
NM_SETTINGS_INTERFACE_ERROR_SECRETS_UNAVAILABLE,
NM_SETTINGS_INTERFACE_ERROR_SECRETS_REQUEST_CANCELED,
NM_SETTINGS_INTERFACE_ERROR_PERMISSION_DENIED
} NMSettingsInterfaceError;
#define NM_SETTINGS_INTERFACE_ERROR (nm_settings_interface_error_quark ())
GQuark nm_settings_interface_error_quark (void);
#define NM_TYPE_SETTINGS_INTERFACE_ERROR (nm_settings_interface_error_get_type ())
GType nm_settings_interface_error_get_type (void);
#define NM_TYPE_SETTINGS_INTERFACE (nm_settings_interface_get_type ())
#define NM_SETTINGS_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTINGS_INTERFACE, NMSettingsInterface))
#define NM_IS_SETTINGS_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTINGS_INTERFACE))
#define NM_SETTINGS_INTERFACE_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_SETTINGS_INTERFACE, NMSettingsInterface))
#define NM_SETTINGS_INTERFACE_NEW_CONNECTION "new-connection"
typedef struct _NMSettingsInterface NMSettingsInterface;
typedef void (*NMSettingsAddConnectionFunc) (NMSettingsInterface *settings,
GError *error,
gpointer user_data);
struct _NMSettingsInterface {
GTypeInterface g_iface;
/* Methods */
/* Returns a list of objects implementing NMSettingsConnectionInterface */
GSList * (*list_connections) (NMSettingsInterface *settings);
NMSettingsConnectionInterface * (*get_connection_by_path) (NMSettingsInterface *settings,
const char *path);
gboolean (*add_connection) (NMSettingsInterface *settings,
NMSettingsConnectionInterface *connection,
NMSettingsAddConnectionFunc callback,
gpointer user_data);
/* Signals */
void (*new_connection) (NMSettingsInterface *settings,
NMSettingsConnectionInterface *connection);
};
GType nm_settings_interface_get_type (void);
/* Returns a list of objects implementing NMSettingsConnectionInterface */
GSList *nm_settings_interface_list_connections (NMSettingsInterface *settings);
NMSettingsConnectionInterface *nm_settings_interface_get_connection_by_path (NMSettingsInterface *settings,
const char *path);
gboolean nm_settings_interface_add_connection (NMSettingsInterface *settings,
NMSettingsConnectionInterface *connection,
NMSettingsAddConnectionFunc callback,
gpointer user_data);
#endif /* NM_SETTINGS_INTERFACE_H */

View file

@ -0,0 +1,287 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager system settings service
*
* 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 2008 Novell, Inc.
* (C) Copyright 2008 - 2009 Red Hat, Inc.
*/
#include <NetworkManager.h>
#include <dbus/dbus-glib-lowlevel.h>
#include "nm-settings-service.h"
#include "nm-settings-interface.h"
#include "nm-exported-connection.h"
static gboolean impl_settings_list_connections (NMSettingsService *self,
GPtrArray **connections,
GError **error);
static void impl_settings_add_connection (NMSettingsService *self,
GHashTable *settings,
DBusGMethodInvocation *context);
#include "nm-settings-glue.h"
static void settings_interface_init (NMSettingsInterface *class);
G_DEFINE_TYPE_EXTENDED (NMSettingsService, nm_settings_service, G_TYPE_OBJECT, G_TYPE_FLAG_ABSTRACT,
G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_INTERFACE, settings_interface_init))
#define NM_SETTINGS_SERVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
NM_TYPE_SETTINGS_SERVICE, \
NMSettingsServicePrivate))
typedef struct {
DBusGConnection *bus;
NMConnectionScope scope;
gboolean exported;
gboolean disposed;
} NMSettingsServicePrivate;
enum {
PROP_0,
PROP_BUS,
PROP_SCOPE,
LAST_PROP
};
/**************************************************************/
void
nm_settings_service_export (NMSettingsService *self)
{
NMSettingsServicePrivate *priv;
g_return_if_fail (self != NULL);
g_return_if_fail (NM_IS_SETTINGS_SERVICE (self));
priv = NM_SETTINGS_SERVICE_GET_PRIVATE (self);
g_return_if_fail (priv->bus != NULL);
/* Don't allow exporting twice */
g_return_if_fail (priv->exported == FALSE);
dbus_g_connection_register_g_object (priv->bus,
NM_DBUS_PATH_SETTINGS,
G_OBJECT (self));
priv->exported = TRUE;
}
/**************************************************************/
static GSList *
list_connections (NMSettingsInterface *settings)
{
/* Must always be implemented */
g_assert (NM_SETTINGS_SERVICE_GET_CLASS (settings)->list_connections);
return NM_SETTINGS_SERVICE_GET_CLASS (settings)->list_connections (NM_SETTINGS_SERVICE (settings));
}
static gboolean
impl_settings_list_connections (NMSettingsService *self,
GPtrArray **connections,
GError **error)
{
GSList *list = NULL, *iter;
list = list_connections (NM_SETTINGS_INTERFACE (self));
*connections = g_ptr_array_sized_new (g_slist_length (list) + 1);
for (iter = list; iter; iter = g_slist_next (iter)) {
g_ptr_array_add (*connections,
g_strdup (nm_connection_get_path (NM_CONNECTION (iter->data))));
}
g_slist_free (list);
return TRUE;
}
static NMSettingsConnectionInterface *
get_connection_by_path (NMSettingsInterface *settings, const char *path)
{
NMExportedConnection *connection;
/* Must always be implemented */
g_assert (NM_SETTINGS_SERVICE_GET_CLASS (settings)->get_connection_by_path);
connection = NM_SETTINGS_SERVICE_GET_CLASS (settings)->get_connection_by_path (NM_SETTINGS_SERVICE (settings), path);
return (NMSettingsConnectionInterface *) connection;
}
NMExportedConnection *
nm_settings_service_get_connection_by_path (NMSettingsService *self,
const char *path)
{
g_return_val_if_fail (self != NULL, NULL);
g_return_val_if_fail (NM_IS_SETTINGS_SERVICE (self), NULL);
return (NMExportedConnection *) get_connection_by_path (NM_SETTINGS_INTERFACE (self), path);
}
static void
impl_settings_add_connection (NMSettingsService *self,
GHashTable *settings,
DBusGMethodInvocation *context)
{
NMConnection *tmp;
GError *error = NULL;
/* Check if the settings are valid first */
tmp = nm_connection_new_from_hash (settings, &error);
if (!tmp) {
g_assert (error);
dbus_g_method_return_error (context, error);
g_error_free (error);
return;
}
g_object_unref (tmp);
if (NM_SETTINGS_SERVICE_GET_CLASS (self)->add_connection)
NM_SETTINGS_SERVICE_GET_CLASS (self)->add_connection (self, settings, context);
else {
error = g_error_new (NM_SETTINGS_INTERFACE_ERROR,
NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR,
"%s: %s:%d add_connection() not implemented",
__func__, __FILE__, __LINE__);
dbus_g_method_return_error (context, error);
g_error_free (error);
}
}
/**************************************************************/
static void
settings_interface_init (NMSettingsInterface *iface)
{
/* interface implementation */
iface->list_connections = list_connections;
iface->get_connection_by_path = get_connection_by_path;
}
static GObject *
constructor (GType type,
guint n_construct_params,
GObjectConstructParam *construct_params)
{
GObject *object;
object = G_OBJECT_CLASS (nm_settings_service_parent_class)->constructor (type, n_construct_params, construct_params);
if (object)
g_assert (NM_SETTINGS_SERVICE_GET_PRIVATE (object)->scope != NM_CONNECTION_SCOPE_UNKNOWN);
return object;
}
static void
nm_settings_service_init (NMSettingsService *self)
{
}
static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
NMSettingsServicePrivate *priv = NM_SETTINGS_SERVICE_GET_PRIVATE (object);
switch (prop_id) {
case PROP_BUS:
/* Construct only */
priv->bus = dbus_g_connection_ref ((DBusGConnection *) g_value_get_boxed (value));
break;
case PROP_SCOPE:
/* Construct only */
priv->scope = g_value_get_uint (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
NMSettingsServicePrivate *priv = NM_SETTINGS_SERVICE_GET_PRIVATE (object);
switch (prop_id) {
case PROP_BUS:
g_value_set_boxed (value, priv->bus);
break;
case PROP_SCOPE:
g_value_set_uint (value, priv->scope);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
dispose (GObject *object)
{
NMSettingsServicePrivate *priv = NM_SETTINGS_SERVICE_GET_PRIVATE (object);
if (!priv->disposed) {
priv->disposed = TRUE;
dbus_g_connection_unref (priv->bus);
}
G_OBJECT_CLASS (nm_settings_service_parent_class)->dispose (object);
}
static void
nm_settings_service_class_init (NMSettingsServiceClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
g_type_class_add_private (class, sizeof (NMSettingsServicePrivate));
/* Virtual methods */
object_class->dispose = dispose;
object_class->constructor = constructor;
object_class->get_property = get_property;
object_class->set_property = set_property;
/**
* NMSettingsService:bus:
*
* The %DBusGConnection which this object is exported on
**/
g_object_class_install_property (object_class, PROP_BUS,
g_param_spec_boxed (NM_SETTINGS_SERVICE_BUS,
"Bus",
"Bus",
DBUS_TYPE_G_CONNECTION,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
/**
* NMSettingsService:scope:
*
* The capabilities of the device.
**/
g_object_class_install_property (object_class, PROP_SCOPE,
g_param_spec_uint (NM_SETTINGS_SERVICE_SCOPE,
"Scope",
"Scope",
NM_CONNECTION_SCOPE_USER,
NM_CONNECTION_SCOPE_SYSTEM,
NM_CONNECTION_SCOPE_USER,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (class),
&dbus_glib_nm_settings_object_info);
}

View file

@ -0,0 +1,71 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager system settings service
*
* 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 2009 Red Hat, Inc.
*/
#ifndef NM_SETTINGS_SERVICE_H
#define NM_SETTINGS_SERVICE_H
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
#include <nm-exported-connection.h>
#include <nm-settings-interface.h>
G_BEGIN_DECLS
#define NM_TYPE_SETTINGS_SERVICE (nm_settings_service_get_type ())
#define NM_SETTINGS_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTINGS_SERVICE, NMSettingsService))
#define NM_SETTINGS_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTINGS_SERVICE, NMSettingsServiceClass))
#define NM_IS_SETTINGS_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTINGS_SERVICE))
#define NM_IS_SETTINGS_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SETTINGS_SERVICE))
#define NM_SETTINGS_SERVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTINGS_SERVICE, NMSettingsServiceClass))
#define NM_SETTINGS_SERVICE_BUS "bus"
#define NM_SETTINGS_SERVICE_SCOPE "scope"
typedef struct {
GObject parent;
} NMSettingsService;
typedef struct {
GObjectClass parent;
/* Returned list must contain all NMExportedConnection objects exported
* by the settings service. The list (but not the NMExportedConnection
* objects) will be freed by caller.
*/
GSList * (*list_connections) (NMSettingsService *self);
NMExportedConnection * (*get_connection_by_path) (NMSettingsService *self,
const char *path);
void (*add_connection) (NMSettingsService *self,
GHashTable *settings,
DBusGMethodInvocation *context);
} NMSettingsServiceClass;
GType nm_settings_service_get_type (void);
NMExportedConnection *nm_settings_service_get_connection_by_path (NMSettingsService *self,
const char *path);
void nm_settings_service_export (NMSettingsService *self);
G_END_DECLS
#endif /* NM_SETTINGS_SERVICE_H */

View file

@ -0,0 +1,114 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager -- Network link manager
*
* 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.
*
* Copyright (C) 2007 - 2008 Novell, Inc.
* Copyright (C) 2007 - 2008 Red Hat, Inc.
*/
#include "nm-settings-interface.h"
#include "nm-settings-system-interface.h"
/**
* nm_settings_system_interface_save_hostname:
* @settings: a object implementing %NMSettingsSystemInterface
* @hostname: the new persistent hostname to set, or NULL to clear any existing
* persistent hostname
* @callback: callback to be called when the hostname operation completes
* @user_data: caller-specific data passed to @callback
*
* Requests that the machine's persistent hostname be set to the specified value
* or cleared.
*
* Returns: TRUE if the request was successful, FALSE if it failed
**/
gboolean
nm_settings_system_interface_save_hostname (NMSettingsSystemInterface *settings,
const char *hostname,
NMSettingsSystemSaveHostnameFunc callback,
gpointer user_data)
{
g_return_val_if_fail (settings != NULL, FALSE);
g_return_val_if_fail (NM_IS_SETTINGS_SYSTEM_INTERFACE (settings), FALSE);
g_return_val_if_fail (hostname != NULL, FALSE);
g_return_val_if_fail (callback != NULL, FALSE);
if (NM_SETTINGS_SYSTEM_INTERFACE_GET_INTERFACE (settings)->save_hostname) {
return NM_SETTINGS_SYSTEM_INTERFACE_GET_INTERFACE (settings)->save_hostname (settings,
hostname,
callback,
user_data);
}
return FALSE;
}
static void
nm_settings_system_interface_init (gpointer g_iface)
{
static gboolean initialized = FALSE;
if (initialized)
return;
/* Properties */
g_object_interface_install_property
(g_iface,
g_param_spec_string (NM_SETTINGS_SYSTEM_INTERFACE_HOSTNAME,
"Hostname",
"Persistent hostname",
NULL,
G_PARAM_READABLE));
g_object_interface_install_property
(g_iface,
g_param_spec_string (NM_SETTINGS_SYSTEM_INTERFACE_CAN_MODIFY,
"CanModify",
"Can modify anything (hostname, connections, etc)",
NULL,
G_PARAM_READABLE));
initialized = TRUE;
}
GType
nm_settings_system_interface_get_type (void)
{
static GType itype = 0;
if (!itype) {
const GTypeInfo iinfo = {
sizeof (NMSettingsSystemInterface), /* class_size */
nm_settings_system_interface_init, /* base_init */
NULL, /* base_finalize */
NULL,
NULL, /* class_finalize */
NULL, /* class_data */
0,
0, /* n_preallocs */
NULL
};
itype = g_type_register_static (G_TYPE_INTERFACE,
"NMSettingsSystemInterface",
&iinfo, 0);
g_type_interface_add_prerequisite (itype, NM_TYPE_SETTINGS_INTERFACE);
}
return itype;
}

View file

@ -0,0 +1,69 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager -- Network link manager
*
* 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.
*
* Copyright (C) 2007 - 2008 Novell, Inc.
* Copyright (C) 2007 - 2009 Red Hat, Inc.
*/
#ifndef NM_SETTINGS_SYSTEM_INTERFACE_H
#define NM_SETTINGS_SYSTEM_INTERFACE_H
#include <glib-object.h>
#include "NetworkManager.h"
#define NM_TYPE_SETTINGS_SYSTEM_INTERFACE (nm_settings_system_interface_get_type ())
#define NM_SETTINGS_SYSTEM_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTINGS_SYSTEM_INTERFACE, NMSettingsSystemInterface))
#define NM_IS_SETTINGS_SYSTEM_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTINGS_SYSTEM_INTERFACE))
#define NM_SETTINGS_SYSTEM_INTERFACE_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_SETTINGS_SYSTEM_INTERFACE, NMSettingsSystemInterface))
#define NM_SETTINGS_SYSTEM_INTERFACE_HOSTNAME "hostname"
#define NM_SETTINGS_SYSTEM_INTERFACE_CAN_MODIFY "can-modify"
typedef enum {
NM_SETTINGS_SYSTEM_INTERFACE_PROP_FIRST = 0x1000,
NM_SETTINGS_SYSTEM_INTERFACE_PROP_HOSTNAME = NM_SETTINGS_SYSTEM_INTERFACE_PROP_FIRST,
NM_SETTINGS_SYSTEM_INTERFACE_PROP_CAN_MODIFY
} NMSettingsSystemInterfaceProp;
typedef struct _NMSettingsSystemInterface NMSettingsSystemInterface;
typedef void (*NMSettingsSystemSaveHostnameFunc) (NMSettingsSystemInterface *settings,
GError *error,
gpointer user_data);
struct _NMSettingsSystemInterface {
GTypeInterface g_iface;
/* Methods */
gboolean (*save_hostname) (NMSettingsSystemInterface *settings,
const char *hostname,
NMSettingsSystemSaveHostnameFunc callback,
gpointer user_data);
};
GType nm_settings_system_interface_get_type (void);
gboolean nm_settings_system_interface_save_hostname (NMSettingsSystemInterface *settings,
const char *hostname,
NMSettingsSystemSaveHostnameFunc callback,
gpointer user_data);
#endif /* NM_SETTINGS_SYSTEM_INTERFACE_H */

View file

@ -1,607 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* libnm_glib -- Access network status & information from glib applications
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright (C) 2007 - 2008 Novell, Inc.
* Copyright (C) 2007 - 2008 Red Hat, Inc.
*/
#include <NetworkManager.h>
#include <nm-utils.h>
#include <nm-setting-connection.h>
#include "nm-settings.h"
#include "nm-dbus-glib-types.h"
#define NM_TYPE_SETTINGS_ERROR (nm_settings_error_get_type ())
/**
* nm_settings_error_quark:
*
* Setting error quark.
*
* Returns: the setting error quark
**/
GQuark
nm_settings_error_quark (void)
{
static GQuark quark;
if (G_UNLIKELY (!quark))
quark = g_quark_from_static_string ("nm-settings-error-quark");
return quark;
}
/* This should really be standard. */
#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
static GType
nm_settings_error_get_type (void)
{
static GType etype = 0;
if (etype == 0) {
static const GEnumValue values[] = {
/* The connection was invalid. */
ENUM_ENTRY (NM_SETTINGS_ERROR_INVALID_CONNECTION, "InvalidConnection"),
/* The connection is read-only; modifications are not allowed. */
ENUM_ENTRY (NM_SETTINGS_ERROR_READ_ONLY_CONNECTION, "ReadOnlyConnection"),
/* A bug in the settings service caused the error. */
ENUM_ENTRY (NM_SETTINGS_ERROR_INTERNAL_ERROR, "InternalError"),
/* Retrieval or request of secrets failed. */
ENUM_ENTRY (NM_SETTINGS_ERROR_SECRETS_UNAVAILABLE, "SecretsUnavailable"),
/* The request for secrets was canceled. */
ENUM_ENTRY (NM_SETTINGS_ERROR_SECRETS_REQUEST_CANCELED, "SecretsRequestCanceled"),
/* The request could not be completed because permission was denied. */
ENUM_ENTRY (NM_SETTINGS_ERROR_PERMISSION_DENIED, "PermissionDenied"),
{ 0, 0, 0 },
};
etype = g_enum_register_static ("NMSettingsError", values);
}
return etype;
}
/*
* NMSettings implementation
*/
static gboolean impl_settings_list_connections (NMSettings *settings, GPtrArray **connections, GError **error);
#include "nm-settings-glue.h"
#define SETTINGS_CLASS(o) (NM_SETTINGS_CLASS (G_OBJECT_GET_CLASS (o)))
G_DEFINE_TYPE (NMSettings, nm_settings, G_TYPE_OBJECT)
enum {
S_NEW_CONNECTION,
S_LAST_SIGNAL
};
static guint settings_signals[S_LAST_SIGNAL] = { 0 };
static gboolean
impl_settings_list_connections (NMSettings *settings, GPtrArray **connections, GError **error)
{
GSList *list, *iter;
g_return_val_if_fail (NM_IS_SETTINGS (settings), FALSE);
list = nm_settings_list_connections (settings);
*connections = g_ptr_array_new ();
for (iter = list; iter; iter = iter->next) {
NMConnection *connection = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (iter->data));
g_ptr_array_add (*connections, g_strdup (nm_connection_get_path (connection)));
}
g_slist_free (list);
return TRUE;
}
static void
nm_settings_init (NMSettings *settings)
{
}
static void
nm_settings_finalize (GObject *object)
{
G_OBJECT_CLASS (nm_settings_parent_class)->finalize (object);
}
static void
nm_settings_class_init (NMSettingsClass *settings_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (settings_class);
/* virtual methods */
object_class->finalize = nm_settings_finalize;
settings_class->list_connections = NULL;
/* signals */
/**
* NMSettings::new-connection:
* @setting: the setting that received the signal
* @connection: the new #NMExportedConnection
*
* Notifies that a new exported connection is added.
**/
settings_signals[S_NEW_CONNECTION] =
g_signal_new ("new-connection",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMSettingsClass, new_connection),
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
G_TYPE_OBJECT);
dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (settings_class),
&dbus_glib_nm_settings_object_info);
dbus_g_error_domain_register (NM_SETTINGS_ERROR, NULL, NM_TYPE_SETTINGS_ERROR);
}
/**
* nm_settings_list_connections:
* @settings:
*
* Lists all the available connections.
*
* Returns: the #GSList containing #NMExportedConnection<!-- -->s
**/
GSList *
nm_settings_list_connections (NMSettings *settings)
{
GSList *list = NULL;
g_return_val_if_fail (NM_IS_SETTINGS (settings), NULL);
if (SETTINGS_CLASS (settings)->list_connections)
list = SETTINGS_CLASS (settings)->list_connections (settings);
else
g_warning ("Missing implementation for Settings::list_connections.");
return list;
}
void
nm_settings_signal_new_connection (NMSettings *settings, NMExportedConnection *connection)
{
g_return_if_fail (NM_IS_SETTINGS (settings));
g_return_if_fail (NM_IS_EXPORTED_CONNECTION (connection));
g_signal_emit (settings, settings_signals[S_NEW_CONNECTION], 0, connection);
}
/*
* NMExportedConnection implementation
*/
static gboolean impl_exported_connection_get_settings (NMExportedConnection *connection,
GHashTable **settings,
GError **error);
static gboolean impl_exported_connection_update (NMExportedConnection *connection,
GHashTable *new_settings,
DBusGMethodInvocation *context);
static gboolean impl_exported_connection_delete (NMExportedConnection *connection,
DBusGMethodInvocation *context);
static void impl_exported_connection_get_secrets (NMExportedConnection *connection,
const gchar *setting_name,
const gchar **hints,
gboolean request_new,
DBusGMethodInvocation *context);
#include "nm-exported-connection-glue.h"
#define EXPORTED_CONNECTION_CLASS(o) (NM_EXPORTED_CONNECTION_CLASS (G_OBJECT_GET_CLASS (o)))
G_DEFINE_TYPE (NMExportedConnection, nm_exported_connection, G_TYPE_OBJECT)
enum {
EC_UPDATED,
EC_REMOVED,
EC_LAST_SIGNAL
};
static guint connection_signals[EC_LAST_SIGNAL] = { 0 };
enum {
PROP_0,
PROP_CONNECTION,
LAST_PROP
};
typedef struct {
NMConnection *wrapped;
} NMExportedConnectionPrivate;
#define NM_EXPORTED_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
NM_TYPE_EXPORTED_CONNECTION, \
NMExportedConnectionPrivate))
NMExportedConnection *
nm_exported_connection_new (NMConnection *wrapped)
{
g_return_val_if_fail (NM_IS_CONNECTION (wrapped), NULL);
return (NMExportedConnection *) g_object_new (NM_TYPE_EXPORTED_CONNECTION,
NM_EXPORTED_CONNECTION_CONNECTION, wrapped,
NULL);
}
static GHashTable *
real_get_settings (NMExportedConnection *exported)
{
NMExportedConnectionPrivate *priv;
NMConnection *no_secrets;
GHashTable *hash;
g_return_val_if_fail (NM_IS_EXPORTED_CONNECTION (exported), NULL);
priv = NM_EXPORTED_CONNECTION_GET_PRIVATE (exported);
/* Secrets should *never* be returned by the GetSettings method, they
* get returned by the GetSecrets method which can be better
* protected against leakage of secrets to unprivileged callers.
*/
no_secrets = nm_connection_duplicate (priv->wrapped);
nm_connection_clear_secrets (no_secrets);
hash = nm_connection_to_hash (no_secrets);
g_object_unref (G_OBJECT (no_secrets));
return hash;
}
static gboolean
impl_exported_connection_get_settings (NMExportedConnection *connection,
GHashTable **settings,
GError **error)
{
NMExportedConnectionPrivate *priv;
g_return_val_if_fail (NM_IS_EXPORTED_CONNECTION (connection), FALSE);
priv = NM_EXPORTED_CONNECTION_GET_PRIVATE (connection);
if (!EXPORTED_CONNECTION_CLASS (connection)->get_settings)
*settings = real_get_settings (connection);
else
*settings = EXPORTED_CONNECTION_CLASS (connection)->get_settings (connection);
return TRUE;
}
static gboolean
impl_exported_connection_update (NMExportedConnection *connection,
GHashTable *new_settings,
DBusGMethodInvocation *context)
{
GError *err = NULL;
NMConnection *wrapped;
gboolean success = FALSE;
/* Read-only connections obviously cannot be changed */
wrapped = nm_exported_connection_get_connection (connection);
if (wrapped) {
NMSettingConnection *s_con;
s_con = (NMSettingConnection *) nm_connection_get_setting (wrapped, NM_TYPE_SETTING_CONNECTION);
if (s_con && nm_setting_connection_get_read_only (s_con)) {
g_set_error (&err, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_READ_ONLY_CONNECTION,
"%s.%d - Read-only connections may not be modified.",
__FILE__, __LINE__);
}
}
if (!err) {
/* A hack to share the DBusGMethodInvocation with the possible overriders of connection::update */
g_object_set_data (G_OBJECT (connection), NM_EXPORTED_CONNECTION_DBUS_METHOD_INVOCATION, context);
success = nm_exported_connection_update (connection, new_settings, &err);
g_object_set_data (G_OBJECT (connection), NM_EXPORTED_CONNECTION_DBUS_METHOD_INVOCATION, NULL);
}
if (success) {
dbus_g_method_return (context);
} else {
dbus_g_method_return_error (context, err);
g_error_free (err);
}
return success;
}
static gboolean
impl_exported_connection_delete (NMExportedConnection *connection,
DBusGMethodInvocation *context)
{
GError *err = NULL;
NMConnection *wrapped;
gboolean success = FALSE;
/* Read-only connections obviously cannot be changed */
wrapped = nm_exported_connection_get_connection (connection);
if (wrapped) {
NMSettingConnection *s_con;
s_con = (NMSettingConnection *) nm_connection_get_setting (wrapped, NM_TYPE_SETTING_CONNECTION);
if (s_con && nm_setting_connection_get_read_only (s_con)) {
g_set_error (&err, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_READ_ONLY_CONNECTION,
"%s.%d - Read-only connections may not be deleted.",
__FILE__, __LINE__);
}
}
if (!err) {
/* A hack to share the DBusGMethodInvocation with the possible overriders of connection::delete */
g_object_set_data (G_OBJECT (connection), NM_EXPORTED_CONNECTION_DBUS_METHOD_INVOCATION, context);
success = nm_exported_connection_delete (connection, &err);
g_object_set_data (G_OBJECT (connection), NM_EXPORTED_CONNECTION_DBUS_METHOD_INVOCATION, NULL);
}
if (success) {
dbus_g_method_return (context);
} else {
dbus_g_method_return_error (context, err);
g_error_free (err);
}
return success;
}
static void
impl_exported_connection_get_secrets (NMExportedConnection *connection,
const gchar *setting_name,
const gchar **hints,
gboolean request_new,
DBusGMethodInvocation *context)
{
GError *error = NULL;
if (!NM_IS_EXPORTED_CONNECTION (connection)) {
g_set_error (&error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
"%s.%d - Invalid connection in ConnectionSettings::GetSecrets.",
__FILE__, __LINE__);
dbus_g_method_return_error (context, error);
g_error_free (error);
return;
}
if (!EXPORTED_CONNECTION_CLASS (connection)->service_get_secrets) {
g_set_error (&error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_SECRETS_UNAVAILABLE,
"%s.%d - Missing implementation for ConnectionSettings::GetSecrets.",
__FILE__, __LINE__);
dbus_g_method_return_error (context, error);
g_error_free (error);
return;
}
EXPORTED_CONNECTION_CLASS (connection)->service_get_secrets (connection, setting_name, hints, request_new, context);
}
static void
nm_exported_connection_init (NMExportedConnection *connection)
{
}
static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
GObject *connection;
NMExportedConnectionPrivate *priv = NM_EXPORTED_CONNECTION_GET_PRIVATE (object);
switch (prop_id) {
case PROP_CONNECTION:
if (priv->wrapped) {
g_object_unref (priv->wrapped);
priv->wrapped = NULL;
}
connection = g_value_dup_object (value);
if (connection)
priv->wrapped = NM_CONNECTION (connection);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
NMExportedConnection *exported = NM_EXPORTED_CONNECTION (object);
switch (prop_id) {
case PROP_CONNECTION:
g_value_set_object (value, nm_exported_connection_get_connection (exported));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
nm_exported_connection_dispose (GObject *object)
{
NMExportedConnectionPrivate *priv = NM_EXPORTED_CONNECTION_GET_PRIVATE (object);
if (priv->wrapped) {
g_object_unref (priv->wrapped);
priv->wrapped = NULL;
}
G_OBJECT_CLASS (nm_exported_connection_parent_class)->dispose (object);
}
static void
nm_exported_connection_class_init (NMExportedConnectionClass *exported_connection_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (exported_connection_class);
g_type_class_add_private (object_class, sizeof (NMExportedConnectionPrivate));
/* virtual methods */
object_class->set_property = set_property;
object_class->get_property = get_property;
object_class->dispose = nm_exported_connection_dispose;
exported_connection_class->get_settings = real_get_settings;
/* Properties */
g_object_class_install_property
(object_class, PROP_CONNECTION,
g_param_spec_object (NM_EXPORTED_CONNECTION_CONNECTION,
"Connection",
"Wrapped connection",
NM_TYPE_CONNECTION,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
/* signals */
connection_signals[EC_UPDATED] =
g_signal_new ("updated",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMExportedConnectionClass, updated),
NULL, NULL,
g_cclosure_marshal_VOID__BOXED,
G_TYPE_NONE, 1,
DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT);
connection_signals[EC_REMOVED] =
g_signal_new ("removed",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMExportedConnectionClass, removed),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (exported_connection_class),
&dbus_glib_nm_exported_connection_object_info);
}
NMConnection *
nm_exported_connection_get_connection (NMExportedConnection *connection)
{
g_return_val_if_fail (NM_IS_EXPORTED_CONNECTION (connection), NULL);
return NM_EXPORTED_CONNECTION_GET_PRIVATE (connection)->wrapped;
}
void
nm_exported_connection_register_object (NMExportedConnection *connection,
NMConnectionScope scope,
DBusGConnection *dbus_connection)
{
NMExportedConnectionPrivate *priv;
static guint32 ec_counter = 0;
char *path;
g_return_if_fail (NM_IS_EXPORTED_CONNECTION (connection));
g_return_if_fail (dbus_connection != NULL);
priv = NM_EXPORTED_CONNECTION_GET_PRIVATE (connection);
/* Don't allow the connection to be exported twice */
g_return_if_fail (nm_connection_get_path (priv->wrapped) == NULL);
path = g_strdup_printf ("%s/%u", NM_DBUS_PATH_SETTINGS, ec_counter++);
nm_connection_set_path (priv->wrapped, path);
nm_connection_set_scope (priv->wrapped, scope);
dbus_g_connection_register_g_object (dbus_connection,
path,
G_OBJECT (connection));
g_free (path);
}
gboolean
nm_exported_connection_update (NMExportedConnection *connection,
GHashTable *new_settings,
GError **err)
{
gboolean success = TRUE;
GError *error = NULL;
g_return_val_if_fail (NM_IS_EXPORTED_CONNECTION (connection), FALSE);
g_return_val_if_fail (new_settings != NULL, FALSE);
if (EXPORTED_CONNECTION_CLASS (connection)->update)
success = EXPORTED_CONNECTION_CLASS (connection)->update (connection, new_settings, err);
if (success) {
if (!nm_connection_replace_settings (NM_EXPORTED_CONNECTION_GET_PRIVATE (connection)->wrapped, new_settings, &error)) {
g_warning ("%s: '%s' / '%s' invalid: %d",
__func__,
error ? g_type_name (nm_connection_lookup_setting_type_by_quark (error->domain)) : "(none)",
(error && error->message) ? error->message : "(none)",
error ? error->code : -1);
g_clear_error (&error);
success = FALSE;
} else
nm_exported_connection_signal_updated (connection, new_settings);
}
return success;
}
gboolean
nm_exported_connection_delete (NMExportedConnection *connection, GError **err)
{
gboolean success = TRUE;
g_return_val_if_fail (NM_IS_EXPORTED_CONNECTION (connection), FALSE);
if (EXPORTED_CONNECTION_CLASS (connection)->do_delete)
success = EXPORTED_CONNECTION_CLASS (connection)->do_delete (connection, err);
if (success)
nm_exported_connection_signal_removed (connection);
return success;
}
void
nm_exported_connection_signal_updated (NMExportedConnection *connection, GHashTable *settings)
{
g_return_if_fail (NM_IS_EXPORTED_CONNECTION (connection));
g_signal_emit (connection, connection_signals[EC_UPDATED], 0, settings);
}
void
nm_exported_connection_signal_removed (NMExportedConnection *connection)
{
g_return_if_fail (NM_IS_EXPORTED_CONNECTION (connection));
g_signal_emit (connection, connection_signals[EC_REMOVED], 0);
}

View file

@ -1,145 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* libnm_glib -- Access network status & information from glib applications
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright (C) 2007 - 2008 Novell, Inc.
* Copyright (C) 2007 - 2008 Red Hat, Inc.
*/
#ifndef __NM_SETTINGS_H__
#define __NM_SETTINGS_H__
#include <glib-object.h>
#include <dbus/dbus-glib.h>
#include <nm-connection.h>
G_BEGIN_DECLS
typedef enum
{
NM_SETTINGS_ERROR_INVALID_CONNECTION = 0,
NM_SETTINGS_ERROR_READ_ONLY_CONNECTION,
NM_SETTINGS_ERROR_INTERNAL_ERROR,
NM_SETTINGS_ERROR_SECRETS_UNAVAILABLE,
NM_SETTINGS_ERROR_SECRETS_REQUEST_CANCELED,
NM_SETTINGS_ERROR_PERMISSION_DENIED
} NMSettingsError;
#define NM_SETTINGS_ERROR (nm_settings_error_quark ())
GQuark nm_settings_error_quark (void);
#define NM_TYPE_EXPORTED_CONNECTION (nm_exported_connection_get_type ())
#define NM_EXPORTED_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_EXPORTED_CONNECTION, NMExportedConnection))
#define NM_EXPORTED_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_EXPORTED_CONNECTION, NMExportedConnectionClass))
#define NM_IS_EXPORTED_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_EXPORTED_CONNECTION))
#define NM_IS_EXPORTED_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_EXPORTED_CONNECTION))
#define NM_EXPORTED_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_EXPORTED_CONNECTION, NMExportedConnectionClass))
#define NM_EXPORTED_CONNECTION_CONNECTION "connection"
#define NM_EXPORTED_CONNECTION_DBUS_METHOD_INVOCATION "nm-exported-connection-dbus-method-invocation"
typedef struct {
GObject parent;
} NMExportedConnection;
typedef struct {
GObjectClass parent_class;
/* virtual methods */
GHashTable * (*get_settings) (NMExportedConnection *connection);
/* service_get_secrets is used in a D-Bus service (like the system settings
* service) to respond to GetSecrets requests from clients.
*/
void (*service_get_secrets) (NMExportedConnection *connection,
const gchar *setting_name,
const gchar **hints,
gboolean request_new,
DBusGMethodInvocation *context);
gboolean (*update) (NMExportedConnection *connection,
GHashTable *new_settings,
GError **err);
gboolean (*do_delete) (NMExportedConnection *connection,
GError **err);
/* signals */
void (*updated) (NMExportedConnection *connection, GHashTable *settings);
void (*removed) (NMExportedConnection *connection);
} NMExportedConnectionClass;
GType nm_exported_connection_get_type (void);
NMExportedConnection *nm_exported_connection_new (NMConnection *wrapped);
void nm_exported_connection_register_object (NMExportedConnection *connection,
NMConnectionScope scope,
DBusGConnection *dbus_connection);
NMConnection *nm_exported_connection_get_connection (NMExportedConnection *connection);
gboolean nm_exported_connection_update (NMExportedConnection *connection,
GHashTable *new_settings,
GError **err);
gboolean nm_exported_connection_delete (NMExportedConnection *connection,
GError **err);
void nm_exported_connection_signal_updated (NMExportedConnection *connection,
GHashTable *new_settings);
void nm_exported_connection_signal_removed (NMExportedConnection *connection);
#define NM_TYPE_SETTINGS (nm_settings_get_type ())
#define NM_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTINGS, NMSettings))
#define NM_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTINGS, NMSettingsClass))
#define NM_IS_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTINGS))
#define NM_IS_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SETTINGS))
#define NM_SETTINGS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTINGS, NMSettingsClass))
typedef struct {
GObject parent;
} NMSettings;
typedef struct {
GObjectClass parent_class;
/* virtual methods */
/* Returns a list of NMExportedConnections. Caller should free the list. */
GSList * (*list_connections) (NMSettings *settings);
/* signals */
void (* new_connection) (NMSettings *settings, NMExportedConnection *connection);
} NMSettingsClass;
GType nm_settings_get_type (void);
GSList *nm_settings_list_connections (NMSettings *settings);
void nm_settings_signal_new_connection (NMSettings *settings, NMExportedConnection *connection);
G_END_DECLS
#endif

View file

@ -18,7 +18,6 @@ VOID:STRING,INT
VOID:STRING,UINT
VOID:OBJECT,OBJECT,ENUM
VOID:POINTER,STRING
POINTER:POINTER
VOID:STRING,BOXED
BOOLEAN:POINTER,STRING,BOOLEAN,UINT,STRING,STRING
BOOLEAN:VOID

View file

@ -49,6 +49,8 @@
#include "nm-bluez-common.h"
#include "nm-sysconfig-settings.h"
#include "nm-secrets-provider-interface.h"
#include "nm-settings-interface.h"
#include "nm-settings-system-interface.h"
#define NM_AUTOIP_DBUS_SERVICE "org.freedesktop.nm_avahi_autoipd"
#define NM_AUTOIP_DBUS_IFACE "org.freedesktop.nm_avahi_autoipd"
@ -862,18 +864,16 @@ user_query_connections (NMManager *manager)
/*******************************************************************/
static void
system_connection_updated_cb (NMExportedConnection *exported,
system_connection_updated_cb (NMSettingsConnectionInterface *connection,
gpointer unused,
NMManager *manager)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
const char *path;
NMConnection *existing;
NMConnection *connection;
NMSettingsConnectionInterface *existing;
GError *error = NULL;
connection = nm_exported_connection_get_connection (exported);
path = nm_connection_get_path (connection);
path = nm_connection_get_path (NM_CONNECTION (connection));
existing = g_hash_table_lookup (priv->system_connections, path);
if (!existing)
@ -883,14 +883,14 @@ system_connection_updated_cb (NMExportedConnection *exported,
return;
}
if (!nm_connection_verify (existing, &error)) {
if (!nm_connection_verify (NM_CONNECTION (existing), &error)) {
/* Updated connection invalid, remove existing connection */
nm_warning ("%s: Invalid connection: '%s' / '%s' invalid: %d",
__func__,
g_type_name (nm_connection_lookup_setting_type_by_quark (error->domain)),
error->message, error->code);
g_error_free (error);
remove_connection (manager, existing, priv->system_connections);
remove_connection (manager, NM_CONNECTION (existing), priv->system_connections);
return;
}
@ -901,37 +901,33 @@ system_connection_updated_cb (NMExportedConnection *exported,
}
static void
system_connection_removed_cb (NMExportedConnection *exported,
system_connection_removed_cb (NMSettingsConnectionInterface *connection,
NMManager *manager)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
const char *path;
NMConnection *connection;
connection = nm_exported_connection_get_connection (exported);
path = nm_connection_get_path (connection);
path = nm_connection_get_path (NM_CONNECTION (connection));
connection = g_hash_table_lookup (priv->system_connections, path);
if (connection)
remove_connection (manager, connection, priv->system_connections);
remove_connection (manager, NM_CONNECTION (connection), priv->system_connections);
}
static void
system_internal_new_connection (NMManager *manager,
NMExportedConnection *exported)
NMSettingsConnectionInterface *connection)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
NMConnection *connection;
const char *path;
g_return_if_fail (exported != NULL);
g_return_if_fail (connection != NULL);
g_signal_connect (exported, "updated",
g_signal_connect (connection, "updated",
G_CALLBACK (system_connection_updated_cb), manager);
g_signal_connect (exported, "removed",
g_signal_connect (connection, "removed",
G_CALLBACK (system_connection_removed_cb), manager);
connection = nm_exported_connection_get_connection (exported);
path = nm_connection_get_path (NM_CONNECTION (connection));
g_hash_table_insert (priv->system_connections, g_strdup (path),
g_object_ref (connection));
@ -939,10 +935,10 @@ system_internal_new_connection (NMManager *manager,
static void
system_new_connection_cb (NMSysconfigSettings *settings,
NMExportedConnection *exported,
NMSettingsConnectionInterface *connection,
NMManager *manager)
{
system_internal_new_connection (manager, exported);
system_internal_new_connection (manager, connection);
}
static void
@ -951,9 +947,9 @@ system_query_connections (NMManager *manager)
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
GSList *system_connections, *iter;
system_connections = nm_sysconfig_settings_list_connections (priv->sys_settings);
system_connections = nm_settings_interface_list_connections (NM_SETTINGS_INTERFACE (priv->sys_settings));
for (iter = system_connections; iter; iter = g_slist_next (iter))
system_internal_new_connection (manager, NM_EXPORTED_CONNECTION (iter->data));
system_internal_new_connection (manager, NM_SETTINGS_CONNECTION_INTERFACE (iter->data));
g_slist_free (system_connections);
}
@ -1679,43 +1675,55 @@ user_get_secrets (NMManager *self,
return info;
}
static void
system_get_secrets_reply_cb (NMSettingsConnectionInterface *connection,
GHashTable *secrets,
GError *error,
gpointer user_data)
{
GetSecretsInfo *info = user_data;
nm_secrets_provider_interface_get_secrets_result (info->provider,
info->setting_name,
info->caller,
error ? NULL : secrets,
error);
free_get_secrets_info (info);
}
static gboolean
system_get_secrets_cb (gpointer user_data)
system_get_secrets_idle_cb (gpointer user_data)
{
GetSecretsInfo *info = user_data;
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (info->manager);
GHashTable *settings;
NMSysconfigConnection *exported;
NMSettingsConnectionInterface *connection;
GError *error = NULL;
const char *hints[3] = { NULL, NULL, NULL };
exported = nm_sysconfig_settings_get_connection_by_path (priv->sys_settings,
info->connection_path);
if (!exported) {
g_set_error (&error, 0, 0, "%s", "unknown connection (not exported by "
"system settings)");
info->idle_id = 0;
connection = nm_settings_interface_get_connection_by_path (NM_SETTINGS_INTERFACE (priv->sys_settings),
info->connection_path);
if (!connection) {
error = g_error_new_literal (0, 0, "unknown connection (not exported by system settings)");
nm_secrets_provider_interface_get_secrets_result (info->provider,
info->setting_name,
info->caller,
NULL,
error);
g_clear_error (&error);
g_error_free (error);
free_get_secrets_info (info);
return FALSE;
}
hints[0] = info->hint1;
hints[1] = info->hint2;
settings = nm_sysconfig_connection_get_secrets (exported,
info->setting_name,
hints,
info->request_new,
&error);
nm_secrets_provider_interface_get_secrets_result (info->provider,
info->setting_name,
info->caller,
settings,
NULL);
g_hash_table_destroy (settings);
nm_settings_connection_interface_get_secrets (connection,
info->setting_name,
hints,
info->request_new,
system_get_secrets_reply_cb,
info);
return FALSE;
}
@ -1744,9 +1752,9 @@ system_get_secrets (NMManager *self,
g_object_weak_ref (G_OBJECT (provider), (GWeakNotify) free_get_secrets_info, info);
info->idle_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
system_get_secrets_cb,
system_get_secrets_idle_cb,
info,
free_get_secrets_info);
NULL);
return info;
}
@ -2455,7 +2463,7 @@ nm_manager_get (const char *config_file, const char *plugins, GError **error)
g_signal_connect (priv->sys_settings, "notify::" NM_SYSCONFIG_SETTINGS_UNMANAGED_SPECS,
G_CALLBACK (system_unmanaged_devices_changed_cb), singleton);
g_signal_connect (priv->sys_settings, "notify::" NM_SYSCONFIG_SETTINGS_HOSTNAME,
g_signal_connect (priv->sys_settings, "notify::" NM_SETTINGS_SYSTEM_INTERFACE_HOSTNAME,
G_CALLBACK (system_hostname_changed_cb), singleton);
g_signal_connect (priv->sys_settings, "new-connection",
G_CALLBACK (system_new_connection_cb), singleton);

View file

@ -15,7 +15,6 @@ libsystem_settings_la_SOURCES = \
nm-sysconfig-settings.h \
nm-inotify-helper.c \
nm-inotify-helper.h \
nm-polkit-helpers.c \
nm-polkit-helpers.h \
nm-system-config-error.c \
nm-system-config-error.h \

View file

@ -24,7 +24,6 @@
#include <glib/gi18n.h>
#include <NetworkManager.h>
#include <nm-settings.h>
#include <nm-setting-connection.h>
#include <nm-setting-wired.h>
#include <nm-utils.h>
@ -32,8 +31,15 @@
#include "nm-dbus-glib-types.h"
#include "nm-marshal.h"
#include "nm-default-wired-connection.h"
#include "nm-settings-connection-interface.h"
G_DEFINE_TYPE (NMDefaultWiredConnection, nm_default_wired_connection, NM_TYPE_SYSCONFIG_CONNECTION)
static NMSettingsConnectionInterface *parent_settings_connection_iface;
static void settings_connection_interface_init (NMSettingsConnectionInterface *iface);
G_DEFINE_TYPE_EXTENDED (NMDefaultWiredConnection, nm_default_wired_connection, NM_TYPE_SYSCONFIG_CONNECTION, 0,
G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_CONNECTION_INTERFACE,
settings_connection_interface_init))
#define NM_DEFAULT_WIRED_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEFAULT_WIRED_CONNECTION, NMDefaultWiredConnectionPrivate))
@ -86,18 +92,13 @@ nm_default_wired_connection_get_device (NMDefaultWiredConnection *wired)
}
static GByteArray *
dup_wired_mac (NMExportedConnection *exported)
dup_wired_mac (NMConnection *connection)
{
NMConnection *wrapped;
NMSettingWired *s_wired;
const GByteArray *mac;
GByteArray *dup;
wrapped = nm_exported_connection_get_connection (exported);
if (!wrapped)
return NULL;
s_wired = (NMSettingWired *) nm_connection_get_setting (wrapped, NM_TYPE_SETTING_WIRED);
s_wired = (NMSettingWired *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED);
if (!s_wired)
return NULL;
@ -111,53 +112,59 @@ dup_wired_mac (NMExportedConnection *exported)
}
static gboolean
update (NMExportedConnection *exported,
GHashTable *new_settings,
GError **error)
update (NMSettingsConnectionInterface *connection,
NMSettingsConnectionInterfaceUpdateFunc callback,
gpointer user_data)
{
NMDefaultWiredConnection *connection = NM_DEFAULT_WIRED_CONNECTION (exported);
gboolean success;
NMDefaultWiredConnection *self = NM_DEFAULT_WIRED_CONNECTION (connection);
GByteArray *mac;
gboolean failed = FALSE;
/* Ensure object stays alive across signal emission */
g_object_ref (exported);
g_object_ref (self);
/* Save a copy of the current MAC address just in case the user
* changed it when updating the connection.
*/
mac = dup_wired_mac (exported);
mac = dup_wired_mac (NM_CONNECTION (self));
/* Let NMSysconfigConnection check permissions */
success = NM_EXPORTED_CONNECTION_CLASS (nm_default_wired_connection_parent_class)->update (exported, new_settings, error);
if (success) {
g_signal_emit_by_name (connection, "try-update", new_settings, error);
success = *error ? FALSE : TRUE;
if (success)
g_signal_emit (connection, signals[DELETED], 0, mac);
}
g_signal_emit (self, signals[TRY_UPDATE], 0, &failed);
if (!failed)
g_signal_emit (connection, signals[DELETED], 0, mac);
g_byte_array_free (mac, TRUE);
g_object_unref (exported);
return success;
g_object_unref (self);
return parent_settings_connection_iface->update (connection, callback, user_data);
}
static gboolean
do_delete (NMExportedConnection *exported, GError **error)
static gboolean
do_delete (NMSettingsConnectionInterface *connection,
NMSettingsConnectionInterfaceDeleteFunc callback,
gpointer user_data)
{
gboolean success;
NMDefaultWiredConnection *self = NM_DEFAULT_WIRED_CONNECTION (connection);
GByteArray *mac;
g_object_ref (exported);
mac = dup_wired_mac (exported);
g_object_ref (self);
mac = dup_wired_mac (NM_CONNECTION (self));
success = NM_EXPORTED_CONNECTION_CLASS (nm_default_wired_connection_parent_class)->do_delete (exported, error);
if (success)
g_signal_emit (exported, signals[DELETED], 0, mac);
g_signal_emit (self, signals[DELETED], 0, mac);
g_byte_array_free (mac, TRUE);
g_object_unref (exported);
return success;
g_object_unref (self);
return parent_settings_connection_iface->delete (connection, callback, user_data);
}
/****************************************************************/
static void
settings_connection_interface_init (NMSettingsConnectionInterface *iface)
{
parent_settings_connection_iface = g_type_interface_peek_parent (iface);
iface->update = update;
iface->delete = do_delete;
}
static void
@ -172,7 +179,6 @@ constructor (GType type,
{
GObject *object;
NMDefaultWiredConnectionPrivate *priv;
NMConnection *wrapped;
NMSettingConnection *s_con;
NMSettingWired *s_wired;
char *id, *uuid;
@ -183,8 +189,6 @@ constructor (GType type,
priv = NM_DEFAULT_WIRED_CONNECTION_GET_PRIVATE (object);
wrapped = nm_connection_new ();
s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
id = g_strdup_printf (_("Auto %s"), nm_device_get_iface (priv->device));
@ -201,15 +205,12 @@ constructor (GType type,
g_free (id);
g_free (uuid);
nm_connection_add_setting (wrapped, NM_SETTING (s_con));
nm_connection_add_setting (NM_CONNECTION (object), NM_SETTING (s_con));
/* Lock the connection to the specific device */
s_wired = NM_SETTING_WIRED (nm_setting_wired_new ());
g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, priv->mac, NULL);
nm_connection_add_setting (wrapped, NM_SETTING (s_wired));
g_object_set (object, NM_EXPORTED_CONNECTION_CONNECTION, wrapped, NULL);
g_object_unref (wrapped);
nm_connection_add_setting (NM_CONNECTION (object), NM_SETTING (s_wired));
return object;
}
@ -288,19 +289,20 @@ try_update_signal_accumulator (GSignalInvocationHint *ihint,
const GValue *handler_return,
gpointer data)
{
gpointer new_ptr = g_value_get_pointer (handler_return);
if (g_value_get_boolean (handler_return)) {
g_value_set_boolean (return_accu, TRUE);
/* Stop */
return FALSE;
}
g_value_set_pointer (return_accu, new_ptr);
/* Continue if no error was returned from the handler */
return new_ptr ? FALSE : TRUE;
/* Continue if handler didn't fail */
return TRUE;
}
static void
nm_default_wired_connection_class_init (NMDefaultWiredConnectionClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
NMExportedConnectionClass *exported_class = NM_EXPORTED_CONNECTION_CLASS (klass);
g_type_class_add_private (klass, sizeof (NMDefaultWiredConnectionPrivate));
@ -310,9 +312,6 @@ nm_default_wired_connection_class_init (NMDefaultWiredConnectionClass *klass)
object_class->get_property = get_property;
object_class->finalize = finalize;
exported_class->update = update;
exported_class->do_delete = do_delete;
/* Properties */
g_object_class_install_property
(object_class, PROP_MAC,
@ -343,16 +342,14 @@ nm_default_wired_connection_class_init (NMDefaultWiredConnectionClass *klass)
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
0, try_update_signal_accumulator, NULL,
_nm_marshal_POINTER__POINTER,
G_TYPE_POINTER, 1,
DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT);
_nm_marshal_BOOLEAN__VOID,
G_TYPE_BOOLEAN, 0);
/* The 'deleted' signal is used to signal intentional deletions (like
* updating or user-requested deletion) rather than using the
* NMExportedConnection superclass' 'removed' signal, since that signal
* doesn't have the semantics we want; it gets emitted as a side-effect
* of various operations and is meant more for D-Bus clients instead
* of in-service uses.
* superclass' 'removed' signal, since that signal doesn't have the
* semantics we want; it gets emitted as a side-effect of various operations
* and is meant more for D-Bus clients instead of in-service uses.
*/
signals[DELETED] =
g_signal_new ("deleted",

View file

@ -22,7 +22,6 @@
#ifndef NM_DEFAULT_WIRED_CONNECTION_H
#define NM_DEFAULT_WIRED_CONNECTION_H
#include <nm-settings.h>
#include "nm-sysconfig-connection.h"
#include "nm-device.h"

View file

@ -1,184 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager system settings service
*
* 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 2008 Novell, Inc.
* (C) Copyright 2008 Red Hat, Inc.
*/
#include <nm-dbus-settings.h>
#include "nm-polkit-helpers.h"
#include "nm-system-config-error.h"
static gboolean
pk_io_watch_have_data (GIOChannel *channel, GIOCondition condition, gpointer user_data)
{
int fd;
PolKitContext *pk_context = (PolKitContext *) user_data;
fd = g_io_channel_unix_get_fd (channel);
polkit_context_io_func (pk_context, fd);
return TRUE;
}
static int
pk_io_add_watch (PolKitContext *pk_context, int fd)
{
guint id = 0;
GIOChannel *channel;
channel = g_io_channel_unix_new (fd);
if (channel == NULL)
goto out;
id = g_io_add_watch (channel, G_IO_IN, pk_io_watch_have_data, pk_context);
if (id == 0) {
g_io_channel_unref (channel);
goto out;
}
g_io_channel_unref (channel);
out:
return id;
}
static void
pk_io_remove_watch (PolKitContext *pk_context, int watch_id)
{
g_source_remove (watch_id);
}
PolKitContext *
create_polkit_context (GError **error)
{
static PolKitContext *global_context = NULL;
PolKitError *pk_err = NULL;
if (G_LIKELY (global_context))
return polkit_context_ref (global_context);
global_context = polkit_context_new ();
polkit_context_set_io_watch_functions (global_context, pk_io_add_watch, pk_io_remove_watch);
if (!polkit_context_init (global_context, &pk_err)) {
g_set_error (error, NM_SYSCONFIG_SETTINGS_ERROR,
NM_SYSCONFIG_SETTINGS_ERROR_GENERAL,
"%s (%d): %s",
pk_err ? polkit_error_get_error_name (pk_err) : "(unknown)",
pk_err ? polkit_error_get_error_code (pk_err) : -1,
pk_err ? polkit_error_get_error_message (pk_err) : "(unknown)");
if (pk_err)
polkit_error_free (pk_err);
/* PK 0.6's polkit_context_init() unrefs the global_context on failure */
#if (POLKIT_VERSION_MAJOR == 0) && (POLKIT_VERSION_MINOR >= 7)
polkit_context_unref (global_context);
#endif
global_context = NULL;
}
return global_context;
}
gboolean
check_polkit_privileges (DBusGConnection *dbus_connection,
PolKitContext *pol_ctx,
DBusGMethodInvocation *context,
GError **err)
{
DBusConnection *tmp;
DBusError dbus_error;
char *sender;
gulong sender_uid = G_MAXULONG;
PolKitCaller *pk_caller;
PolKitAction *pk_action;
PolKitResult pk_result;
/* Always allow uid 0 */
tmp = dbus_g_connection_get_connection (dbus_connection);
if (!tmp) {
g_set_error (err,
NM_SYSCONFIG_SETTINGS_ERROR,
NM_SYSCONFIG_SETTINGS_ERROR_GENERAL,
"Could not get D-Bus connection.");
return FALSE;
}
sender = dbus_g_method_get_sender (context);
dbus_error_init (&dbus_error);
/* FIXME: do this async */
sender_uid = dbus_bus_get_unix_user (tmp, sender, &dbus_error);
if (dbus_error_is_set (&dbus_error)) {
g_set_error (err,
NM_SYSCONFIG_SETTINGS_ERROR,
NM_SYSCONFIG_SETTINGS_ERROR_GENERAL,
"Could not determine the Unix user ID of the requestor: %s: %s",
dbus_error.name, dbus_error.message);
dbus_error_free (&dbus_error);
return FALSE;
}
/* PolicyKit < 1.0 is not compatible with root processes spawned outside
* the session manager, and when asking ConsoleKit for the session of the
* process, ConsoleKit won't be able to get XDG_SESSION_COOKIE because it
* doesn't exist in the caller's environment for non-session-managed
* processes. So, for PK < 1.0, ignore PolicyKit for uid 0.
*/
if (0 == sender_uid)
return TRUE;
/* Non-root users need to auth via PolicyKit */
dbus_error_init (&dbus_error);
pk_caller = polkit_caller_new_from_dbus_name (dbus_g_connection_get_connection (dbus_connection),
sender,
&dbus_error);
g_free (sender);
if (dbus_error_is_set (&dbus_error)) {
*err = g_error_new (NM_SYSCONFIG_SETTINGS_ERROR,
NM_SYSCONFIG_SETTINGS_ERROR_NOT_PRIVILEGED,
"Error getting information about caller: %s: %s",
dbus_error.name, dbus_error.message);
dbus_error_free (&dbus_error);
if (pk_caller)
polkit_caller_unref (pk_caller);
return FALSE;
}
pk_action = polkit_action_new ();
polkit_action_set_action_id (pk_action, NM_SYSCONFIG_POLICY_ACTION);
#if (POLKIT_VERSION_MAJOR == 0) && (POLKIT_VERSION_MINOR < 7)
pk_result = polkit_context_can_caller_do_action (pol_ctx, pk_action, pk_caller);
#else
pk_result = polkit_context_is_caller_authorized (pol_ctx, pk_action, pk_caller, TRUE, NULL);
#endif
polkit_caller_unref (pk_caller);
polkit_action_unref (pk_action);
if (pk_result != POLKIT_RESULT_YES) {
*err = g_error_new (NM_SYSCONFIG_SETTINGS_ERROR,
NM_SYSCONFIG_SETTINGS_ERROR_NOT_PRIVILEGED,
"%s %s",
NM_SYSCONFIG_POLICY_ACTION,
polkit_result_to_string_representation (pk_result));
return FALSE;
}
return TRUE;
}

View file

@ -22,16 +22,8 @@
#ifndef NM_POLKIT_HELPERS_H
#define NM_POLKIT_HELPERS_H
#include <polkit-dbus/polkit-dbus.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
#include <polkit/polkit.h>
#define NM_SYSCONFIG_POLICY_ACTION "org.freedesktop.network-manager-settings.system.modify"
PolKitContext *create_polkit_context (GError **error);
gboolean check_polkit_privileges (DBusGConnection *dbus_connection,
PolKitContext *pol_ctx,
DBusGMethodInvocation *context,
GError **err);
#endif /* NM_POLKIT_HELPERS_H */

View file

@ -16,51 +16,55 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* (C) Copyright 2008 Novell, Inc.
* (C) Copyright 2008 - 2009 Red Hat, Inc.
*/
#include <NetworkManager.h>
#include <dbus/dbus-glib-lowlevel.h>
#include "nm-sysconfig-connection.h"
#include "nm-system-config-error.h"
#include "nm-polkit-helpers.h"
#include "nm-dbus-glib-types.h"
#include "nm-settings-connection-interface.h"
#include "nm-settings-interface.h"
#include "nm-polkit-helpers.h"
G_DEFINE_ABSTRACT_TYPE (NMSysconfigConnection, nm_sysconfig_connection, NM_TYPE_EXPORTED_CONNECTION)
static void settings_connection_interface_init (NMSettingsConnectionInterface *klass);
G_DEFINE_TYPE_EXTENDED (NMSysconfigConnection, nm_sysconfig_connection, NM_TYPE_EXPORTED_CONNECTION, 0,
G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_CONNECTION_INTERFACE,
settings_connection_interface_init))
#define NM_SYSCONFIG_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
NM_TYPE_SYSCONFIG_CONNECTION, \
NMSysconfigConnectionPrivate))
typedef struct {
DBusGConnection *dbus_connection;
PolKitContext *pol_ctx;
DBusGProxy *proxy;
DBusGConnection *bus;
PolkitAuthority *authority;
} NMSysconfigConnectionPrivate;
/**************************************************************/
static gboolean
update (NMExportedConnection *exported,
GHashTable *new_settings,
GError **err)
update (NMSettingsConnectionInterface *connection,
NMSettingsConnectionInterfaceUpdateFunc callback,
gpointer user_data)
{
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (exported);
DBusGMethodInvocation *context;
context = g_object_get_data (G_OBJECT (exported), NM_EXPORTED_CONNECTION_DBUS_METHOD_INVOCATION);
g_return_val_if_fail (context != NULL, FALSE);
return check_polkit_privileges (priv->dbus_connection, priv->pol_ctx, context, err);
/* Default handler for subclasses */
callback (connection, NULL, user_data);
return TRUE;
}
static gboolean
do_delete (NMExportedConnection *exported, GError **err)
do_delete (NMSettingsConnectionInterface *connection,
NMSettingsConnectionInterfaceDeleteFunc callback,
gpointer user_data)
{
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (exported);
DBusGMethodInvocation *context;
context = g_object_get_data (G_OBJECT (exported), NM_EXPORTED_CONNECTION_DBUS_METHOD_INVOCATION);
g_return_val_if_fail (context != NULL, FALSE);
return check_polkit_privileges (priv->dbus_connection, priv->pol_ctx, context, err);
/* Default handler for subclasses */
callback (connection, NULL, user_data);
return TRUE;
}
static GValue *
@ -118,25 +122,28 @@ destroy_gvalue (gpointer data)
g_slice_free (GValue, value);
}
GHashTable *
nm_sysconfig_connection_get_secrets (NMSysconfigConnection *self,
const gchar *setting_name,
const gchar **hints,
gboolean request_new,
GError **error)
static gboolean
get_secrets (NMSettingsConnectionInterface *connection,
const char *setting_name,
const char **hints,
gboolean request_new,
NMSettingsConnectionInterfaceGetSecretsFunc callback,
gpointer user_data)
{
NMConnection *connection;
GHashTable *settings = NULL;
GHashTable *secrets = NULL;
NMSetting *setting;
GError *error = NULL;
connection = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (self));
setting = nm_connection_get_setting_by_name (connection, setting_name);
setting = nm_connection_get_setting_by_name (NM_CONNECTION (connection), setting_name);
if (!setting) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
"%s.%d - Connection didn't have requested setting '%s'.",
__FILE__, __LINE__, setting_name);
return NULL;
error = g_error_new (NM_SETTINGS_INTERFACE_ERROR,
NM_SETTINGS_INTERFACE_ERROR_INVALID_CONNECTION,
"%s.%d - Connection didn't have requested setting '%s'.",
__FILE__, __LINE__, setting_name);
(*callback) (connection, NULL, error, user_data);
g_error_free (error);
return TRUE;
}
/* Returned secrets are a{sa{sv}}; this is the outer a{s...} hash that
@ -150,166 +157,349 @@ nm_sysconfig_connection_get_secrets (NMSysconfigConnection *self,
nm_setting_enumerate_values (setting, add_secrets, secrets);
g_hash_table_insert (settings, g_strdup (setting_name), secrets);
return settings;
callback (connection, settings, NULL, user_data);
g_hash_table_destroy (settings);
return TRUE;
}
/**************************************************************/
typedef struct {
NMSysconfigConnection *self;
char *setting_name;
DBusGMethodInvocation *context;
} GetUnixUserInfo;
PolkitSubject *subject;
GCancellable *cancellable;
static GetUnixUserInfo *
get_unix_user_info_new (NMSysconfigConnection *self,
const char *setting_name,
DBusGMethodInvocation *context)
/* Update */
NMConnection *connection;
/* Secrets */
char *setting_name;
char **hints;
gboolean request_new;
} PolkitCall;
static PolkitCall *
polkit_call_new (NMSysconfigConnection *self,
DBusGMethodInvocation *context,
NMConnection *connection,
const char *setting_name,
const char **hints,
gboolean request_new)
{
GetUnixUserInfo *info;
PolkitCall *call;
char *sender;
g_return_val_if_fail (self != NULL, NULL);
g_return_val_if_fail (setting_name != NULL, NULL);
g_return_val_if_fail (context != NULL, NULL);
info = g_malloc0 (sizeof (GetUnixUserInfo));
info->self = self;
info->setting_name = g_strdup (setting_name);
info->context = context;
return info;
call = g_malloc0 (sizeof (PolkitCall));
call->self = self;
call->context = context;
call->cancellable = g_cancellable_new ();
call->connection = connection;
call->setting_name = g_strdup (setting_name);
if (hints)
call->hints = g_strdupv ((char **) hints);
call->request_new = request_new;
sender = dbus_g_method_get_sender (context);
call->subject = polkit_system_bus_name_new (sender);
g_free (sender);
return call;
}
static void
get_unix_user_info_free (gpointer user_data)
polkit_call_free (PolkitCall *call)
{
GetUnixUserInfo *info = user_data;
if (call->connection)
g_object_unref (call->connection);
g_free (call->setting_name);
if (call->hints)
g_strfreev (call->hints);
g_free (info->setting_name);
g_free (info);
g_object_unref (call->subject);
g_object_unref (call->cancellable);
g_free (call);
}
static void
get_unix_user_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
con_update_cb (NMSettingsConnectionInterface *connection,
GError *error,
gpointer user_data)
{
GetUnixUserInfo *info = user_data;
NMSysconfigConnection *self;
NMSysconfigConnectionPrivate *priv;
PolkitCall *call = user_data;
if (error)
dbus_g_method_return_error (call->context, error);
else
dbus_g_method_return (call->context);
polkit_call_free (call);
}
static void
pk_update_cb (GObject *object, GAsyncResult *result, gpointer user_data)
{
PolkitCall *call = user_data;
NMSysconfigConnection *self = call->self;
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
PolkitAuthorizationResult *pk_result;
GError *error = NULL;
guint32 requestor_uid = G_MAXUINT32;
GHashTable *secrets;
GHashTable *settings;
g_return_if_fail (info != NULL);
self = info->self;
priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
if (!dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_UINT, &requestor_uid, G_TYPE_INVALID))
goto error;
/* Non-root users need PolicyKit authorization */
if (requestor_uid != 0) {
if (!check_polkit_privileges (priv->dbus_connection, priv->pol_ctx, info->context, &error))
goto error;
}
secrets = nm_sysconfig_connection_get_secrets (self, info->setting_name, NULL, FALSE, &error);
if (secrets) {
/* success; return secrets to caller */
dbus_g_method_return (info->context, secrets);
g_hash_table_destroy (secrets);
pk_result = polkit_authority_check_authorization_finish (priv->authority,
result,
&error);
/* Some random error happened */
if (error) {
dbus_g_method_return_error (call->context, error);
g_error_free (error);
polkit_call_free (call);
return;
}
if (!error) {
/* Shouldn't happen, but... */
g_set_error (&error, NM_SYSCONFIG_SETTINGS_ERROR,
NM_SYSCONFIG_SETTINGS_ERROR_GENERAL,
"%s", "Could not get secrets from connection (unknown error ocurred)");
/* Caller didn't successfully authenticate */
if (!polkit_authorization_result_get_is_authorized (pk_result)) {
error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
NM_SYSCONFIG_SETTINGS_ERROR_NOT_PRIVILEGED,
"Insufficient privileges.");
dbus_g_method_return_error (call->context, error);
g_error_free (error);
polkit_call_free (call);
goto out;
}
error:
dbus_g_method_return_error (info->context, error);
g_clear_error (&error);
/* Update our settings internally so the update() call will save the new
* ones.
*/
settings = nm_connection_to_hash (call->connection);
if (!nm_connection_replace_settings (NM_CONNECTION (self), settings, &error)) {
/* Shouldn't really happen since we've already validated the settings */
dbus_g_method_return_error (call->context, error);
g_error_free (error);
polkit_call_free (call);
goto out;
}
g_hash_table_destroy (settings);
/* Caller is authenticated, now we can finally try to update */
nm_settings_connection_interface_update (NM_SETTINGS_CONNECTION_INTERFACE (self),
con_update_cb,
call);
out:
g_object_unref (pk_result);
}
static void
service_get_secrets (NMExportedConnection *exported,
const gchar *setting_name,
const gchar **hints,
gboolean request_new,
DBusGMethodInvocation *context)
dbus_update (NMExportedConnection *exported,
GHashTable *new_settings,
DBusGMethodInvocation *context)
{
NMSysconfigConnection *self = NM_SYSCONFIG_CONNECTION (exported);
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
GetUnixUserInfo *info;
PolkitCall *call;
NMConnection *tmp;
GError *error = NULL;
char *sender = NULL;
sender = dbus_g_method_get_sender (context);
if (!sender) {
g_set_error (&error, NM_SYSCONFIG_SETTINGS_ERROR,
NM_SYSCONFIG_SETTINGS_ERROR_GENERAL,
"%s", "Could not determine D-Bus requestor to authorize GetSecrets request");
goto out;
}
if (priv->proxy)
g_object_unref (priv->proxy);
priv->proxy = dbus_g_proxy_new_for_name (priv->dbus_connection,
DBUS_SERVICE_DBUS,
DBUS_PATH_DBUS,
DBUS_INTERFACE_DBUS);
if (!priv->proxy) {
g_set_error (&error, NM_SYSCONFIG_SETTINGS_ERROR,
NM_SYSCONFIG_SETTINGS_ERROR_GENERAL,
"%s", "Could not connect to D-Bus to authorize GetSecrets request");
goto out;
}
info = get_unix_user_info_new (self, setting_name, context);
if (!info) {
g_set_error (&error, NM_SYSCONFIG_SETTINGS_ERROR,
NM_SYSCONFIG_SETTINGS_ERROR_GENERAL,
"%s", "Not enough memory to authorize GetSecrets request");
goto out;
}
dbus_g_proxy_begin_call_with_timeout (priv->proxy, "GetConnectionUnixUser",
get_unix_user_cb,
info,
get_unix_user_info_free,
5000,
G_TYPE_STRING, sender,
G_TYPE_INVALID);
out:
if (error) {
/* Check if the settings are valid first */
tmp = nm_connection_new_from_hash (new_settings, &error);
if (!tmp) {
g_assert (error);
dbus_g_method_return_error (context, error);
g_error_free (error);
return;
}
call = polkit_call_new (self, context, tmp, NULL, NULL, FALSE);
g_assert (call);
polkit_authority_check_authorization (priv->authority,
call->subject,
NM_SYSCONFIG_POLICY_ACTION,
NULL,
POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
call->cancellable,
pk_update_cb,
call);
}
/* GObject */
static void
con_delete_cb (NMSettingsConnectionInterface *connection,
GError *error,
gpointer user_data)
{
PolkitCall *call = user_data;
if (error)
dbus_g_method_return_error (call->context, error);
else
dbus_g_method_return (call->context);
polkit_call_free (call);
}
static void
pk_delete_cb (GObject *object, GAsyncResult *result, gpointer user_data)
{
PolkitCall *call = user_data;
NMSysconfigConnection *self = call->self;
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
PolkitAuthorizationResult *pk_result;
GError *error = NULL;
pk_result = polkit_authority_check_authorization_finish (priv->authority,
result,
&error);
/* Some random error happened */
if (error) {
dbus_g_method_return_error (call->context, error);
g_error_free (error);
polkit_call_free (call);
return;
}
/* Caller didn't successfully authenticate */
if (!polkit_authorization_result_get_is_authorized (pk_result)) {
error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
NM_SYSCONFIG_SETTINGS_ERROR_NOT_PRIVILEGED,
"Insufficient privileges.");
dbus_g_method_return_error (call->context, error);
g_error_free (error);
polkit_call_free (call);
goto out;
}
/* Caller is authenticated, now we can finally try to delete */
nm_settings_connection_interface_delete (NM_SETTINGS_CONNECTION_INTERFACE (self),
con_delete_cb,
call);
out:
g_object_unref (pk_result);
}
static void
dbus_delete (NMExportedConnection *exported,
DBusGMethodInvocation *context)
{
NMSysconfigConnection *self = NM_SYSCONFIG_CONNECTION (exported);
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
PolkitCall *call;
call = polkit_call_new (self, context, NULL, NULL, NULL, FALSE);
g_assert (call);
polkit_authority_check_authorization (priv->authority,
call->subject,
NM_SYSCONFIG_POLICY_ACTION,
NULL,
POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
call->cancellable,
pk_delete_cb,
call);
}
static void
con_secrets_cb (NMSettingsConnectionInterface *connection,
GHashTable *secrets,
GError *error,
gpointer user_data)
{
PolkitCall *call = user_data;
if (error)
dbus_g_method_return_error (call->context, error);
else
dbus_g_method_return (call->context, secrets);
polkit_call_free (call);
}
static void
pk_secrets_cb (GObject *object, GAsyncResult *result, gpointer user_data)
{
PolkitCall *call = user_data;
NMSysconfigConnection *self = call->self;
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
PolkitAuthorizationResult *pk_result;
GError *error = NULL;
pk_result = polkit_authority_check_authorization_finish (priv->authority,
result,
&error);
/* Some random error happened */
if (error) {
dbus_g_method_return_error (call->context, error);
g_error_free (error);
polkit_call_free (call);
return;
}
/* Caller didn't successfully authenticate */
if (!polkit_authorization_result_get_is_authorized (pk_result)) {
error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
NM_SYSCONFIG_SETTINGS_ERROR_NOT_PRIVILEGED,
"Insufficient privileges.");
dbus_g_method_return_error (call->context, error);
g_error_free (error);
polkit_call_free (call);
goto out;
}
/* Caller is authenticated, now we can finally try to update */
nm_settings_connection_interface_get_secrets (NM_SETTINGS_CONNECTION_INTERFACE (self),
call->setting_name,
(const char **) call->hints,
call->request_new,
con_secrets_cb,
call);
out:
g_object_unref (pk_result);
}
static void
dbus_get_secrets (NMExportedConnection *exported,
const gchar *setting_name,
const gchar **hints,
gboolean request_new,
DBusGMethodInvocation *context)
{
NMSysconfigConnection *self = NM_SYSCONFIG_CONNECTION (exported);
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
PolkitCall *call;
call = polkit_call_new (self, context, NULL, setting_name, hints, request_new);
g_assert (call);
polkit_authority_check_authorization (priv->authority,
call->subject,
NM_SYSCONFIG_POLICY_ACTION,
NULL,
POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
call->cancellable,
pk_secrets_cb,
call);
}
/**************************************************************/
static void
settings_connection_interface_init (NMSettingsConnectionInterface *iface)
{
iface->update = update;
iface->delete = do_delete;
iface->get_secrets = get_secrets;
}
static void
nm_sysconfig_connection_init (NMSysconfigConnection *self)
{
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
GError *err = NULL;
priv->dbus_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err);
if (err) {
g_warning ("%s: error getting D-Bus connection: %s",
__func__,
(err && err->message) ? err->message : "(unknown)");
g_error_free (err);
}
priv->pol_ctx = create_polkit_context (&err);
if (!priv->pol_ctx) {
g_warning ("%s: error creating PolicyKit context: %s",
__func__,
(err && err->message) ? err->message : "(unknown)");
}
priv->authority = polkit_authority_get ();
if (!priv->authority)
g_warning ("%s: error creating PolicyKit authority", __func__);
}
static void
@ -317,30 +507,23 @@ dispose (GObject *object)
{
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (object);
if (priv->proxy)
g_object_unref (priv->proxy);
if (priv->pol_ctx)
polkit_context_unref (priv->pol_ctx);
if (priv->dbus_connection)
dbus_g_connection_unref (priv->dbus_connection);
if (priv->authority)
g_object_unref (priv->authority);
G_OBJECT_CLASS (nm_sysconfig_connection_parent_class)->dispose (object);
}
static void
nm_sysconfig_connection_class_init (NMSysconfigConnectionClass *sysconfig_connection_class)
nm_sysconfig_connection_class_init (NMSysconfigConnectionClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (sysconfig_connection_class);
NMExportedConnectionClass *connection_class = NM_EXPORTED_CONNECTION_CLASS (sysconfig_connection_class);
GObjectClass *object_class = G_OBJECT_CLASS (class);
NMExportedConnectionClass *ec_class = NM_EXPORTED_CONNECTION_CLASS (class);
g_type_class_add_private (sysconfig_connection_class, sizeof (NMSysconfigConnectionPrivate));
g_type_class_add_private (class, sizeof (NMSysconfigConnectionPrivate));
/* Virtual methods */
object_class->dispose = dispose;
connection_class->update = update;
connection_class->do_delete = do_delete;
connection_class->service_get_secrets = service_get_secrets;
ec_class->update = dbus_update;
ec_class->delete = dbus_delete;
ec_class->get_secrets = dbus_get_secrets;
}

View file

@ -21,7 +21,8 @@
#ifndef NM_SYSCONFIG_CONNECTION_H
#define NM_SYSCONFIG_CONNECTION_H
#include <nm-settings.h>
#include <nm-connection.h>
#include <nm-exported-connection.h>
G_BEGIN_DECLS
@ -42,13 +43,6 @@ typedef struct {
GType nm_sysconfig_connection_get_type (void);
/* Only for internal NM usage */
GHashTable *nm_sysconfig_connection_get_secrets (NMSysconfigConnection *self,
const gchar *setting_name,
const gchar **hints,
gboolean request_new,
GError **error);
G_END_DECLS
#endif /* NM_SYSCONFIG_CONNECTION_H */

File diff suppressed because it is too large Load diff

View file

@ -27,15 +27,11 @@
#define __NM_SYSCONFIG_SETTINGS_H__
#include <nm-connection.h>
#include <nm-settings.h>
#include "nm-sysconfig-connection.h"
#include "nm-system-config-interface.h"
#include "nm-device.h"
typedef struct _NMSysconfigSettings NMSysconfigSettings;
typedef struct _NMSysconfigSettingsClass NMSysconfigSettingsClass;
#define NM_TYPE_SYSCONFIG_SETTINGS (nm_sysconfig_settings_get_type ())
#define NM_SYSCONFIG_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SYSCONFIG_SETTINGS, NMSysconfigSettings))
#define NM_SYSCONFIG_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SYSCONFIG_SETTINGS, NMSysconfigSettingsClass))
@ -44,21 +40,17 @@ typedef struct _NMSysconfigSettingsClass NMSysconfigSettingsClass;
#define NM_SYSCONFIG_SETTINGS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SYSCONFIG_SETTINGS, NMSysconfigSettingsClass))
#define NM_SYSCONFIG_SETTINGS_UNMANAGED_SPECS "unmanaged-specs"
#define NM_SYSCONFIG_SETTINGS_HOSTNAME "hostname"
#define NM_SYSCONFIG_SETTINGS_CAN_MODIFY "can-modify"
struct _NMSysconfigSettings
{
NMSettings parent_instance;
};
typedef struct {
GObject parent_instance;
} NMSysconfigSettings;
struct _NMSysconfigSettingsClass
{
NMSettingsClass parent_class;
typedef struct {
GObjectClass parent_class;
/* Signals */
void (*properties_changed) (NMSysconfigSettings *settings, GHashTable *properties);
};
void (*properties_changed) (NMSysconfigSettings *self, GHashTable *properties);
} NMSysconfigSettingsClass;
GType nm_sysconfig_settings_get_type (void);
@ -66,34 +58,10 @@ NMSysconfigSettings *nm_sysconfig_settings_new (const char *config_file,
const char *plugins,
GError **error);
/* Registers an exising connection with the settings service */
void nm_sysconfig_settings_add_connection (NMSysconfigSettings *settings,
NMExportedConnection *connection,
gboolean do_export);
void nm_sysconfig_settings_remove_connection (NMSysconfigSettings *settings,
NMExportedConnection *connection,
gboolean do_signal);
NMSystemConfigInterface *nm_sysconfig_settings_get_plugin (NMSysconfigSettings *self,
guint32 capability);
/* Adds a new connection from a hash of that connection's settings,
* potentially saving the new connection to persistent storage.
*/
gboolean nm_sysconfig_settings_add_new_connection (NMSysconfigSettings *self,
GHashTable *hash,
GError **error);
const GSList *nm_sysconfig_settings_get_unmanaged_specs (NMSysconfigSettings *self);
char *nm_sysconfig_settings_get_hostname (NMSysconfigSettings *self);
GSList *nm_sysconfig_settings_list_connections (NMSysconfigSettings *self);
NMSysconfigConnection *nm_sysconfig_settings_get_connection_by_path (NMSysconfigSettings *self,
const char *path);
void nm_sysconfig_settings_device_added (NMSysconfigSettings *self, NMDevice *device);
void nm_sysconfig_settings_device_removed (NMSysconfigSettings *self, NMDevice *device);

View file

@ -66,19 +66,19 @@ interface_init (gpointer g_iface)
G_PARAM_READWRITE));
/* Signals */
g_signal_new ("connection-added",
g_signal_new (NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED,
iface_type,
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMSystemConfigInterface, connection_added),
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
NM_TYPE_EXPORTED_CONNECTION);
NM_TYPE_SETTINGS_CONNECTION_INTERFACE);
g_signal_new ("unmanaged-devices-changed",
g_signal_new (NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED,
iface_type,
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMSystemConfigInterface, unmanaged_devices_changed),
G_STRUCT_OFFSET (NMSystemConfigInterface, unmanaged_specs_changed),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);

View file

@ -25,7 +25,7 @@
#include <glib.h>
#include <glib-object.h>
#include <nm-connection.h>
#include <nm-settings.h>
#include <nm-settings-connection-interface.h>
G_BEGIN_DECLS
@ -61,6 +61,9 @@ GObject * nm_system_config_factory (void);
#define NM_SYSTEM_CONFIG_INTERFACE_CAPABILITIES "capabilities"
#define NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME "hostname"
#define NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED "unmanaged-specs-changed"
#define NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED "connection-added"
typedef enum {
NM_SYSTEM_CONFIG_INTERFACE_CAP_NONE = 0x00000000,
NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS = 0x00000001,
@ -87,8 +90,9 @@ struct _NMSystemConfigInterface {
/* Called when the plugin is loaded to initialize it */
void (*init) (NMSystemConfigInterface *config);
/* Returns the plugins currently known list of connections. The returned
* list is freed by the system settings service.
/* Returns a GSList of objects that implement NMSettingsConnectionInterface
* that represent connections the plugin knows about. The returned list
* is freed by the system settings service.
*/
GSList * (*get_connections) (NMSystemConfigInterface *config);
@ -109,15 +113,18 @@ struct _NMSystemConfigInterface {
/*
* Add a new connection.
*/
gboolean (*add_connection) (NMSystemConfigInterface *config, NMConnection *connection, GError **error);
gboolean (*add_connection) (NMSystemConfigInterface *config,
NMConnection *connection,
GError **error);
/* Signals */
/* Emitted when a new connection has been found by the plugin */
void (*connection_added) (NMSystemConfigInterface *config, NMExportedConnection *connection);
void (*connection_added) (NMSystemConfigInterface *config,
NMSettingsConnectionInterface *connection);
/* Emitted when the list of unmanaged devices changes */
void (*unmanaged_devices_changed) (NMSystemConfigInterface *config);
/* Emitted when the list of unmanaged device specifications changes */
void (*unmanaged_specs_changed) (NMSystemConfigInterface *config);
};
GType nm_system_config_interface_get_type (void);

View file

@ -33,6 +33,7 @@
#include <nm-setting-pppoe.h>
#include <nm-setting-wireless-security.h>
#include <nm-setting-8021x.h>
#include <nm-settings-connection-interface.h>
#include "common.h"
#include "nm-ifcfg-connection.h"
@ -40,7 +41,13 @@
#include "writer.h"
#include "nm-inotify-helper.h"
G_DEFINE_TYPE (NMIfcfgConnection, nm_ifcfg_connection, NM_TYPE_SYSCONFIG_CONNECTION)
static NMSettingsConnectionInterface *parent_settings_connection_iface;
static void settings_connection_interface_init (NMSettingsConnectionInterface *klass);
G_DEFINE_TYPE_EXTENDED (NMIfcfgConnection, nm_ifcfg_connection, NM_TYPE_SYSCONFIG_CONNECTION, 0,
G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_CONNECTION_INTERFACE,
settings_connection_interface_init))
#define NM_IFCFG_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_IFCFG_CONNECTION, NMIfcfgConnectionPrivate))
@ -97,24 +104,32 @@ nm_ifcfg_connection_new (const char *filename,
{
GObject *object;
NMIfcfgConnectionPrivate *priv;
NMConnection *wrapped;
NMConnection *tmp;
char *unmanaged = NULL;
char *keyfile = NULL;
NMInotifyHelper *ih;
GHashTable *settings;
g_return_val_if_fail (filename != NULL, NULL);
wrapped = connection_from_file (filename, NULL, NULL, &unmanaged, &keyfile, error, ignore_error);
if (!wrapped)
tmp = connection_from_file (filename, NULL, NULL, &unmanaged, &keyfile, error, ignore_error);
if (!tmp)
return NULL;
object = (GObject *) g_object_new (NM_TYPE_IFCFG_CONNECTION,
NM_IFCFG_CONNECTION_FILENAME, filename,
NM_IFCFG_CONNECTION_UNMANAGED, unmanaged,
NM_EXPORTED_CONNECTION_CONNECTION, wrapped,
NULL);
if (!object)
goto out;
if (!object) {
g_object_unref (tmp);
return NULL;
}
/* Update our settings with what was read from the file */
settings = nm_connection_to_hash (tmp);
nm_connection_replace_settings (NM_CONNECTION (object), settings, NULL);
g_hash_table_destroy (settings);
g_object_unref (tmp);
priv = NM_IFCFG_CONNECTION_GET_PRIVATE (object);
@ -126,9 +141,7 @@ nm_ifcfg_connection_new (const char *filename,
priv->keyfile = keyfile;
priv->keyfile_wd = nm_inotify_helper_add_watch (ih, keyfile);
out:
g_object_unref (wrapped);
return (NMIfcfgConnection *) object;
return NM_IFCFG_CONNECTION (object);
}
const char *
@ -147,43 +160,51 @@ nm_ifcfg_connection_get_unmanaged_spec (NMIfcfgConnection *self)
return NM_IFCFG_CONNECTION_GET_PRIVATE (self)->unmanaged;
}
gboolean
nm_ifcfg_connection_update (NMIfcfgConnection *self, GHashTable *new_settings, GError **error)
static gboolean
update (NMSettingsConnectionInterface *connection,
NMSettingsConnectionInterfaceUpdateFunc callback,
gpointer user_data)
{
NMExportedConnection *exported = NM_EXPORTED_CONNECTION (self);
NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (exported);
NMConnection *connection;
NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (connection);
GError *error = NULL;
connection = nm_exported_connection_get_connection (exported);
if (!nm_connection_replace_settings (connection, new_settings, error))
if (!writer_update_connection (NM_CONNECTION (connection),
IFCFG_DIR,
priv->filename,
priv->keyfile,
&error)) {
callback (connection, error, user_data);
g_error_free (error);
return FALSE;
}
return writer_update_connection (connection, IFCFG_DIR, priv->filename, priv->keyfile, error);
return parent_settings_connection_iface->update (connection, callback, user_data);
}
static gboolean
update (NMExportedConnection *exported, GHashTable *new_settings, GError **error)
static gboolean
do_delete (NMSettingsConnectionInterface *connection,
NMSettingsConnectionInterfaceDeleteFunc callback,
gpointer user_data)
{
if (!NM_EXPORTED_CONNECTION_CLASS (nm_ifcfg_connection_parent_class)->update (exported, new_settings, error))
return FALSE;
return nm_ifcfg_connection_update (NM_IFCFG_CONNECTION (exported), new_settings, error);
}
static gboolean
do_delete (NMExportedConnection *exported, GError **error)
{
NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (exported);
NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (connection);
g_unlink (priv->filename);
if (priv->keyfile)
g_unlink (priv->keyfile);
return TRUE;
return parent_settings_connection_iface->delete (connection, callback, user_data);
}
/* GObject */
static void
settings_connection_interface_init (NMSettingsConnectionInterface *iface)
{
parent_settings_connection_iface = g_type_interface_peek_parent (iface);
iface->update = update;
iface->delete = do_delete;
}
static void
nm_ifcfg_connection_init (NMIfcfgConnection *connection)
{
@ -193,14 +214,11 @@ static void
finalize (GObject *object)
{
NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (object);
NMConnection *wrapped;
NMInotifyHelper *ih;
g_free (priv->udi);
wrapped = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (object));
if (wrapped)
nm_connection_clear_secrets (wrapped);
nm_connection_clear_secrets (NM_CONNECTION (object));
ih = nm_inotify_helper_get ();
@ -267,7 +285,6 @@ static void
nm_ifcfg_connection_class_init (NMIfcfgConnectionClass *ifcfg_connection_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (ifcfg_connection_class);
NMExportedConnectionClass *connection_class = NM_EXPORTED_CONNECTION_CLASS (ifcfg_connection_class);
g_type_class_add_private (ifcfg_connection_class, sizeof (NMIfcfgConnectionPrivate));
@ -276,9 +293,6 @@ nm_ifcfg_connection_class_init (NMIfcfgConnectionClass *ifcfg_connection_class)
object_class->get_property = get_property;
object_class->finalize = finalize;
connection_class->update = update;
connection_class->do_delete = do_delete;
/* Properties */
g_object_class_install_property
(object_class, PROP_FILENAME,

View file

@ -88,7 +88,7 @@ connection_unmanaged_changed (NMIfcfgConnection *connection,
GParamSpec *pspec,
gpointer user_data)
{
g_signal_emit_by_name (SC_PLUGIN_IFCFG (user_data), "unmanaged-devices-changed");
g_signal_emit_by_name (SC_PLUGIN_IFCFG (user_data), NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED);
}
static void
@ -117,13 +117,10 @@ read_one_connection (SCPluginIfcfg *plugin, const char *filename)
connection = nm_ifcfg_connection_new (filename, &error, &ignore_error);
if (connection) {
NMConnection *wrapped;
NMSettingConnection *s_con;
const char *cid;
wrapped = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (connection));
g_assert (wrapped);
s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (wrapped, NM_TYPE_SETTING_CONNECTION));
s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (connection), NM_TYPE_SETTING_CONNECTION);
g_assert (s_con);
cid = nm_setting_connection_get_id (s_con);
@ -137,7 +134,7 @@ read_one_connection (SCPluginIfcfg *plugin, const char *filename)
if (nm_ifcfg_connection_get_unmanaged_spec (connection)) {
PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "Ignoring connection '%s' and its "
"device because NM_CONTROLLED was false.", cid);
g_signal_emit_by_name (plugin, "unmanaged-devices-changed");
g_signal_emit_by_name (plugin, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED);
} else {
/* Wait for the connection to become unmanaged once it knows the
* UDI of it's device, if/when the device gets plugged in.
@ -227,6 +224,13 @@ read_connections (SCPluginIfcfg *plugin)
/* Monitoring */
static void
ignore_cb (NMSettingsConnectionInterface *connection,
GError *error,
gpointer user_data)
{
}
static void
connection_changed_handler (SCPluginIfcfg *plugin,
const char *path,
@ -234,7 +238,7 @@ connection_changed_handler (SCPluginIfcfg *plugin,
gboolean *do_remove,
gboolean *do_new)
{
NMIfcfgConnection *tmp;
NMIfcfgConnection *new;
GError *error = NULL;
GHashTable *settings;
gboolean ignore_error = FALSE;
@ -248,8 +252,8 @@ connection_changed_handler (SCPluginIfcfg *plugin,
PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "updating %s", path);
tmp = (NMIfcfgConnection *) nm_ifcfg_connection_new (path, &error, &ignore_error);
if (!tmp) {
new = (NMIfcfgConnection *) nm_ifcfg_connection_new (path, &error, &ignore_error);
if (!new) {
/* errors reading connection; remove it */
if (!ignore_error) {
PLUGIN_WARN (IFCFG_PLUGIN_NAME, " error: %s",
@ -265,7 +269,7 @@ connection_changed_handler (SCPluginIfcfg *plugin,
/* Successfully read connection changes */
old_unmanaged = nm_ifcfg_connection_get_unmanaged_spec (NM_IFCFG_CONNECTION (connection));
new_unmanaged = nm_ifcfg_connection_get_unmanaged_spec (NM_IFCFG_CONNECTION (tmp));
new_unmanaged = nm_ifcfg_connection_get_unmanaged_spec (NM_IFCFG_CONNECTION (new));
if (new_unmanaged) {
if (!old_unmanaged) {
@ -273,16 +277,11 @@ connection_changed_handler (SCPluginIfcfg *plugin,
*do_remove = *do_new = TRUE;
}
} else {
NMConnection *old_wrapped, *new_wrapped;
new_wrapped = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (tmp));
old_wrapped = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (connection));
if (old_unmanaged) { /* now managed */
NMSettingConnection *s_con;
const char *cid;
s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (new_wrapped, NM_TYPE_SETTING_CONNECTION));
s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (new), NM_TYPE_SETTING_CONNECTION);
g_assert (s_con);
cid = nm_setting_connection_get_id (s_con);
@ -290,25 +289,30 @@ connection_changed_handler (SCPluginIfcfg *plugin,
PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "Managing connection '%s' and its "
"device because NM_CONTROLLED was true.", cid);
g_signal_emit_by_name (plugin, "connection-added", connection);
g_signal_emit_by_name (plugin, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, connection);
}
/* Only update if different */
if (!nm_connection_compare (new_wrapped, old_wrapped, NM_SETTING_COMPARE_FLAG_EXACT)) {
settings = nm_connection_to_hash (new_wrapped);
if (!nm_ifcfg_connection_update (connection, settings, &error)) {
if (!nm_connection_compare (NM_CONNECTION (new),
NM_CONNECTION (connection),
NM_SETTING_COMPARE_FLAG_EXACT)) {
settings = nm_connection_to_hash (NM_CONNECTION (new));
if (!nm_connection_replace_settings (NM_CONNECTION (connection), settings, &error)) {
PLUGIN_WARN (IFCFG_PLUGIN_NAME, " error updating: %s",
(error && error->message) ? error->message : "(unknown)");
g_clear_error (&error);
}
g_hash_table_destroy (settings);
nm_settings_connection_interface_update (NM_SETTINGS_CONNECTION_INTERFACE (connection),
ignore_cb,
NULL);
}
/* Update unmanaged status */
g_object_set (connection, "unmanaged", new_unmanaged, NULL);
g_signal_emit_by_name (plugin, "unmanaged-devices-changed");
g_signal_emit_by_name (plugin, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED);
}
g_object_unref (tmp);
g_object_unref (new);
}
static void
@ -330,18 +334,18 @@ handle_connection_remove_or_new (SCPluginIfcfg *plugin,
unmanaged = nm_ifcfg_connection_get_unmanaged_spec (connection);
g_hash_table_remove (priv->connections, path);
nm_exported_connection_signal_removed (NM_EXPORTED_CONNECTION (connection));
g_signal_emit_by_name (connection, "removed");
/* Emit unmanaged changes _after_ removing the connection */
if (unmanaged)
g_signal_emit_by_name (plugin, "unmanaged-devices-changed");
g_signal_emit_by_name (plugin, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED);
}
if (do_new) {
connection = read_one_connection (plugin, path);
if (connection) {
if (!nm_ifcfg_connection_get_unmanaged_spec (NM_IFCFG_CONNECTION (connection)))
g_signal_emit_by_name (plugin, "connection-added", connection);
if (!nm_ifcfg_connection_get_unmanaged_spec (connection))
g_signal_emit_by_name (plugin, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, connection);
}
}
}

View file

@ -190,7 +190,7 @@ read_connection (SCPluginIfcfg *self, GUdevDevice *device, NMDeviceType dev_type
if (address && (strlen (address) == 17)) {
spec = g_strdup_printf ("mac:%s", address);
g_hash_table_insert (priv->unmanaged_specs, GUINT_TO_POINTER (ifindex), spec);
g_signal_emit_by_name (self, "unmanaged-devices-changed");
g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED);
} else
PLUGIN_WARN (IFCFG_PLUGIN_NAME, " (%s) error getting hardware address", iface);
} else {
@ -201,7 +201,7 @@ read_connection (SCPluginIfcfg *self, GUdevDevice *device, NMDeviceType dev_type
g_hash_table_insert (priv->connections,
GUINT_TO_POINTER (ifindex),
connection);
g_signal_emit_by_name (self, "connection-added", connection);
g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, connection);
}
}
}
@ -281,7 +281,7 @@ handle_uevent (GUdevClient *client,
ifindex = (guint32) g_udev_device_get_property_as_uint64 (device, "IFINDEX");
if (g_hash_table_remove (priv->unmanaged_specs, GUINT_TO_POINTER (ifindex)))
g_signal_emit_by_name (self, "unmanaged-devices-changed");
g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED);
exported = (NMExportedConnection *) g_hash_table_lookup (priv->connections,
GUINT_TO_POINTER (ifindex));

View file

@ -255,7 +255,7 @@ udev_device_added (SCPluginIfupdown *self, GUdevDevice *device)
g_hash_table_insert (priv->well_known_ifaces, g_strdup (iface), g_object_ref (device));
if (ALWAYS_UNMANAGE || priv->unmanage_well_known)
g_signal_emit_by_name (G_OBJECT (self), "unmanaged-devices-changed");
g_signal_emit_by_name (G_OBJECT (self), NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED);
else
bind_device_to_connection (self, device, exported);
}
@ -278,7 +278,7 @@ udev_device_removed (SCPluginIfupdown *self, GUdevDevice *device)
return;
if (ALWAYS_UNMANAGE || priv->unmanage_well_known)
g_signal_emit_by_name (G_OBJECT (self), "unmanaged-devices-changed");
g_signal_emit_by_name (G_OBJECT (self), NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED);
}
static void

View file

@ -34,7 +34,7 @@
#include <string.h>
#include <arpa/inet.h>
#include <netinet/ether.h>
#include <nm-settings.h>
#include <nm-settings-interface.h>
#include "nm-dbus-glib-types.h"
#include "writer.h"
@ -437,14 +437,18 @@ write_connection (NMConnection *connection,
g_file_set_contents (path, data, len, error);
if (chown (path, owner_uid, owner_grp) < 0) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INTERNAL_ERROR,
g_set_error (error,
NM_SETTINGS_INTERFACE_ERROR,
NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR,
"%s.%d: error chowning '%s': %d", __FILE__, __LINE__,
path, errno);
unlink (path);
} else {
err = chmod (path, S_IRUSR | S_IWUSR);
if (err) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INTERNAL_ERROR,
g_set_error (error,
NM_SETTINGS_INTERFACE_ERROR,
NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR,
"%s.%d: error setting permissions on '%s': %d", __FILE__,
__LINE__, path, errno);
unlink (path);

View file

@ -22,16 +22,22 @@
#include <string.h>
#include <glib/gstdio.h>
#include <NetworkManager.h>
#include <nm-settings.h>
#include <nm-setting-connection.h>
#include <nm-utils.h>
#include <nm-settings-connection-interface.h>
#include "nm-dbus-glib-types.h"
#include "nm-keyfile-connection.h"
#include "reader.h"
#include "writer.h"
G_DEFINE_TYPE (NMKeyfileConnection, nm_keyfile_connection, NM_TYPE_SYSCONFIG_CONNECTION)
static NMSettingsConnectionInterface *parent_settings_connection_iface;
static void settings_connection_interface_init (NMSettingsConnectionInterface *klass);
G_DEFINE_TYPE_EXTENDED (NMKeyfileConnection, nm_keyfile_connection, NM_TYPE_SYSCONFIG_CONNECTION, 0,
G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_CONNECTION_INTERFACE,
settings_connection_interface_init))
#define NM_KEYFILE_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_KEYFILE_CONNECTION, NMKeyfileConnectionPrivate))
@ -65,50 +71,52 @@ nm_keyfile_connection_get_filename (NMKeyfileConnection *self)
}
static gboolean
update (NMExportedConnection *exported,
GHashTable *new_settings,
GError **error)
update (NMSettingsConnectionInterface *connection,
NMSettingsConnectionInterfaceUpdateFunc callback,
gpointer user_data)
{
NMKeyfileConnectionPrivate *priv = NM_KEYFILE_CONNECTION_GET_PRIVATE (exported);
NMKeyfileConnectionPrivate *priv = NM_KEYFILE_CONNECTION_GET_PRIVATE (connection);
char *filename = NULL;
GError *error = NULL;
gboolean success;
success = NM_EXPORTED_CONNECTION_CLASS (nm_keyfile_connection_parent_class)->update (exported, new_settings, error);
if (success) {
NMConnection *connection;
char *filename = NULL;
connection = nm_exported_connection_get_connection (exported);
success = nm_connection_replace_settings (connection, new_settings, error);
if (success) {
success = write_connection (connection, KEYFILE_DIR, 0, 0, &filename, error);
if (success && filename && strcmp (priv->filename, filename)) {
/* Update the filename if it changed */
g_free (priv->filename);
priv->filename = filename;
} else
g_free (filename);
}
success = write_connection (NM_CONNECTION (connection), KEYFILE_DIR, 0, 0, &filename, &error);
if (success && filename && strcmp (priv->filename, filename)) {
/* Update the filename if it changed */
g_free (priv->filename);
priv->filename = filename;
success = parent_settings_connection_iface->update (connection, callback, user_data);
} else {
callback (connection, error, user_data);
g_error_free (error);
g_free (filename);
}
return success;
}
static gboolean
do_delete (NMExportedConnection *exported, GError **err)
static gboolean
do_delete (NMSettingsConnectionInterface *connection,
NMSettingsConnectionInterfaceDeleteFunc callback,
gpointer user_data)
{
NMKeyfileConnectionPrivate *priv = NM_KEYFILE_CONNECTION_GET_PRIVATE (exported);
gboolean success;
NMKeyfileConnectionPrivate *priv = NM_KEYFILE_CONNECTION_GET_PRIVATE (connection);
success = NM_EXPORTED_CONNECTION_CLASS (nm_keyfile_connection_parent_class)->do_delete (exported, err);
g_unlink (priv->filename);
if (success)
g_unlink (priv->filename);
return success;
return parent_settings_connection_iface->delete (connection, callback, user_data);
}
/* GObject */
static void
settings_connection_interface_init (NMSettingsConnectionInterface *iface)
{
parent_settings_connection_iface = g_type_interface_peek_parent (iface);
iface->update = update;
iface->delete = do_delete;
}
static void
nm_keyfile_connection_init (NMKeyfileConnection *connection)
{
@ -121,8 +129,9 @@ constructor (GType type,
{
GObject *object;
NMKeyfileConnectionPrivate *priv;
NMConnection *wrapped;
NMSettingConnection *s_con;
NMConnection *tmp;
GHashTable *settings;
object = G_OBJECT_CLASS (nm_keyfile_connection_parent_class)->constructor (type, n_construct_params, construct_params);
@ -131,17 +140,21 @@ constructor (GType type,
priv = NM_KEYFILE_CONNECTION_GET_PRIVATE (object);
if (!priv->filename) {
g_warning ("Keyfile file name not provided.");
goto err;
}
g_assert (priv->filename);
wrapped = connection_from_file (priv->filename);
if (!wrapped)
goto err;
tmp = connection_from_file (priv->filename);
if (!tmp) {
g_object_unref (object);
return NULL;
}
settings = nm_connection_to_hash (tmp);
nm_connection_replace_settings (NM_CONNECTION (object), settings, NULL);
g_hash_table_destroy (settings);
g_object_unref (tmp);
/* if for some reason the connection didn't have a UUID, add one */
s_con = (NMSettingConnection *) nm_connection_get_setting (wrapped, NM_TYPE_SETTING_CONNECTION);
s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (object), NM_TYPE_SETTING_CONNECTION);
if (s_con && !nm_setting_connection_get_uuid (s_con)) {
GError *error = NULL;
char *uuid;
@ -150,23 +163,16 @@ constructor (GType type,
g_object_set (s_con, NM_SETTING_CONNECTION_UUID, uuid, NULL);
g_free (uuid);
if (!write_connection (wrapped, KEYFILE_DIR, 0, 0, NULL, &error)) {
if (!write_connection (NM_CONNECTION (object), KEYFILE_DIR, 0, 0, NULL, &error)) {
g_warning ("Couldn't update connection %s with a UUID: (%d) %s",
nm_setting_connection_get_id (s_con), error ? error->code : 0,
error ? error->message : "unknown");
nm_setting_connection_get_id (s_con),
error ? error->code : 0,
(error && error->message) ? error->message : "unknown");
g_error_free (error);
}
}
g_object_set (object, NM_EXPORTED_CONNECTION_CONNECTION, wrapped, NULL);
g_object_unref (wrapped);
return object;
err:
g_object_unref (object);
return NULL;
}
static void
@ -174,6 +180,8 @@ finalize (GObject *object)
{
NMKeyfileConnectionPrivate *priv = NM_KEYFILE_CONNECTION_GET_PRIVATE (object);
nm_connection_clear_secrets (NM_CONNECTION (object));
g_free (priv->filename);
G_OBJECT_CLASS (nm_keyfile_connection_parent_class)->finalize (object);
@ -216,7 +224,6 @@ static void
nm_keyfile_connection_class_init (NMKeyfileConnectionClass *keyfile_connection_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (keyfile_connection_class);
NMExportedConnectionClass *connection_class = NM_EXPORTED_CONNECTION_CLASS (keyfile_connection_class);
g_type_class_add_private (keyfile_connection_class, sizeof (NMKeyfileConnectionPrivate));
@ -226,9 +233,6 @@ nm_keyfile_connection_class_init (NMKeyfileConnectionClass *keyfile_connection_c
object_class->get_property = get_property;
object_class->finalize = finalize;
connection_class->update = update;
connection_class->do_delete = do_delete;
/* Properties */
g_object_class_install_property
(object_class, PROP_FILENAME,

View file

@ -112,15 +112,13 @@ find_by_uuid (gpointer key, gpointer data, gpointer user_data)
{
NMKeyfileConnection *keyfile = NM_KEYFILE_CONNECTION (data);
FindByUUIDInfo *info = user_data;
NMConnection *connection;
NMSettingConnection *s_con;
const char *uuid;
if (info->found)
return;
connection = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (keyfile));
s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (keyfile), NM_TYPE_SETTING_CONNECTION);
uuid = s_con ? nm_setting_connection_get_uuid (s_con) : NULL;
if (uuid && !strcmp (info->uuid, uuid))
@ -128,17 +126,15 @@ find_by_uuid (gpointer key, gpointer data, gpointer user_data)
}
static void
update_connection_settings (NMExportedConnection *orig,
NMExportedConnection *new)
update_connection_settings (NMConnection *orig,
NMConnection *new)
{
NMConnection *wrapped;
GHashTable *new_settings;
GError *error = NULL;
new_settings = nm_connection_to_hash (nm_exported_connection_get_connection (new));
wrapped = nm_exported_connection_get_connection (orig);
if (nm_connection_replace_settings (wrapped, new_settings, &error))
nm_exported_connection_signal_updated (orig, new_settings);
new_settings = nm_connection_to_hash (new);
if (nm_connection_replace_settings (orig, new_settings, &error))
nm_settings_connection_interface_emit_updated (NM_SETTINGS_CONNECTION_INTERFACE (orig));
else {
g_warning ("%s: '%s' / '%s' invalid: %d",
__func__,
@ -146,7 +142,7 @@ update_connection_settings (NMExportedConnection *orig,
(error && error->message) ? error->message : "(none)",
error ? error->code : -1);
g_clear_error (&error);
nm_exported_connection_signal_removed (orig);
g_signal_emit_by_name (orig, "removed");
}
g_hash_table_destroy (new_settings);
@ -175,7 +171,7 @@ dir_changed (GFileMonitor *monitor,
/* Removing from the hash table should drop the last reference */
g_object_ref (connection);
g_hash_table_remove (priv->hash, name);
nm_exported_connection_signal_removed (NM_EXPORTED_CONNECTION (connection));
g_signal_emit_by_name (connection, "removed");
g_object_unref (connection);
}
break;
@ -183,18 +179,17 @@ dir_changed (GFileMonitor *monitor,
case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
if (connection) {
/* Update */
NMExportedConnection *tmp;
NMKeyfileConnection *tmp;
tmp = (NMExportedConnection *) nm_keyfile_connection_new (name);
tmp = (NMKeyfileConnection *) nm_keyfile_connection_new (name);
if (tmp) {
update_connection_settings (NM_EXPORTED_CONNECTION (connection), tmp);
update_connection_settings (NM_CONNECTION (connection), NM_CONNECTION (tmp));
g_object_unref (tmp);
}
} else {
/* New */
connection = nm_keyfile_connection_new (name);
if (connection) {
NMConnection *tmp;
NMSettingConnection *s_con;
const char *connection_uuid;
NMKeyfileConnection *found = NULL;
@ -202,8 +197,7 @@ dir_changed (GFileMonitor *monitor,
/* Connection renames will show up as different files but with
* the same UUID. Try to find the original connection.
*/
tmp = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (connection));
s_con = (NMSettingConnection *) nm_connection_get_setting (tmp, NM_TYPE_SETTING_CONNECTION);
s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (connection), NM_TYPE_SETTING_CONNECTION);
connection_uuid = s_con ? nm_setting_connection_get_uuid (s_con) : NULL;
if (connection_uuid) {
@ -228,8 +222,8 @@ dir_changed (GFileMonitor *monitor,
/* Updating settings should update the NMKeyfileConnection's
* filename property too.
*/
update_connection_settings (NM_EXPORTED_CONNECTION (found),
NM_EXPORTED_CONNECTION (connection));
update_connection_settings (NM_CONNECTION (found),
NM_CONNECTION (connection));
/* Re-insert the connection back into the hash with the new filename */
g_hash_table_insert (priv->hash,
@ -242,7 +236,7 @@ dir_changed (GFileMonitor *monitor,
g_hash_table_insert (priv->hash,
(gpointer) nm_keyfile_connection_get_filename (connection),
connection);
g_signal_emit_by_name (config, "connection-added", connection);
g_signal_emit_by_name (config, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, connection);
}
}
}
@ -269,7 +263,7 @@ conf_file_changed (GFileMonitor *monitor,
case G_FILE_MONITOR_EVENT_DELETED:
case G_FILE_MONITOR_EVENT_CREATED:
case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
g_signal_emit_by_name (self, "unmanaged-devices-changed");
g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED);
/* hostname */
tmp = plugin_get_hostname (self);