Merge commit 'origin/polkit1'

This commit is contained in:
Dan Williams 2009-08-26 12:18:30 -05:00
commit 0ea50e2a92
58 changed files with 4698 additions and 3391 deletions

View file

@ -213,42 +213,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

@ -53,7 +53,7 @@
<signal name="Removed">
<tp:docstring>
Emitted when this settings object was removed. FIXME: Is this emitted after it was removed or when it is about to be removed? If after removed, then different semantics to Device removed. if prior to removal, should be called AboutToBeRemoved.
Emitted when this connection has been deleted/removed. After receipt of this signal, the object no longer exists.
</tp:docstring>
</signal>

View file

@ -6,19 +6,6 @@
Implemented by the system settings service to provide additional settings to NetworkManager.
</tp:docstring>
<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 properties.
</tp:docstring>
</arg>
</method>
<method name="SaveHostname">
<tp:docstring>
Save the hostname to persistent configuration.
@ -52,6 +39,43 @@
</arg>
</signal>
<signal name="CheckPermissions">
<tp:docstring>
Emitted when system authorization details change, indicating that clients may wish to recheck permissions with GetPermissions.
</tp:docstring>
</signal>
<method name="GetPermissions">
<tp:docstring>
Returns a bitfield indicating certain operations the caller is permitted to perform. Some of these operations may require authorization by the user.
</tp:docstring>
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_settings_get_permissions"/>
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="permissions" type="u" direction="out" tp:type="NM_SETTINGS_SYSTEM_PERMISSIONS">
<tp:docstring>
A bitfield of permitted operations. Some of these operations may require the user to authorize via password entry or other means.
</tp:docstring>
</arg>
</method>
<tp:flags name="NM_SETTINGS_SYSTEM_PERMISSIONS" value-prefix="NM_SETTINGS_SYSTEM_PERMISSION" type="u">
<tp:flag suffix="NONE" value="0x0">
<tp:docstring>No permissions.</tp:docstring>
</tp:flag>
<tp:flag suffix="CONNECTION_MODIFY" value="0x1">
<tp:docstring>Can modify/add/delete connections.</tp:docstring>
</tp:flag>
<tp:flag suffix="WIFI_SHARING_PROTECTED" value="0x2">
<tp:docstring>Can share connections via a encrypted user-created WiFi network.</tp:docstring>
</tp:flag>
<tp:flag suffix="WIFI_SHARING_OPEN" value="0x4">
<tp:docstring>Can share connections via a open/unencrypted user-created WiFi network.</tp:docstring>
</tp:flag>
<tp:flag suffix="HOSTNAME_MODIFY" value="0x8">
<tp:docstring>Can modify the persistent system hostname.</tp:docstring>
</tp:flag>
</tp:flags>
</interface>
</node>

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>
@ -28,5 +41,7 @@
</tp:docstring>
</arg>
</signal>
</interface>
</node>

View file

@ -42,7 +42,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 \
@ -51,11 +50,16 @@ 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-ip6-config.h
nm-ip6-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 \
@ -71,7 +75,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 \
@ -81,11 +84,17 @@ 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-ip6-config.c
nm-ip6-config.c \
nm-remote-connection.c \
nm-remote-connection-private.h \
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;
@ -86,14 +84,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;
@ -117,9 +110,33 @@ 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_export_connection;
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_get_permissions;
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,274 @@
/* -*- 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-setting-connection.h>
#include "nm-exported-connection.h"
#include "nm-settings-interface.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"
static void settings_connection_interface_init (NMSettingsConnectionInterface *class);
G_DEFINE_TYPE_EXTENDED (NMExportedConnection, nm_exported_connection, NM_TYPE_CONNECTION, 0,
G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_CONNECTION_INTERFACE,
settings_connection_interface_init))
#define NM_EXPORTED_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
NM_TYPE_EXPORTED_CONNECTION, \
NMExportedConnectionPrivate))
typedef struct {
gboolean foo;
} NMExportedConnectionPrivate;
/**************************************************************/
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
check_writable (NMConnection *connection, GError **error)
{
NMSettingConnection *s_con;
g_return_val_if_fail (connection != NULL, FALSE);
g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
s_con = (NMSettingConnection *) nm_connection_get_setting (connection,
NM_TYPE_SETTING_CONNECTION);
if (!s_con) {
g_set_error_literal (error,
NM_SETTINGS_INTERFACE_ERROR,
NM_SETTINGS_INTERFACE_ERROR_INVALID_CONNECTION,
"Connection did not have required 'connection' setting");
return FALSE;
}
/* If the connection is read-only, that has to be changed at the source of
* the problem (ex a system settings plugin that can't write connections out)
* instead of over D-Bus.
*/
if (nm_setting_connection_get_read_only (s_con)) {
g_set_error_literal (error,
NM_SETTINGS_INTERFACE_ERROR,
NM_SETTINGS_INTERFACE_ERROR_READ_ONLY_CONNECTION,
"Connection is read-only");
return FALSE;
}
return TRUE;
}
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 gboolean
update (NMSettingsConnectionInterface *connection,
NMSettingsConnectionInterfaceUpdateFunc callback,
gpointer user_data)
{
nm_settings_connection_interface_emit_updated (connection);
callback (connection, NULL, user_data);
return TRUE;
}
static void
impl_exported_connection_update (NMExportedConnection *self,
GHashTable *new_settings,
DBusGMethodInvocation *context)
{
NMConnection *tmp;
GError *error = NULL;
/* If the connection is read-only, that has to be changed at the source of
* the problem (ex a system settings plugin that can't write connections out)
* instead of over D-Bus.
*/
if (!check_writable (NM_CONNECTION (self), &error)) {
dbus_g_method_return_error (context, error);
g_error_free (error);
return;
}
/* 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 (NM_SETTINGS_INTERFACE_ERROR,
NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR,
"%s: %s:%d update() unimplemented", __func__, __FILE__, __LINE__);
dbus_g_method_return_error (context, error);
g_error_free (error);
}
}
static gboolean
do_delete (NMSettingsConnectionInterface *connection,
NMSettingsConnectionInterfaceDeleteFunc callback,
gpointer user_data)
{
g_signal_emit_by_name (connection, "removed");
callback (connection, NULL, user_data);
return TRUE;
}
static void
impl_exported_connection_delete (NMExportedConnection *self,
DBusGMethodInvocation *context)
{
GError *error = NULL;
if (!check_writable (NM_CONNECTION (self), &error)) {
dbus_g_method_return_error (context, error);
g_error_free (error);
return;
}
if (NM_EXPORTED_CONNECTION_GET_CLASS (self)->delete)
NM_EXPORTED_CONNECTION_GET_CLASS (self)->delete (self, context);
else {
error = g_error_new (NM_SETTINGS_INTERFACE_ERROR,
NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR,
"%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);
}
}
/**************************************************************/
static void
settings_connection_interface_init (NMSettingsConnectionInterface *iface)
{
iface->update = update;
iface->delete = do_delete;
}
/**
* nm_exported_connection_new:
* @scope: the Connection scope (either user or system)
*
* 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 (NMConnectionScope scope)
{
g_return_val_if_fail (scope != NM_CONNECTION_SCOPE_UNKNOWN, NULL);
return (NMExportedConnection *) g_object_new (NM_TYPE_EXPORTED_CONNECTION,
NM_CONNECTION_SCOPE, scope,
NULL);
}
static void
nm_exported_connection_init (NMExportedConnection *self)
{
}
static void
nm_exported_connection_class_init (NMExportedConnectionClass *class)
{
g_type_class_add_private (class, sizeof (NMExportedConnectionPrivate));
/* Virtual methods */
class->get_settings = real_get_settings;
dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (class),
&dbus_glib_nm_exported_connection_object_info);
}

View file

@ -0,0 +1,66 @@
/* -*- 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))
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 (NMConnectionScope scope);
G_END_DECLS
#endif /* NM_EXPORTED_CONNECTION_H */

View file

@ -0,0 +1,35 @@
/* -*- 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) 2009 Red Hat, Inc.
*/
#ifndef __NM_REMOTE_CONNECTION_PRIVATE_H__
#define __NM_REMOTE_CONNECTION_PRIVATE_H__
#define NM_REMOTE_CONNECTION_INIT_RESULT "init-result"
typedef enum {
NM_REMOTE_CONNECTION_INIT_RESULT_UNKNOWN = 0,
NM_REMOTE_CONNECTION_INIT_RESULT_SUCCESS,
NM_REMOTE_CONNECTION_INIT_RESULT_ERROR
} NMRemoteConnectionInitResult;
#endif /* __NM_REMOTE_CONNECTION_PRIVATE__ */

View file

@ -0,0 +1,437 @@
/* -*- 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-remote-connection-private.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,
PROP_INIT_RESULT,
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;
NMRemoteConnectionInitResult init_result;
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;
NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self);
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);
priv->init_result = NM_REMOTE_CONNECTION_INIT_RESULT_ERROR;
g_object_notify (G_OBJECT (self), NM_REMOTE_CONNECTION_INIT_RESULT);
} else {
replace_settings (self, new_settings);
g_hash_table_destroy (new_settings);
priv->init_result = NM_REMOTE_CONNECTION_INIT_RESULT_SUCCESS;
g_object_notify (G_OBJECT (self), NM_REMOTE_CONNECTION_INIT_RESULT);
}
}
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_INIT_RESULT:
g_value_set_uint (value, priv->init_result);
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_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property
(object_class, PROP_INIT_RESULT,
g_param_spec_uint (NM_REMOTE_CONNECTION_INIT_RESULT,
"Initialization result (PRIVATE)",
"Initialization result (PRIVATE)",
NM_REMOTE_CONNECTION_INIT_RESULT_UNKNOWN,
NM_REMOTE_CONNECTION_INIT_RESULT_ERROR,
NM_REMOTE_CONNECTION_INIT_RESULT_UNKNOWN,
G_PARAM_READABLE));
}

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,369 @@
/* -*- 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;
NMSettingsSystemPermissions permissions;
gboolean have_permissions;
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);
}
typedef struct {
NMSettingsSystemInterface *settings;
NMSettingsSystemSaveHostnameFunc callback;
gpointer callback_data;
} SaveHostnameInfo;
static void
save_hostname_cb (DBusGProxy *proxy,
DBusGProxyCall *call,
gpointer user_data)
{
SaveHostnameInfo *info = user_data;
GError *error = NULL;
dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID);
info->callback (info->settings, error, info->callback_data);
g_clear_error (&error);
}
static gboolean
save_hostname (NMSettingsSystemInterface *settings,
const char *hostname,
NMSettingsSystemSaveHostnameFunc callback,
gpointer user_data)
{
NMRemoteSettingsSystem *self = NM_REMOTE_SETTINGS_SYSTEM (settings);
NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (self);
SaveHostnameInfo *info;
info = g_malloc0 (sizeof (SaveHostnameInfo));
info->settings = settings;
info->callback = callback;
info->callback_data = user_data;
dbus_g_proxy_begin_call (priv->proxy, "SaveHostname",
save_hostname_cb,
info,
g_free,
G_TYPE_STRING, hostname ? hostname : "",
G_TYPE_INVALID);
return TRUE;
}
typedef struct {
NMSettingsSystemInterface *settings;
NMSettingsSystemGetPermissionsFunc callback;
gpointer callback_data;
} GetPermissionsInfo;
static void
get_permissions_cb (DBusGProxy *proxy,
DBusGProxyCall *call,
gpointer user_data)
{
GetPermissionsInfo *info = user_data;
NMRemoteSettingsSystem *self = NM_REMOTE_SETTINGS_SYSTEM (info->settings);
NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (self);
NMSettingsSystemPermissions permissions = NM_SETTINGS_SYSTEM_PERMISSION_NONE;
GError *error = NULL;
dbus_g_proxy_end_call (proxy, call, &error,
G_TYPE_UINT, &permissions,
G_TYPE_INVALID);
priv->permissions = permissions;
priv->have_permissions = !error;
info->callback (info->settings, permissions, error, info->callback_data);
g_clear_error (&error);
}
static gboolean
get_permissions (NMSettingsSystemInterface *settings,
NMSettingsSystemGetPermissionsFunc callback,
gpointer user_data)
{
NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (settings);
GetPermissionsInfo *info;
/* Skip D-Bus if we already have permissions */
if (priv->have_permissions) {
callback (settings, priv->permissions, NULL, user_data);
return TRUE;
}
/* Otherwise fetch them from NM */
info = g_malloc0 (sizeof (GetPermissionsInfo));
info->settings = settings;
info->callback = callback;
info->callback_data = user_data;
dbus_g_proxy_begin_call (priv->proxy, "GetPermissions",
get_permissions_cb,
info,
g_free,
G_TYPE_INVALID);
return TRUE;
}
static void
check_permissions_cb (DBusGProxy *proxy, gpointer user_data)
{
NMRemoteSettingsSystem *self = NM_REMOTE_SETTINGS_SYSTEM (user_data);
NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (self);
/* Permissions need to be re-fetched */
priv->have_permissions = FALSE;
g_signal_emit_by_name (self, NM_SETTINGS_SYSTEM_INTERFACE_CHECK_PERMISSIONS);
}
/****************************************************************/
static void
settings_system_interface_init (NMSettingsSystemInterface *klass)
{
/* interface implementation */
klass->save_hostname = save_hostname;
klass->get_permissions = get_permissions;
}
/**
* 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 (g_cclosure_marshal_VOID__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);
/* Monitor for permissions changes */
dbus_g_proxy_add_signal (priv->proxy, "CheckPermissions", G_TYPE_INVALID);
dbus_g_proxy_connect_signal (priv->proxy, "CheckPermissions",
G_CALLBACK (check_permissions_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,56 @@
/* -*- 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"
#include "nm-settings-system-interface.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,488 @@
/* -*- 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"
#include "nm-remote-connection-private.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;
GHashTable *pending; /* Connections we don't have settings for yet */
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)
{
NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
const char *path;
path = nm_connection_get_path (NM_CONNECTION (remote));
g_hash_table_remove (priv->connections, path);
g_hash_table_remove (priv->pending, path);
}
static void
connection_init_result_cb (NMRemoteConnection *remote,
GParamSpec *pspec,
gpointer user_data)
{
NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
guint32 init_result = NM_REMOTE_CONNECTION_INIT_RESULT_UNKNOWN;
const char *path;
/* Disconnect from the init-result signal just to be safe */
g_signal_handlers_disconnect_matched (remote,
G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
0,
0,
NULL,
G_CALLBACK (connection_init_result_cb),
self);
path = nm_connection_get_path (NM_CONNECTION (remote));
g_object_get (G_OBJECT (remote),
NM_REMOTE_CONNECTION_INIT_RESULT, &init_result,
NULL);
switch (init_result) {
case NM_REMOTE_CONNECTION_INIT_RESULT_SUCCESS:
/* ref it when adding to ->connections, since removing it from ->pending
* will unref it.
*/
g_hash_table_insert (priv->connections, g_strdup (path), g_object_ref (remote));
/* Finally, let users know of the new connection now that it has all
* its settings and is valid.
*/
g_signal_emit_by_name (self, "new-connection", remote);
break;
case NM_REMOTE_CONNECTION_INIT_RESULT_ERROR:
default:
break;
}
g_hash_table_remove (priv->pending, path);
}
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_signal_connect (connection, "notify::" NM_REMOTE_CONNECTION_INIT_RESULT,
G_CALLBACK (connection_init_result_cb),
self);
/* Add the connection to the pending table to wait for it to retrieve
* it's settings asynchronously over D-Bus. The connection isn't
* really valid until it has all its settings, so hide it until it does.
*/
g_hash_table_insert (priv->pending, g_strdup (path), 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,
NMConnection *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 (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);
priv->pending = 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);
if (priv->pending)
g_hash_table_destroy (priv->pending);
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,191 @@
/* -*- 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, NM_SETTINGS_CONNECTION_INTERFACE_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;
/* Signals */
g_signal_new (NM_SETTINGS_CONNECTION_INTERFACE_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 (NM_SETTINGS_CONNECTION_INTERFACE_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,108 @@
/* -*- 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_UPDATED "updated"
#define NM_SETTINGS_CONNECTION_INTERFACE_REMOVED "removed"
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 object's 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,
NMConnection *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_CONNECTION (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,
NMConnection *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,
NMConnection *connection,
NMSettingsAddConnectionFunc callback,
gpointer user_data);
#endif /* NM_SETTINGS_INTERFACE_H */

View file

@ -0,0 +1,371 @@
/* -*- 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 <string.h>
#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 = NULL;
GSList *list = NULL, *iter;
list = list_connections (settings);
for (iter = list; iter; iter = g_slist_next (iter)) {
if (!strcmp (nm_connection_get_path (NM_CONNECTION (iter->data)), path)) {
connection = NM_EXPORTED_CONNECTION (iter->data);
break;
}
}
g_slist_free (list);
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 gboolean
add_connection (NMSettingsInterface *settings,
NMConnection *connection,
NMSettingsAddConnectionFunc callback,
gpointer user_data)
{
NMSettingsService *self = NM_SETTINGS_SERVICE (settings);
GError *error = NULL;
gboolean success = FALSE;
if (NM_SETTINGS_SERVICE_GET_CLASS (self)->add_connection) {
NM_SETTINGS_SERVICE_GET_CLASS (self)->add_connection (NM_SETTINGS_SERVICE (self),
connection,
NULL,
callback,
user_data);
success = TRUE;
} 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__);
callback (settings, error, user_data);
g_error_free (error);
}
return success;
}
static void
dbus_add_connection_cb (NMSettingsInterface *settings,
GError *error,
gpointer user_data)
{
DBusGMethodInvocation *context = user_data;
if (error)
dbus_g_method_return_error (context, error);
else
dbus_g_method_return (context);
}
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;
}
if (NM_SETTINGS_SERVICE_GET_CLASS (self)->add_connection) {
NM_SETTINGS_SERVICE_GET_CLASS (self)->add_connection (NM_SETTINGS_SERVICE (self),
tmp,
context,
dbus_add_connection_cb,
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);
}
g_object_unref (tmp);
}
void
nm_settings_service_export_connection (NMSettingsService *self,
NMSettingsConnectionInterface *connection)
{
NMSettingsServicePrivate *priv = NM_SETTINGS_SERVICE_GET_PRIVATE (self);
static guint32 ec_counter = 0;
char *path;
g_return_if_fail (connection != NULL);
g_return_if_fail (NM_IS_SETTINGS_CONNECTION_INTERFACE (connection));
g_return_if_fail (priv->bus != NULL);
/* Don't allow exporting twice */
g_return_if_fail (nm_connection_get_path (NM_CONNECTION (connection)) == NULL);
path = g_strdup_printf ("%s/%u", NM_DBUS_PATH_SETTINGS, ec_counter++);
nm_connection_set_path (NM_CONNECTION (connection), path);
nm_connection_set_scope (NM_CONNECTION (connection), priv->scope);
dbus_g_connection_register_g_object (priv->bus, path, G_OBJECT (connection));
g_free (path);
}
/**************************************************************/
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;
dbus_g_object_type_install_info (G_TYPE_FROM_INTERFACE (iface),
&dbus_glib_nm_settings_object_info);
}
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);
DBusGConnection *bus;
switch (prop_id) {
case PROP_BUS:
/* Construct only */
bus = g_value_get_boxed (value);
if (bus)
priv->bus = dbus_g_connection_ref (bus);
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;
if (priv->bus)
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_SYSTEM,
NM_CONNECTION_SCOPE_USER,
NM_CONNECTION_SCOPE_USER,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
}

View file

@ -0,0 +1,73 @@
/* -*- 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);
void (*add_connection) (NMSettingsService *self,
NMConnection *connection,
DBusGMethodInvocation *context, /* Only present for D-Bus calls */
NMSettingsAddConnectionFunc callback,
gpointer user_data);
} 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);
void nm_settings_service_export_connection (NMSettingsService *self,
NMSettingsConnectionInterface *exported);
G_END_DECLS
#endif /* NM_SETTINGS_SERVICE_H */

View file

@ -0,0 +1,147 @@
/* -*- 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;
}
/**
* nm_settings_system_interface_get_permissions:
* @settings: a object implementing %NMSettingsSystemInterface
* @callback: callback to be called when the permissions operation completes
* @user_data: caller-specific data passed to @callback
*
* Requests an indication of the operations the caller is permitted to perform
* including those that may require authorization.
**/
gboolean
nm_settings_system_interface_get_permissions (NMSettingsSystemInterface *settings,
NMSettingsSystemGetPermissionsFunc 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 (callback != NULL, FALSE);
if (NM_SETTINGS_SYSTEM_INTERFACE_GET_INTERFACE (settings)->get_permissions)
return NM_SETTINGS_SYSTEM_INTERFACE_GET_INTERFACE (settings)->get_permissions (settings, callback, user_data);
return FALSE;
}
static void
nm_settings_system_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_SYSTEM_INTERFACE_HOSTNAME,
"Hostname",
"Persistent hostname",
NULL,
G_PARAM_READABLE));
g_object_interface_install_property
(g_iface,
g_param_spec_boolean (NM_SETTINGS_SYSTEM_INTERFACE_CAN_MODIFY,
"CanModify",
"Can modify anything (hostname, connections, etc)",
FALSE,
G_PARAM_READABLE));
/* Signals */
g_signal_new (NM_SETTINGS_SYSTEM_INTERFACE_CHECK_PERMISSIONS,
iface_type,
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMSettingsSystemInterface, check_permissions),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
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,95 @@
/* -*- 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"
typedef enum {
NM_SETTINGS_SYSTEM_PERMISSION_NONE = 0x0,
NM_SETTINGS_SYSTEM_PERMISSION_CONNECTION_MODIFY = 0x1,
NM_SETTINGS_SYSTEM_PERMISSION_WIFI_SHARE_PROTECTED = 0x2,
NM_SETTINGS_SYSTEM_PERMISSION_WIFI_SHARE_OPEN = 0x4,
NM_SETTINGS_SYSTEM_PERMISSION_HOSTNAME_MODIFY = 0x8
} NMSettingsSystemPermissions;
#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"
#define NM_SETTINGS_SYSTEM_INTERFACE_CHECK_PERMISSIONS "check-permissions"
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);
typedef void (*NMSettingsSystemGetPermissionsFunc) (NMSettingsSystemInterface *settings,
NMSettingsSystemPermissions permissions,
GError *error,
gpointer user_data);
struct _NMSettingsSystemInterface {
GTypeInterface g_iface;
/* Methods */
gboolean (*save_hostname) (NMSettingsSystemInterface *settings,
const char *hostname,
NMSettingsSystemSaveHostnameFunc callback,
gpointer user_data);
gboolean (*get_permissions) (NMSettingsSystemInterface *settings,
NMSettingsSystemGetPermissionsFunc callback,
gpointer user_data);
/* Signals */
void (*check_permissions) (NMSettingsSystemInterface *settings);
};
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);
gboolean nm_settings_system_interface_get_permissions (NMSettingsSystemInterface *settings,
NMSettingsSystemGetPermissionsFunc 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

@ -1172,7 +1172,7 @@ nm_connection_class_init (NMConnectionClass *klass)
NM_CONNECTION_SCOPE_UNKNOWN,
NM_CONNECTION_SCOPE_USER,
NM_CONNECTION_SCOPE_UNKNOWN,
G_PARAM_READWRITE));
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
/**
* NMConnection:path:
@ -1186,7 +1186,7 @@ nm_connection_class_init (NMConnectionClass *klass)
"Path",
"Path",
NULL,
G_PARAM_READWRITE));
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
/* Signals */

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

@ -1,4 +1,4 @@
polkit_policydir = $(datadir)/PolicyKit/policy
polkit_policydir = $(datadir)/polkit-1/actions
dist_polkit_policy_in_files = org.freedesktop.network-manager-settings.system.policy.in
dist_polkit_policy_DATA = $(dist_polkit_policy_in_files:.policy.in=.policy)

View file

@ -14,7 +14,34 @@
<_message>System policy prevents modification of system settings</_message>
<defaults>
<allow_inactive>no</allow_inactive>
<allow_active>auth_admin_keep_always</allow_active>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
<action id="org.freedesktop.network-manager-settings.system.hostname.modify">
<_description>Modify persistent system hostname</_description>
<_message>System policy prevents modification of the persistent system hostname</_message>
<defaults>
<allow_inactive>no</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
<action id="org.freedesktop.network-manager-settings.system.wifi.share.protected">
<_description>Connection sharing via a protected WiFi network</_description>
<_message>System policy prevents sharing connections via a protected WiFi network</_message>
<defaults>
<allow_inactive>no</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
</action>
<action id="org.freedesktop.network-manager-settings.system.wifi.share.open">
<_description>Connection sharing via an open WiFi network</_description>
<_message>System policy prevents sharing connections via an open WiFi network</_message>
<defaults>
<allow_inactive>no</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
</action>

View file

@ -50,6 +50,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"
@ -883,18 +885,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)
@ -904,14 +904,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;
}
@ -922,37 +922,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, NM_SETTINGS_CONNECTION_INTERFACE_UPDATED,
G_CALLBACK (system_connection_updated_cb), manager);
g_signal_connect (exported, "removed",
g_signal_connect (connection, NM_SETTINGS_CONNECTION_INTERFACE_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));
@ -960,10 +956,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
@ -972,9 +968,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);
}
@ -1741,43 +1737,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;
}
@ -1806,9 +1814,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;
}
@ -2500,6 +2508,7 @@ nm_manager_get (const char *config_file, const char *plugins, GError **error)
{
static NMManager *singleton = NULL;
NMManagerPrivate *priv;
DBusGConnection *bus;
if (singleton)
return g_object_ref (singleton);
@ -2509,17 +2518,21 @@ nm_manager_get (const char *config_file, const char *plugins, GError **error)
priv = NM_MANAGER_GET_PRIVATE (singleton);
priv->sys_settings = nm_sysconfig_settings_new (config_file, plugins, error);
bus = nm_dbus_manager_get_connection (priv->dbus_mgr);
g_assert (bus);
priv->sys_settings = nm_sysconfig_settings_new (config_file, plugins, bus, error);
if (!priv->sys_settings) {
g_object_unref (singleton);
return NULL;
}
nm_settings_service_export (NM_SETTINGS_SERVICE (priv->sys_settings));
priv->config_file = g_strdup (config_file);
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,11 @@
#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);
#define NM_SYSCONFIG_POLICY_ACTION_CONNECTION_MODIFY "org.freedesktop.network-manager-settings.system.modify"
#define NM_SYSCONFIG_POLICY_ACTION_WIFI_SHARE_PROTECTED "org.freedesktop.network-manager-settings.system.wifi.share.protected"
#define NM_SYSCONFIG_POLICY_ACTION_WIFI_SHARE_OPEN "org.freedesktop.network-manager-settings.system.wifi.share.open"
#define NM_SYSCONFIG_POLICY_ACTION_HOSTNAME_MODIFY "org.freedesktop.network-manager-settings.system.hostname.modify"
#endif /* NM_POLKIT_HELPERS_H */

View file

@ -16,52 +16,35 @@
* 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;
PolkitAuthority *authority;
} NMSysconfigConnectionPrivate;
static gboolean
update (NMExportedConnection *exported,
GHashTable *new_settings,
GError **err)
{
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);
}
static gboolean
do_delete (NMExportedConnection *exported, GError **err)
{
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);
}
/**************************************************************/
static GValue *
string_to_gvalue (const char *str)
@ -118,25 +101,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 +136,347 @@ 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_CONNECTION_MODIFY,
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_CONNECTION_MODIFY,
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_CONNECTION_MODIFY,
NULL,
POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
call->cancellable,
pk_secrets_cb,
call);
}
/**************************************************************/
static void
settings_connection_interface_init (NMSettingsConnectionInterface *iface)
{
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 +484,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,12 @@
#define __NM_SYSCONFIG_SETTINGS_H__
#include <nm-connection.h>
#include <nm-settings.h>
#include <nm-settings-service.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,56 +41,29 @@ 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 {
NMSettingsService parent_instance;
} NMSysconfigSettings;
struct _NMSysconfigSettingsClass
{
NMSettingsClass parent_class;
typedef struct {
NMSettingsServiceClass 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);
NMSysconfigSettings *nm_sysconfig_settings_new (const char *config_file,
const char *plugins,
DBusGConnection *bus,
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, NULL, &unmanaged, &keyfile, error, ignore_error);
if (!wrapped)
tmp = connection_from_file (filename, NULL, 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

@ -84,7 +84,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
@ -113,13 +113,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);
@ -133,7 +130,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.
@ -223,6 +220,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,
@ -230,7 +234,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;
@ -244,8 +248,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",
@ -261,7 +265,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) {
@ -269,16 +273,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);
@ -286,25 +285,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
@ -326,18 +330,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);
}
}
}
@ -404,29 +408,27 @@ setup_ifcfg_monitoring (SCPluginIfcfg *plugin)
}
}
static void
hash_to_slist (gpointer key, gpointer value, gpointer user_data)
{
NMIfcfgConnection *exported = NM_IFCFG_CONNECTION (value);
GSList **list = (GSList **) user_data;
if (!nm_ifcfg_connection_get_unmanaged_spec (exported))
*list = g_slist_prepend (*list, value);
}
static GSList *
get_connections (NMSystemConfigInterface *config)
{
SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (config);
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
GSList *list = NULL;
GHashTableIter iter;
gpointer value;
if (!priv->connections) {
setup_ifcfg_monitoring (plugin);
read_connections (plugin);
}
g_hash_table_foreach (priv->connections, hash_to_slist, &list);
g_hash_table_iter_init (&iter, priv->connections);
while (g_hash_table_iter_next (&iter, NULL, &value)) {
NMIfcfgConnection *exported = NM_IFCFG_CONNECTION (value);
if (!nm_ifcfg_connection_get_unmanaged_spec (exported))
list = g_slist_prepend (list, value);
}
return list;
}

View file

@ -22,6 +22,8 @@
#include <glib/gstdio.h>
#include <gio/gio.h>
#include <NetworkManager.h>
#include <nm-settings-connection-interface.h>
#include <nm-setting-connection.h>
#include "nm-suse-connection.h"
#include "parser.h"
#include "nm-system-config-error.h"
@ -40,43 +42,53 @@ typedef struct {
} NMSuseConnectionPrivate;
static void
file_changed (GFileMonitor *monitor,
GFile *file,
GFile *other_file,
GFileMonitorEvent event_type,
gpointer user_data)
ignore_cb (NMSettingsConnectionInterface *connection,
GError *error,
gpointer user_data)
{
NMExportedConnection *exported = NM_EXPORTED_CONNECTION (user_data);
NMSuseConnectionPrivate *priv = NM_SUSE_CONNECTION_GET_PRIVATE (exported);
NMConnection *new_connection;
GHashTable *new_settings;
}
static void
file_changed (GFileMonitor *monitor,
GFile *file,
GFile *other_file,
GFileMonitorEvent event_type,
gpointer user_data)
{
NMSuseConnection *self = NM_SUSE_CONNECTION (user_data);
NMSuseConnectionPrivate *priv = NM_SUSE_CONNECTION_GET_PRIVATE (self);
NMConnection *new;
switch (event_type) {
case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
new_connection = parse_ifcfg (priv->iface, priv->dev_type);
if (new_connection) {
new = parse_ifcfg (priv->iface, priv->dev_type);
if (new) {
GError *error = NULL;
GHashTable *settings;
new_settings = nm_connection_to_hash (new_connection);
if (nm_connection_replace_settings (nm_exported_connection_get_connection (exported), new_settings, &error))
nm_exported_connection_signal_updated (exported, new_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);
if (!nm_connection_compare (new,
NM_CONNECTION (self),
NM_SETTING_COMPARE_FLAG_EXACT)) {
settings = nm_connection_to_hash (new);
if (!nm_connection_replace_settings (NM_CONNECTION (self), 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);
}
g_hash_table_destroy (settings);
nm_settings_connection_interface_update (NM_SETTINGS_CONNECTION_INTERFACE (self),
ignore_cb,
NULL);
}
g_hash_table_destroy (new_settings);
g_object_unref (new_connection);
g_object_unref (new);
} else
nm_exported_connection_signal_removed (exported);
g_signal_emit_by_name (self, "removed");
break;
case G_FILE_MONITOR_EVENT_DELETED:
nm_exported_connection_signal_removed (exported);
g_signal_emit_by_name (self, "removed");
break;
default:
break;
@ -86,24 +98,40 @@ file_changed (GFileMonitor *monitor,
NMSuseConnection *
nm_suse_connection_new (const char *iface, NMDeviceType dev_type)
{
NMConnection *connection;
NMConnection *tmp;
GFile *file;
GFileMonitor *monitor;
NMSuseConnection *exported;
NMSuseConnectionPrivate *priv;
GHashTable *settings;
NMSettingConnection *s_con;
g_return_val_if_fail (iface != NULL, NULL);
connection = parse_ifcfg (iface, dev_type);
if (!connection)
tmp = parse_ifcfg (iface, dev_type);
if (!tmp)
return NULL;
exported = (NMSuseConnection *) g_object_new (NM_TYPE_SUSE_CONNECTION,
NM_EXPORTED_CONNECTION_CONNECTION, connection,
NULL);
g_object_unref (connection);
if (!exported)
/* Ensure the read connection is read-only since we don't have write capability yet */
s_con = (NMSettingConnection *) nm_connection_get_setting (tmp, NM_TYPE_SETTING_CONNECTION);
g_assert (s_con);
if (!nm_setting_connection_get_read_only (s_con)) {
g_warning ("%s: expected read-only connection!", __func__);
g_object_unref (tmp);
return NULL;
}
exported = (NMSuseConnection *) g_object_new (NM_TYPE_SUSE_CONNECTION, NULL);
if (!exported) {
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 (exported), settings, NULL);
g_hash_table_destroy (settings);
g_object_unref (tmp);
priv = NM_SUSE_CONNECTION_GET_PRIVATE (exported);
@ -123,28 +151,6 @@ nm_suse_connection_new (const char *iface, NMDeviceType dev_type)
return exported;
}
static gboolean
update (NMExportedConnection *exported,
GHashTable *new_settings,
GError **err)
{
g_set_error (err, NM_SYSCONFIG_SETTINGS_ERROR,
NM_SYSCONFIG_SETTINGS_ERROR_UPDATE_NOT_SUPPORTED,
"%s", "Please use YaST to change this connection.");
return FALSE;
}
static gboolean
do_delete (NMExportedConnection *exported, GError **err)
{
g_set_error (err, NM_SYSCONFIG_SETTINGS_ERROR,
NM_SYSCONFIG_SETTINGS_ERROR_DELETE_NOT_SUPPORTED,
"%s", "Please use YaST to remove this connection.");
return FALSE;
}
/* GObject */
static void
@ -165,6 +171,7 @@ finalize (GObject *object)
g_object_unref (priv->monitor);
}
nm_connection_clear_secrets (NM_CONNECTION (object));
g_free (priv->filename);
G_OBJECT_CLASS (nm_suse_connection_parent_class)->finalize (object);
@ -174,13 +181,9 @@ static void
nm_suse_connection_class_init (NMSuseConnectionClass *suse_connection_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (suse_connection_class);
NMExportedConnectionClass *connection_class = NM_EXPORTED_CONNECTION_CLASS (suse_connection_class);
g_type_class_add_private (suse_connection_class, sizeof (NMSuseConnectionPrivate));
/* Virtual methods */
object_class->finalize = finalize;
connection_class->update = update;
connection_class->do_delete = do_delete;
}

View file

@ -86,38 +86,41 @@ ifcfg_plugin_error_quark (void)
}
static void
update_one_connection (gpointer key, gpointer val, gpointer user_data)
ignore_cb (NMSettingsConnectionInterface *connection,
GError *error,
gpointer user_data)
{
NMExportedConnection *exported = NM_EXPORTED_CONNECTION (val);
NMConnection *connection;
NMSettingIP4Config *ip4_config;
connection = nm_exported_connection_get_connection (exported);
ip4_config = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
if (!ip4_config)
return;
if (nm_setting_ip4_config_get_num_addresses (ip4_config)) {
/* suse only has one address per device */
NMIP4Address *ip4_address = nm_setting_ip4_config_get_address (ip4_config, 0);
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (user_data);
GHashTable *settings;
if (nm_ip4_address_get_gateway (ip4_address) != priv->default_gw) {
nm_ip4_address_set_gateway (ip4_address, priv->default_gw);
settings = nm_connection_to_hash (connection);
nm_exported_connection_signal_updated (exported, settings);
g_hash_table_destroy (settings);
}
}
}
static void
update_connections (SCPluginIfcfg *self)
{
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self);
GHashTableIter iter;
gpointer value;
g_hash_table_foreach (priv->connections, update_one_connection, self);
g_hash_table_iter_init (&iter, priv->connections);
while (g_hash_table_iter_next (&iter, NULL, &value)) {
NMSuseConnection *exported = NM_SUSE_CONNECTION (value);
NMSettingIP4Config *ip4_config;
ip4_config = (NMSettingIP4Config *) nm_connection_get_setting (NM_CONNECTION (exported), NM_TYPE_SETTING_IP4_CONFIG);
if (!ip4_config)
continue;
if (nm_setting_ip4_config_get_num_addresses (ip4_config)) {
/* suse only has one address per device */
NMIP4Address *ip4_address;
ip4_address = nm_setting_ip4_config_get_address (ip4_config, 0);
if (nm_ip4_address_get_gateway (ip4_address) != priv->default_gw) {
nm_ip4_address_set_gateway (ip4_address, priv->default_gw);
nm_settings_connection_interface_update (NM_SETTINGS_CONNECTION_INTERFACE (exported),
ignore_cb,
NULL);
}
}
}
}
static void
@ -186,7 +189,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 {
@ -197,7 +200,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);
}
}
}
@ -277,12 +280,14 @@ 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));
if (exported) {
nm_exported_connection_signal_removed (exported);
nm_settings_connection_interface_delete (NM_SETTINGS_CONNECTION_INTERFACE (exported),
ignore_cb,
NULL);
g_hash_table_remove (priv->connections, GUINT_TO_POINTER (ifindex));
}
}
@ -302,20 +307,14 @@ init (NMSystemConfigInterface *config)
g_signal_connect (priv->client, "uevent", G_CALLBACK (handle_uevent), self);
}
static void
get_connections_cb (gpointer key, gpointer val, gpointer user_data)
{
GSList **list = (GSList **) user_data;
*list = g_slist_prepend (*list, val);
}
static GSList *
get_connections (NMSystemConfigInterface *config)
{
SCPluginIfcfg *self = SC_PLUGIN_IFCFG (config);
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self);
GSList *list = NULL;
GHashTableIter iter;
gpointer value;
if (!priv->initialized) {
const char *filename;
@ -332,7 +331,9 @@ get_connections (NMSystemConfigInterface *config)
priv->initialized = TRUE;
}
g_hash_table_foreach (priv->connections, get_connections_cb, &list);
g_hash_table_iter_init (&iter, priv->connections);
while (g_hash_table_iter_next (&iter, NULL, &value))
list = g_slist_prepend (list, value);
return list;
}

View file

@ -29,13 +29,10 @@
#include <nm-sysconfig-connection.h>
#include <nm-system-config-interface.h>
#include <nm-system-config-error.h>
#include <nm-settings.h>
#include "nm-ifupdown-connection.h"
#include "parser.h"
G_DEFINE_TYPE (NMIfupdownConnection,
nm_ifupdown_connection,
NM_TYPE_SYSCONFIG_CONNECTION)
G_DEFINE_TYPE (NMIfupdownConnection, nm_ifupdown_connection, NM_TYPE_SYSCONFIG_CONNECTION)
#define NM_IFUPDOWN_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_IFUPDOWN_CONNECTION, NMIfupdownConnectionPrivate))
@ -60,36 +57,16 @@ nm_ifupdown_connection_new (if_block *block)
NULL);
}
static gboolean
update (NMExportedConnection *exported,
GHashTable *new_settings,
GError **err)
{
g_set_error (err, NM_SYSCONFIG_SETTINGS_ERROR,
NM_SYSCONFIG_SETTINGS_ERROR_UPDATE_NOT_SUPPORTED,
"%s.%d - %s", __FILE__, __LINE__, "connection update not supported (read-only).");
return FALSE;
}
static gboolean
do_delete (NMExportedConnection *exported, GError **err)
{
g_set_error (err, NM_SYSCONFIG_SETTINGS_ERROR,
NM_SYSCONFIG_SETTINGS_ERROR_DELETE_NOT_SUPPORTED,
"%s", "ifupdown - connection delete not supported (read-only).");
return FALSE;
}
static void
service_get_secrets (NMExportedConnection *exported,
const gchar *setting_name,
const gchar **hints,
gboolean request_new,
DBusGMethodInvocation *context)
get_secrets (NMExportedConnection *exported,
const gchar *setting_name,
const gchar **hints,
gboolean request_new,
DBusGMethodInvocation *context)
{
GError *error = NULL;
PLUGIN_PRINT ("SCPlugin-Ifupdown", "get_secrets for setting_name:'%s')", setting_name);
PLUGIN_PRINT ("SCPlugin-Ifupdown", "get_secrets() for setting_name:'%s'", setting_name);
/* FIXME: Only wifi secrets are supported for now */
if (strcmp (setting_name, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME)) {
@ -104,10 +81,9 @@ service_get_secrets (NMExportedConnection *exported,
return;
}
NM_EXPORTED_CONNECTION_CLASS (nm_ifupdown_connection_parent_class)->service_get_secrets (exported, setting_name, hints, request_new, context);
NM_EXPORTED_CONNECTION_CLASS (nm_ifupdown_connection_parent_class)->get_secrets (exported, setting_name, hints, request_new, context);
}
/* GObject */
static void
nm_ifupdown_connection_init (NMIfupdownConnection *connection)
{
@ -120,23 +96,29 @@ constructor (GType type,
{
GObject *object;
NMIfupdownConnectionPrivate *priv;
NMConnection *wrapped = nm_connection_new();
GError *error = NULL;
object = G_OBJECT_CLASS (nm_ifupdown_connection_parent_class)->constructor (type, n_construct_params, construct_params);
g_return_val_if_fail (object, NULL);
priv = NM_IFUPDOWN_CONNECTION_GET_PRIVATE (object);
if (!priv) {
nm_warning ("%s.%d - no private instance.", __FILE__, __LINE__);
g_warning ("%s.%d - no private instance.", __FILE__, __LINE__);
goto err;
}
if (!priv->ifblock) {
nm_warning ("(ifupdown) ifblock not provided to constructor.");
g_warning ("(ifupdown) ifblock not provided to constructor.");
goto err;
}
g_object_set (object, NM_EXPORTED_CONNECTION_CONNECTION, wrapped, NULL);
g_object_unref (wrapped);
if (!ifupdown_update_connection_from_if_block (NM_CONNECTION (object), priv->ifblock, &error)) {
g_warning ("%s.%d - invalid connection read from /etc/network/interfaces: (%d) %s",
__FILE__,
__LINE__,
error ? error->code : -1,
error && error->message ? error->message : "(unknown)");
goto err;
}
return object;
@ -145,12 +127,6 @@ constructor (GType type,
return NULL;
}
static void
finalize (GObject *object)
{
G_OBJECT_CLASS (nm_ifupdown_connection_parent_class)->finalize (object);
}
static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
@ -197,11 +173,8 @@ nm_ifupdown_connection_class_init (NMIfupdownConnectionClass *ifupdown_connectio
object_class->constructor = constructor;
object_class->set_property = set_property;
object_class->get_property = get_property;
object_class->finalize = finalize;
connection_class->update = update;
connection_class->do_delete = do_delete;
connection_class->service_get_secrets = service_get_secrets;
connection_class->get_secrets = get_secrets;
/* Properties */
g_object_class_install_property

View file

@ -525,58 +525,53 @@ update_ip4_setting_from_if_block(NMConnection *connection,
nm_connection_add_setting(connection, NM_SETTING(ip4_setting));
}
void
ifupdown_update_connection_from_if_block(NMConnection *connection,
if_block *block)
gboolean
ifupdown_update_connection_from_if_block (NMConnection *connection,
if_block *block,
GError **error)
{
const char *type = NULL;
char *idstr = NULL;
char *uuid_base = NULL;
GError *verify_error = NULL;
char *uuid = NULL;
NMSettingConnection *s_con;
gboolean success = FALSE;
NMSettingConnection *connection_setting =
NM_SETTING_CONNECTION(nm_connection_get_setting
(connection, NM_TYPE_SETTING_CONNECTION));
if(!connection_setting) {
connection_setting = NM_SETTING_CONNECTION(nm_setting_connection_new());
nm_connection_add_setting(connection, NM_SETTING(connection_setting));
s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
if(!s_con) {
s_con = NM_SETTING_CONNECTION (nm_setting_connection_new());
g_assert (s_con);
nm_connection_add_setting (connection, NM_SETTING (s_con));
}
type = _ifupdownplugin_guess_connection_type (block);
idstr = g_strconcat("Ifupdown (", block->name,")", NULL);
idstr = g_strconcat ("Ifupdown (", block->name, ")", NULL);
uuid_base = idstr;
uuid = nm_utils_uuid_generate_from_string(uuid_base);
g_object_set (connection_setting,
uuid = nm_utils_uuid_generate_from_string (uuid_base);
g_object_set (s_con,
NM_SETTING_CONNECTION_TYPE, type,
NM_SETTING_CONNECTION_ID, idstr,
NM_SETTING_CONNECTION_UUID, uuid,
NM_SETTING_CONNECTION_READ_ONLY, TRUE,
NM_SETTING_CONNECTION_AUTOCONNECT, FALSE,
NULL);
g_free (uuid);
PLUGIN_PRINT("SCPlugin-Ifupdown", "update_connection_setting_from_if_block: name:%s, type:%s, autoconnect:%d, id:%s, uuid: %s",
block->name, type,
((gboolean) strcmp("dhcp", type) == 0),
idstr,
nm_setting_connection_get_uuid (connection_setting));
PLUGIN_PRINT("SCPlugin-Ifupdown", "update_connection_setting_from_if_block: name:%s, type:%s, id:%s, uuid: %s",
block->name, type, idstr, nm_setting_connection_get_uuid (s_con));
if(!strcmp (NM_SETTING_WIRED_SETTING_NAME, type)) {
if (!strcmp (NM_SETTING_WIRED_SETTING_NAME, type))
update_wired_setting_from_if_block (connection, block);
}
else if(!strcmp (NM_SETTING_WIRELESS_SETTING_NAME, type)) {
else if (!strcmp (NM_SETTING_WIRELESS_SETTING_NAME, type)) {
update_wireless_setting_from_if_block (connection, block);
update_wireless_security_setting_from_if_block (connection, block);
}
update_ip4_setting_from_if_block(connection, block);
update_ip4_setting_from_if_block (connection, block);
if(!nm_connection_verify(connection, &verify_error)) {
nm_warning("connection broken: %s (%d)",
verify_error->message, verify_error->code);
}
success = nm_connection_verify (connection, error);
g_free(idstr);
g_free (idstr);
return success;
}

View file

@ -26,8 +26,9 @@
G_BEGIN_DECLS
void
ifupdown_update_connection_from_if_block(NMConnection *connection,
if_block *block);
gboolean
ifupdown_update_connection_from_if_block (NMConnection *connection,
if_block *block,
GError **error);
G_END_DECLS

View file

@ -86,8 +86,8 @@ static void
system_config_interface_init (NMSystemConfigInterface *system_config_interface_class);
G_DEFINE_TYPE_EXTENDED (SCPluginIfupdown, sc_plugin_ifupdown, G_TYPE_OBJECT, 0,
G_IMPLEMENT_INTERFACE (NM_TYPE_SYSTEM_CONFIG_INTERFACE,
system_config_interface_init))
G_IMPLEMENT_INTERFACE (NM_TYPE_SYSTEM_CONFIG_INTERFACE,
system_config_interface_init))
#define SC_PLUGIN_IFUPDOWN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SC_TYPE_PLUGIN_IFUPDOWN, SCPluginIfupdownPrivate))
@ -124,9 +124,6 @@ GObject__set_property (GObject *object, guint prop_id,
static void
GObject__dispose (GObject *object);
static void
GObject__finalize (GObject *object);
/* other helpers */
static const char *
get_hostname (NMSystemConfigInterface *config);
@ -155,7 +152,6 @@ sc_plugin_ifupdown_class_init (SCPluginIfupdownClass *req_class)
g_type_class_add_private (req_class, sizeof (SCPluginIfupdownPrivate));
object_class->dispose = GObject__dispose;
object_class->finalize = GObject__finalize;
object_class->get_property = GObject__get_property;
object_class->set_property = GObject__set_property;
@ -176,13 +172,19 @@ sc_plugin_ifupdown_class_init (SCPluginIfupdownClass *req_class)
NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME);
}
static void
ignore_cb (NMSettingsConnectionInterface *connection,
GError *error,
gpointer user_data)
{
}
static void
bind_device_to_connection (SCPluginIfupdown *self,
GUdevDevice *device,
NMExportedConnection *exported)
NMIfupdownConnection *exported)
{
GByteArray *mac_address;
NMConnection *connection;
NMSetting *s_wired = NULL;
NMSetting *s_wifi = NULL;
const char *iface, *address;
@ -194,13 +196,6 @@ bind_device_to_connection (SCPluginIfupdown *self,
return;
}
connection = nm_exported_connection_get_connection (exported);
if (!connection) {
PLUGIN_WARN ("SCPluginIfupdown", "no device locking possible. "
"NMExportedConnection doesnt have a real connection.");
return;
}
address = g_udev_device_get_sysfs_attr (device, "address");
if (!address || !strlen (address)) {
PLUGIN_WARN ("SCPluginIfupdown", "failed to get MAC address for %s", iface);
@ -217,8 +212,8 @@ bind_device_to_connection (SCPluginIfupdown *self,
mac_address = g_byte_array_sized_new (ETH_ALEN);
g_byte_array_append (mac_address, &(tmp_mac->ether_addr_octet[0]), ETH_ALEN);
s_wired = nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED);
s_wifi = nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS);
s_wired = nm_connection_get_setting (NM_CONNECTION (exported), NM_TYPE_SETTING_WIRED);
s_wifi = nm_connection_get_setting (NM_CONNECTION (exported), NM_TYPE_SETTING_WIRELESS);
if (s_wifi) {
PLUGIN_PRINT ("SCPluginIfupdown", "locking wired connection setting");
g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, mac_address, NULL);
@ -226,8 +221,11 @@ bind_device_to_connection (SCPluginIfupdown *self,
PLUGIN_PRINT ("SCPluginIfupdown", "locking wireless connection setting");
g_object_set (s_wifi, NM_SETTING_WIRELESS_MAC_ADDRESS, mac_address, NULL);
}
g_byte_array_free (mac_address, TRUE);
nm_settings_connection_interface_update (NM_SETTINGS_CONNECTION_INTERFACE (exported),
ignore_cb,
NULL);
}
static void
@ -235,7 +233,7 @@ udev_device_added (SCPluginIfupdown *self, GUdevDevice *device)
{
SCPluginIfupdownPrivate *priv = SC_PLUGIN_IFUPDOWN_GET_PRIVATE (self);
const char *iface, *path;
NMExportedConnection *exported;
NMIfupdownConnection *exported;
iface = g_udev_device_get_name (device);
path = g_udev_device_get_sysfs_path (device);
@ -248,14 +246,14 @@ udev_device_added (SCPluginIfupdown *self, GUdevDevice *device)
/* if we have a configured connection for this particular iface
* we want to either unmanage the device or lock it
*/
exported = (NMExportedConnection *) g_hash_table_lookup (priv->iface_connections, iface);
exported = (NMIfupdownConnection *) g_hash_table_lookup (priv->iface_connections, iface);
if (!exported)
return;
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 +276,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
@ -352,14 +350,23 @@ SCPluginIfupdown_init (NMSystemConfigInterface *config)
if(!strcmp ("auto", block->type))
g_hash_table_insert (auto_ifaces, block->name, GUINT_TO_POINTER (1));
else if (!strcmp ("iface", block->type) && strcmp ("lo", block->name)) {
NMExportedConnection *exported;
NMIfupdownConnection *exported;
g_hash_table_remove (priv->iface_connections, block->name);
/* Remove any connection for this block that was previously found */
exported = g_hash_table_lookup (priv->iface_connections, block->name);
if (exported) {
nm_settings_connection_interface_delete (NM_SETTINGS_CONNECTION_INTERFACE (exported),
ignore_cb,
NULL);
g_hash_table_remove (priv->iface_connections, block->name);
}
exported = NM_EXPORTED_CONNECTION (nm_ifupdown_connection_new (block));
ifupdown_update_connection_from_if_block (nm_exported_connection_get_connection (exported),
block);
g_hash_table_insert (priv->iface_connections, block->name, exported);
/* add the new connection */
exported = nm_ifupdown_connection_new (block);
if (exported) {
g_hash_table_insert (priv->iface_connections, block->name, exported);
g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, exported);
}
}
block = block->next;
}
@ -367,17 +374,20 @@ SCPluginIfupdown_init (NMSystemConfigInterface *config)
/* Make 'auto' interfaces autoconnect=TRUE */
keys = g_hash_table_get_keys (priv->iface_connections);
for (iter = keys; iter; iter = g_list_next (iter)) {
NMExportedConnection *exported;
NMConnection *wrapped;
NMIfupdownConnection *exported;
NMSetting *setting;
if (!g_hash_table_lookup (auto_ifaces, iter->data))
continue;
exported = g_hash_table_lookup (priv->iface_connections, iter->data);
wrapped = nm_exported_connection_get_connection (exported);
setting = NM_SETTING (nm_connection_get_setting (wrapped, NM_TYPE_SETTING_CONNECTION));
setting = NM_SETTING (nm_connection_get_setting (NM_CONNECTION (exported), NM_TYPE_SETTING_CONNECTION));
g_object_set (setting, NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NULL);
nm_settings_connection_interface_update (NM_SETTINGS_CONNECTION_INTERFACE (exported),
ignore_cb,
NULL);
PLUGIN_PRINT("SCPlugin-Ifupdown", "autoconnect");
}
g_list_free (keys);
@ -433,15 +443,15 @@ SCPluginIfupdown_get_connections (NMSystemConfigInterface *config)
{
SCPluginIfupdownPrivate *priv = SC_PLUGIN_IFUPDOWN_GET_PRIVATE (config);
GSList *connections = NULL;
GList *priv_list = g_hash_table_get_values(priv->iface_connections);
GList *it = priv_list;
GHashTableIter iter;
gpointer value;
PLUGIN_PRINT("SCPlugin-Ifupdown", "(%d) ... get_connections.", GPOINTER_TO_UINT(config));
while(it) {
NMExportedConnection *conn = it->data;
connections = g_slist_append(connections, conn);
it = it->next;
}
g_hash_table_iter_init (&iter, priv->iface_connections);
while (g_hash_table_iter_next (&iter, NULL, &value))
connections = g_slist_prepend (connections, value);
PLUGIN_PRINT("SCPlugin-Ifupdown", "(%d) connections count: %d", GPOINTER_TO_UINT(config), g_slist_length(connections));
return connections;
}
@ -455,28 +465,25 @@ static GSList*
SCPluginIfupdown_get_unmanaged_specs (NMSystemConfigInterface *config)
{
SCPluginIfupdownPrivate *priv = SC_PLUGIN_IFUPDOWN_GET_PRIVATE (config);
GList *devs, *iter;
GSList *specs = NULL;
GHashTableIter iter;
gpointer value;
if (!ALWAYS_UNMANAGE && !priv->unmanage_well_known)
return NULL;
devs = g_hash_table_get_values (priv->well_known_ifaces);
PLUGIN_PRINT("Ifupdown", "get unmanaged devices count: %d", g_list_length (devs));
PLUGIN_PRINT("Ifupdown", "get unmanaged devices count: %d",
g_hash_table_size (priv->well_known_ifaces));
for (iter = devs; iter; iter = g_list_next (iter)) {
GUdevDevice *device = G_UDEV_DEVICE (iter->data);
g_hash_table_iter_init (&iter, priv->well_known_ifaces);
while (g_hash_table_iter_next (&iter, NULL, &value)) {
GUdevDevice *device = G_UDEV_DEVICE (value);
const char *address;
char *spec;
address = g_udev_device_get_sysfs_attr (device, "address");
if (!address)
continue;
spec = g_strdup_printf ("mac:%s", address);
specs = g_slist_append (specs, spec);
if (address)
specs = g_slist_append (specs, g_strdup_printf ("mac:%s", address));
}
g_list_free (devs);
return specs;
}
@ -619,12 +626,6 @@ GObject__dispose (GObject *object)
G_OBJECT_CLASS (sc_plugin_ifupdown_parent_class)->dispose (object);
}
static void
GObject__finalize (GObject *object)
{
G_OBJECT_CLASS (sc_plugin_ifupdown_parent_class)->finalize (object);
}
G_MODULE_EXPORT GObject *
nm_system_config_factory (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

@ -109,15 +109,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))
@ -125,17 +123,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__,
@ -143,7 +139,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);
@ -172,7 +168,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;
@ -180,18 +176,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;
@ -199,8 +194,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) {
@ -225,8 +219,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,
@ -239,7 +233,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);
}
}
}
@ -266,7 +260,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);