diff --git a/ChangeLog b/ChangeLog index b3ef434ab..05fcc39ce 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2008-03-26 Dan Williams + + Rework VPN connection handling for a more consistent D-Bus API. The + VPNManager object has been removed, and active VPN connections are now the + same as any other active connection. The Manager object's ActivateConnection + and DeactivateConnection methods are used to start and stop a VPN connection, + and the VPNConnection objects are subclasses of the ActiveConnection objects. + When activating a VPN connection, pass the path of the active connection + to which the VPN connection is tied in the 'specific_object' argument. + + Consequently, the libnm-glib API has been reworked to match this arrangement, + with the VPNManager object removed, and the NMVPNConnection objects now + being subclasses of NMActiveConnection. + 2008-03-25 Dan Williams Patch from Björn Martensen diff --git a/introspection/Makefile.am b/introspection/Makefile.am index e8ca586d0..6b74577a8 100644 --- a/introspection/Makefile.am +++ b/introspection/Makefile.am @@ -10,7 +10,6 @@ EXTRA_DIST = \ nm-manager-client.xml \ nm-settings.xml \ nm-exported-connection.xml \ - nm-vpn-manager.xml \ nm-vpn-plugin.xml \ nm-vpn-connection.xml \ nm-ppp-manager.xml \ diff --git a/introspection/all.xml b/introspection/all.xml index 07f8dbed4..654f7cce9 100644 --- a/introspection/all.xml +++ b/introspection/all.xml @@ -36,7 +36,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - diff --git a/introspection/nm-vpn-connection.xml b/introspection/nm-vpn-connection.xml index b899d95f1..757b8d22a 100644 --- a/introspection/nm-vpn-connection.xml +++ b/introspection/nm-vpn-connection.xml @@ -1,20 +1,32 @@ + + + The D-Bus service name providing this connection. + + + The path of the connection. + + + A specific object associated with the active connection. + + + The D-Bus service name that provides a connection with which this active connection is shared. + + + The path of a connection provided by the D-Bus service SharedServiceName which which this connection is shared. + + + Array of object paths representing devices which are part of this active connection. + + + - Represents a connection to a Virtual Private Network. + Represents an active connection to a Virtual Private Network. - - - Disconnect the VPN connection. - - - - - The name of the VPN connection. - The state of the VPN connection. @@ -37,6 +49,7 @@ + diff --git a/introspection/nm-vpn-manager.xml b/introspection/nm-vpn-manager.xml deleted file mode 100644 index 57665f61a..000000000 --- a/introspection/nm-vpn-manager.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - Establish a VPN connection. - - - - - String describing the connection type. - - - - - Object path of the network connection to establish the VPN connection on. - - - - - Object path of the device to establish the VPN connection on. - - - - - Object path of the newly created VPN connection. - - - - - - - Get the list of active VPN connections. - - - - - List of object paths of active VPN connections. - - - - - - - diff --git a/libnm-glib/Makefile.am b/libnm-glib/Makefile.am index a88ca59e5..47d4f1e8e 100644 --- a/libnm-glib/Makefile.am +++ b/libnm-glib/Makefile.am @@ -10,7 +10,6 @@ BUILT_SOURCES = \ nm-marshal.c \ nm-exported-connection-glue.h \ nm-settings-glue.h \ - nm-vpn-manager-bindings.h \ nm-vpn-connection-bindings.h \ nm-vpn-plugin-glue.h \ nm-active-connection-bindings.h @@ -39,7 +38,6 @@ libnminclude_HEADERS = \ nm-gsm-device.h \ nm-cdma-device.h \ nm-vpn-connection.h \ - nm-vpn-manager.h \ nm-vpn-plugin.h \ nm-types.h \ nm-active-connection.h @@ -61,7 +59,6 @@ libnm_glib_la_SOURCES = \ nm-gsm-device.c \ nm-cdma-device.c \ nm-vpn-connection.c \ - nm-vpn-manager.c \ nm-marshal-main.c \ nm-types.c \ nm-types-private.h \ @@ -123,9 +120,6 @@ nm-settings-glue.h: $(top_srcdir)/introspection/nm-settings.xml nm-exported-connection-glue.h: $(top_srcdir)/introspection/nm-exported-connection.xml dbus-binding-tool --prefix=nm_exported_connection --mode=glib-server --output=nm-exported-connection-glue.h $(top_srcdir)/introspection/nm-exported-connection.xml -nm-vpn-manager-bindings.h: $(top_srcdir)/introspection/nm-vpn-manager.xml - dbus-binding-tool --prefix=nm_vpn_manager --mode=glib-client --output=nm-vpn-manager-bindings.h $(top_srcdir)/introspection/nm-vpn-manager.xml - nm-vpn-connection-bindings.h: $(top_srcdir)/introspection/nm-vpn-connection.xml dbus-binding-tool --prefix=nm_vpn_connection --mode=glib-client --output=nm-vpn-connection-bindings.h $(top_srcdir)/introspection/nm-vpn-connection.xml diff --git a/libnm-glib/nm-active-connection.c b/libnm-glib/nm-active-connection.c index d8d5dd051..8ee8a8e3c 100644 --- a/libnm-glib/nm-active-connection.c +++ b/libnm-glib/nm-active-connection.c @@ -7,6 +7,7 @@ #include "nm-object-private.h" #include "nm-types-private.h" #include "nm-device.h" +#include "nm-connection.h" #include "nm-active-connection-bindings.h" @@ -22,6 +23,7 @@ typedef struct { DBusGProxy *proxy; char *service_name; + NMConnectionScope scope; char *connection; char *specific_object; char *shared_service_name; @@ -60,6 +62,17 @@ nm_active_connection_new (DBusGConnection *connection, const char *path) NULL); } +static NMConnectionScope +get_scope_for_service_name (const char *service_name) +{ + if (service_name && !strcmp (service_name, NM_DBUS_SERVICE_USER_SETTINGS)) + return NM_CONNECTION_SCOPE_USER; + else if (service_name && !strcmp (service_name, NM_DBUS_SERVICE_SYSTEM_SETTINGS)) + return NM_CONNECTION_SCOPE_SYSTEM; + + return NM_CONNECTION_SCOPE_UNKNOWN; +} + const char * nm_active_connection_get_service_name (NMActiveConnection *connection) { @@ -72,11 +85,22 @@ nm_active_connection_get_service_name (NMActiveConnection *connection) priv->service_name = nm_object_get_string_property (NM_OBJECT (connection), NM_DBUS_INTERFACE_ACTIVE_CONNECTION, DBUS_PROP_SERVICE_NAME); + priv->scope = get_scope_for_service_name (priv->service_name); } return priv->service_name; } +NMConnectionScope +nm_active_connection_get_scope (NMActiveConnection *connection) +{ + g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NM_CONNECTION_SCOPE_UNKNOWN); + + /* Make sure service_name and scope are up-to-date */ + nm_active_connection_get_service_name (connection); + return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->scope; +} + const char * nm_active_connection_get_connection (NMActiveConnection *connection) { @@ -256,12 +280,24 @@ demarshal_devices (NMObject *object, GParamSpec *pspec, GValue *value, gpointer return TRUE; } +static gboolean +demarshal_service (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field) +{ + NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object); + + if (nm_object_demarshal_generic (object, pspec, value, field)) { + priv->scope = get_scope_for_service_name (priv->service_name); + return TRUE; + } + return FALSE; +} + static void register_for_property_changed (NMActiveConnection *connection) { NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (connection); const NMPropertiesChangedInfo property_changed_info[] = { - { NM_ACTIVE_CONNECTION_SERVICE_NAME, nm_object_demarshal_generic, &priv->service_name }, + { NM_ACTIVE_CONNECTION_SERVICE_NAME, demarshal_service, &priv->service_name }, { NM_ACTIVE_CONNECTION_CONNECTION, nm_object_demarshal_generic, &priv->connection }, { NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT, nm_object_demarshal_generic, &priv->specific_object }, { NM_ACTIVE_CONNECTION_SHARED_SERVICE_NAME, nm_object_demarshal_generic, &priv->shared_service_name }, diff --git a/libnm-glib/nm-active-connection.h b/libnm-glib/nm-active-connection.h index b42aa5122..bf4129f7f 100644 --- a/libnm-glib/nm-active-connection.h +++ b/libnm-glib/nm-active-connection.h @@ -4,6 +4,7 @@ #include #include #include "nm-object.h" +#include G_BEGIN_DECLS @@ -34,6 +35,7 @@ GType nm_active_connection_get_type (void); GObject *nm_active_connection_new (DBusGConnection *connection, const char *path); const char * nm_active_connection_get_service_name (NMActiveConnection *connection); +NMConnectionScope nm_active_connection_get_scope (NMActiveConnection *connection); const char * nm_active_connection_get_connection (NMActiveConnection *connection); const char * nm_active_connection_get_specific_object (NMActiveConnection *connection); const char * nm_active_connection_get_shared_service_name (NMActiveConnection *connection); diff --git a/libnm-glib/nm-client.c b/libnm-glib/nm-client.c index 1d028f4be..126e65820 100644 --- a/libnm-glib/nm-client.c +++ b/libnm-glib/nm-client.c @@ -14,6 +14,7 @@ #include "nm-types-private.h" #include "nm-object-private.h" #include "nm-active-connection.h" +#include "nm-vpn-connection.h" #include "nm-object-cache.h" #include "nm-dbus-glib-types.h" @@ -131,6 +132,46 @@ wireless_enabled_cb (GObject *object, GParamSpec *pspec, gpointer user_data) poke_wireless_devices_with_rf_status (NM_CLIENT (object)); } +static GObject * +new_active_connection (DBusGConnection *connection, const char *path) +{ + DBusGProxy *proxy; + GError *error = NULL; + GValue value = {0,}; + GObject *object = NULL; + + proxy = dbus_g_proxy_new_for_name (connection, + NM_DBUS_SERVICE, + path, + "org.freedesktop.DBus.Properties"); + if (!proxy) { + g_warning ("%s: couldn't create D-Bus object proxy.", __func__); + return NULL; + } + + /* Have to create an NMVPNConnection if it's a VPN connection, otherwise + * a plain NMActiveConnection. + */ + if (dbus_g_proxy_call (proxy, + "Get", &error, + G_TYPE_STRING, NM_DBUS_INTERFACE_ACTIVE_CONNECTION, + G_TYPE_STRING, "Vpn", + G_TYPE_INVALID, + G_TYPE_VALUE, &value, G_TYPE_INVALID)) { + if (g_value_get_boolean (&value)) + object = nm_vpn_connection_new (connection, path); + else + object = nm_active_connection_new (connection, path); + } else { + g_warning ("Error in getting active connection 'Vpn' property: (%d) %s", + error->code, error->message); + g_error_free (error); + } + + g_object_unref (proxy); + return object; +} + static gboolean demarshal_active_connections (NMObject *object, GParamSpec *pspec, @@ -140,7 +181,7 @@ demarshal_active_connections (NMObject *object, DBusGConnection *connection; connection = nm_object_get_connection (object); - if (!nm_object_array_demarshal (value, (GPtrArray **) field, connection, nm_active_connection_new)) + if (!nm_object_array_demarshal (value, (GPtrArray **) field, connection, new_active_connection)) return FALSE; nm_object_queue_notify (object, NM_CLIENT_ACTIVE_CONNECTIONS); diff --git a/libnm-glib/nm-vpn-connection.c b/libnm-glib/nm-vpn-connection.c index ff18de924..e256bef3a 100644 --- a/libnm-glib/nm-vpn-connection.c +++ b/libnm-glib/nm-vpn-connection.c @@ -27,14 +27,14 @@ #include "nm-vpn-connection-bindings.h" #include "nm-marshal.h" #include "nm-object-private.h" +#include "nm-active-connection.h" -G_DEFINE_TYPE (NMVPNConnection, nm_vpn_connection, NM_TYPE_OBJECT) +G_DEFINE_TYPE (NMVPNConnection, nm_vpn_connection, NM_TYPE_ACTIVE_CONNECTION) #define NM_VPN_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_VPN_CONNECTION, NMVPNConnectionPrivate)) typedef struct { DBusGProxy *proxy; - char *name; char *banner; NMVPNConnectionState state; } NMVPNConnectionPrivate; @@ -48,38 +48,16 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; -NMVPNConnection * -nm_vpn_connection_new (DBusGConnection *dbus_connection, - const char *path) +GObject * +nm_vpn_connection_new (DBusGConnection *dbus_connection, const char *path) { - NMVPNConnection *connection; - g_return_val_if_fail (dbus_connection != NULL, NULL); g_return_val_if_fail (path != NULL, NULL); - connection = (NMVPNConnection *) g_object_new (NM_TYPE_VPN_CONNECTION, - NM_OBJECT_DBUS_CONNECTION, dbus_connection, - NM_OBJECT_DBUS_PATH, path, - NULL); - - nm_vpn_connection_get_name (connection); - - return connection; -} - -const char * -nm_vpn_connection_get_name (NMVPNConnection *vpn) -{ - NMVPNConnectionPrivate *priv; - - g_return_val_if_fail (NM_IS_VPN_CONNECTION (vpn), NULL); - - priv = NM_VPN_CONNECTION_GET_PRIVATE (vpn); - if (!priv->name) - priv->name = nm_object_get_string_property (NM_OBJECT (vpn), - NM_DBUS_INTERFACE_VPN_CONNECTION, - "Name"); - return priv->name; + return g_object_new (NM_TYPE_VPN_CONNECTION, + NM_OBJECT_DBUS_CONNECTION, dbus_connection, + NM_OBJECT_DBUS_PATH, path, + NULL); } const char * @@ -136,20 +114,6 @@ state_changed_proxy (DBusGProxy *proxy, } } -void -nm_vpn_connection_disconnect (NMVPNConnection *vpn) -{ - GError *err = NULL; - - g_return_if_fail (NM_IS_VPN_CONNECTION (vpn)); - - org_freedesktop_NetworkManager_VPN_Connection_disconnect (NM_VPN_CONNECTION_GET_PRIVATE (vpn)->proxy, &err); - if (err) { - nm_warning ("Error in VPN disconnect: %s", err->message); - g_error_free (err); - } -} - /*****************************************************************************/ static void @@ -199,12 +163,11 @@ finalize (GObject *object) { NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (object); - if (priv->name) - g_free (priv->name); if (priv->banner) g_free (priv->banner); g_object_unref (priv->proxy); + G_OBJECT_CLASS (nm_vpn_connection_parent_class)->finalize (object); } diff --git a/libnm-glib/nm-vpn-connection.h b/libnm-glib/nm-vpn-connection.h index a32cc6664..6b6098843 100644 --- a/libnm-glib/nm-vpn-connection.h +++ b/libnm-glib/nm-vpn-connection.h @@ -26,7 +26,7 @@ #include #include #include -#include "nm-object.h" +#include "nm-active-connection.h" #include "NetworkManagerVPN.h" G_BEGIN_DECLS @@ -39,11 +39,11 @@ G_BEGIN_DECLS #define NM_VPN_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_VPN_CONNECTION, NMVPNConnectionClass)) typedef struct { - NMObject parent; + NMActiveConnection parent; } NMVPNConnection; typedef struct { - NMObjectClass parent; + NMActiveConnectionClass parent; /* Signals */ void (*state_changed) (NMVPNConnection *connection, @@ -53,16 +53,11 @@ typedef struct { GType nm_vpn_connection_get_type (void); +GObject * nm_vpn_connection_new (DBusGConnection *dbus_connection, const char *path); -NMVPNConnection * nm_vpn_connection_new (DBusGConnection *dbus_connection, - const char *path); - -const char * nm_vpn_connection_get_name (NMVPNConnection *vpn); NMVPNConnectionState nm_vpn_connection_get_state (NMVPNConnection *vpn); const char * nm_vpn_connection_get_banner (NMVPNConnection *vpn); -void nm_vpn_connection_disconnect (NMVPNConnection *vpn); - G_END_DECLS #endif /* NM_VPN_CONNECTION_H */ diff --git a/libnm-glib/nm-vpn-manager.c b/libnm-glib/nm-vpn-manager.c deleted file mode 100644 index 2c5768788..000000000 --- a/libnm-glib/nm-vpn-manager.c +++ /dev/null @@ -1,136 +0,0 @@ -/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ - -#include -#include -#include "nm-vpn-manager.h" -#include "nm-marshal.h" - -#include "nm-vpn-manager-bindings.h" - -G_DEFINE_TYPE (NMVPNManager, nm_vpn_manager, NM_TYPE_OBJECT) - -#define NM_VPN_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_VPN_MANAGER, NMVPNManagerPrivate)) - -typedef struct { - DBusGProxy *manager_proxy; -} NMVPNManagerPrivate; - -NMVPNManager * -nm_vpn_manager_new (void) -{ - DBusGConnection *connection; - GError *err = NULL; - - connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err); - if (!connection) { - g_warning ("Couldn't connect to system bus: %s", err->message); - g_error_free (err); - return NULL; - } - - return (NMVPNManager *) g_object_new (NM_TYPE_VPN_MANAGER, - NM_OBJECT_DBUS_CONNECTION, connection, - NM_OBJECT_DBUS_PATH, NM_DBUS_PATH_VPN, - NULL); - -} - -NMVPNConnection * -nm_vpn_manager_connect (NMVPNManager *manager, - const char *connection_type, - const char *connection_path, - NMDevice *device) -{ - char *vpn_connection = NULL; - GError *err = NULL; - - g_return_val_if_fail (NM_IS_VPN_MANAGER (manager), NULL); - g_return_val_if_fail (connection_type != NULL, NULL); - g_return_val_if_fail (connection_path, NULL); - g_return_val_if_fail (NM_IS_DEVICE (device), NULL); - - if (!org_freedesktop_NetworkManager_VPN_Manager_connect (NM_VPN_MANAGER_GET_PRIVATE (manager)->manager_proxy, - connection_type, - connection_path, - nm_object_get_path (NM_OBJECT (device)), - &vpn_connection, - &err)) { - g_warning ("Error in VPN Connect: %s", err->message); - g_error_free (err); - return NULL; - } - - return nm_vpn_connection_new (nm_object_get_connection (NM_OBJECT (manager)), vpn_connection); -} - -GSList * -nm_vpn_manager_get_connections (NMVPNManager *manager) -{ - GPtrArray *array = NULL; - GSList *list = NULL; - DBusGConnection *dbus_connection; - int i; - GError *err = NULL; - - g_return_val_if_fail (NM_IS_VPN_MANAGER (manager), NULL); - - if (!org_freedesktop_NetworkManager_VPN_Manager_list_connections (NM_VPN_MANAGER_GET_PRIVATE (manager)->manager_proxy, - &array, &err)) { - g_warning ("Error in getting VPN connections: %s", err->message); - g_error_free (err); - return NULL; - } - - dbus_connection = nm_object_get_connection (NM_OBJECT (manager)); - - for (i = 0; i < array->len; i++) - list = g_slist_prepend (list, nm_vpn_connection_new (dbus_connection, (char *) g_ptr_array_index (array, i))); - - return list; -} - -/*****************************************************************************/ - -static void -nm_vpn_manager_init (NMVPNManager *manager) -{ -} - -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) -{ - NMObject *object; - - object = (NMObject *) G_OBJECT_CLASS (nm_vpn_manager_parent_class)->constructor (type, - n_construct_params, - construct_params); - if (!object) - return NULL; - - NM_VPN_MANAGER_GET_PRIVATE (object)->manager_proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (object), - NM_DBUS_SERVICE, - nm_object_get_path (object), - NM_DBUS_INTERFACE_VPN); - return G_OBJECT (object); -} - -static void -finalize (GObject *object) -{ - g_object_unref (NM_VPN_MANAGER_GET_PRIVATE (object)->manager_proxy); - G_OBJECT_CLASS (nm_vpn_manager_parent_class)->finalize (object); -} - -static void -nm_vpn_manager_class_init (NMVPNManagerClass *manager_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (manager_class); - - g_type_class_add_private (manager_class, sizeof (NMVPNManagerPrivate)); - - /* virtual methods */ - object_class->constructor = constructor; - object_class->finalize = finalize; -} diff --git a/libnm-glib/nm-vpn-manager.h b/libnm-glib/nm-vpn-manager.h deleted file mode 100644 index 50797b4c9..000000000 --- a/libnm-glib/nm-vpn-manager.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ - -#ifndef NM_VPN_MANAGER_H -#define NM_VPN_MANAGER_H 1 - -#include -#include -#include -#include -#include -#include "nm-object.h" -#include "nm-device.h" -#include "nm-connection.h" -#include "nm-vpn-connection.h" - -G_BEGIN_DECLS - -#define NM_TYPE_VPN_MANAGER (nm_vpn_manager_get_type ()) -#define NM_VPN_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VPN_MANAGER, NMVPNManager)) -#define NM_VPN_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_VPN_MANAGER, NMVPNManagerClass)) -#define NM_IS_VPN_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_VPN_MANAGER)) -#define NM_IS_VPN_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_VPN_MANAGER)) -#define NM_VPN_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_VPN_MANAGER, NMVPNManagerClass)) - -typedef struct { - NMObject parent; -} NMVPNManager; - -typedef struct { - NMObjectClass parent; -} NMVPNManagerClass; - -GType nm_vpn_manager_get_type (void); - - -NMVPNManager *nm_vpn_manager_new (void); -NMVPNConnection *nm_vpn_manager_connect (NMVPNManager *manager, - const char *connection_type, - const char *connection_path, - NMDevice *device); - -GSList *nm_vpn_manager_get_connections (NMVPNManager *manager); - -G_END_DECLS - -#endif /* NM_MANAGER_H */ diff --git a/src/Makefile.am b/src/Makefile.am index f2eddd700..cdda0feb6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -38,6 +38,8 @@ NetworkManager_SOURCES = \ nm-hal-manager.h \ nm-ip4-config.c \ nm-ip4-config.h \ + nm-active-connection.h \ + nm-active-connection.c \ NetworkManager.c \ NetworkManagerPolicy.c \ NetworkManagerPolicy.h \ diff --git a/src/NetworkManager.c b/src/NetworkManager.c index 465d55306..7c46cdff6 100644 --- a/src/NetworkManager.c +++ b/src/NetworkManager.c @@ -303,6 +303,12 @@ main (int argc, char *argv[]) /* Initialize our DBus service & connection */ dbus_mgr = nm_dbus_manager_get (); + vpn_manager = nm_vpn_manager_get (); + if (!vpn_manager) { + nm_warning ("Failed to start the VPN manager."); + goto done; + } + manager = nm_manager_new (); if (manager == NULL) { nm_error ("Failed to initialize the network manager."); @@ -322,12 +328,6 @@ main (int argc, char *argv[]) goto done; } - vpn_manager = nm_vpn_manager_new (manager); - if (!vpn_manager) { - nm_warning ("Failed to start the VPN manager."); - goto done; - } - named_mgr = nm_named_manager_get (); if (!named_mgr) { nm_warning ("Failed to start the named manager."); @@ -354,9 +354,6 @@ main (int argc, char *argv[]) g_main_loop_run (main_loop); done: - if (vpn_manager) - g_object_unref (vpn_manager); - if (hal_manager) nm_hal_manager_destroy (hal_manager); @@ -366,6 +363,9 @@ done: if (manager) g_object_unref (manager); + if (vpn_manager) + g_object_unref (vpn_manager); + if (sup_mgr) g_object_unref (sup_mgr); diff --git a/src/NetworkManagerPolicy.c b/src/NetworkManagerPolicy.c index 7e3171492..22d3f3d2f 100644 --- a/src/NetworkManagerPolicy.c +++ b/src/NetworkManagerPolicy.c @@ -214,17 +214,22 @@ auto_activate_device (gpointer user_data) best_connection = nm_device_get_best_auto_connection (data->device, connections, &specific_object); if (best_connection) { GError *error = NULL; + const char *device_path; - if (!nm_manager_activate_device (policy->manager, - data->device, - best_connection, - specific_object, - FALSE, - &error)) { - nm_warning ("Failed to automatically activate device %s: (%d) %s", - nm_device_get_iface (data->device), - error->code, - error->message); + device_path = nm_device_get_udi (data->device); + if (!nm_manager_activate_connection (policy->manager, + best_connection, + specific_object, + device_path, + FALSE, + &error)) { + NMSettingConnection *s_con; + + s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (best_connection, NM_TYPE_SETTING_CONNECTION)); + g_assert (s_con); + + nm_warning ("Connection '%s' auto-activation failed: (%d) %s", + s_con->id, error->code, error->message); g_error_free (error); } } @@ -476,23 +481,30 @@ connection_removed (NMManager *manager, NMConnectionScope scope, gpointer user_data) { - GSList *iter; + NMSettingConnection *s_con; + GPtrArray *list; + int i; - /* If the connection just removed was active, deactive it */ - for (iter = nm_manager_get_devices (manager); iter; iter = g_slist_next (iter)) { - NMDevice *device = NM_DEVICE (iter->data); - NMActRequest *req = nm_device_get_act_request (device); - NMConnection *dev_connection; + s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION)); + if (!s_con) + return; - if (!req) - continue; + list = nm_manager_get_active_connections_by_connection (manager, connection); + if (!list) + return; - dev_connection = nm_act_request_get_connection (req); - if (dev_connection == connection) { - nm_device_interface_deactivate (NM_DEVICE_INTERFACE (device)); - schedule_activate_check ((NMPolicy *) user_data, device); + for (i = 0; i < list->len; i++) { + char *path = g_ptr_array_index (list, i); + GError *error = NULL; + + if (!nm_manager_deactivate_connection (manager, path, &error)) { + nm_warning ("Connection '%s' disappeared, but error deactivating it: (%d) %s", + s_con->id, error->code, error->message); + g_error_free (error); } + g_free (path); } + g_ptr_array_free (list, TRUE); } NMPolicy * diff --git a/src/marshallers/nm-marshal.list b/src/marshallers/nm-marshal.list index e6443022b..8370d4dac 100644 --- a/src/marshallers/nm-marshal.list +++ b/src/marshallers/nm-marshal.list @@ -8,3 +8,5 @@ VOID:UINT,UINT VOID:STRING,STRING VOID:STRING,UCHAR VOID:STRING,OBJECT +VOID:OBJECT,UINT,UINT + diff --git a/src/nm-activation-request.c b/src/nm-activation-request.c index 1d4d7259b..02e9817f0 100644 --- a/src/nm-activation-request.c +++ b/src/nm-activation-request.c @@ -30,7 +30,7 @@ #include "nm-dbus-manager.h" #include "nm-device.h" #include "nm-properties-changed-signal.h" -#include "nm-active-connection-glue.h" +#include "nm-active-connection.h" #include "nm-manager.h" /* FIXME! */ @@ -69,6 +69,7 @@ enum { PROP_SHARED_SERVICE_NAME, PROP_SHARED_CONNECTION, PROP_DEVICES, + PROP_VPN, LAST_PROP }; @@ -82,8 +83,6 @@ nm_act_request_new (NMConnection *connection, { GObject *object; NMActRequestPrivate *priv; - DBusGConnection *g_connection; - static guint32 counter = 0; g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); g_return_val_if_fail (NM_DEVICE (device), NULL); @@ -100,16 +99,22 @@ nm_act_request_new (NMConnection *connection, priv->device = NM_DEVICE (device); priv->user_requested = user_requested; - g_connection = nm_dbus_manager_get_connection (nm_dbus_manager_get ()); - priv->ac_path = g_strdup_printf (NM_DBUS_PATH "/ActiveConnection/%d", counter++); - dbus_g_connection_register_g_object (g_connection, priv->ac_path, object); - return NM_ACT_REQUEST (object); } static void nm_act_request_init (NMActRequest *req) { + NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (req); + NMDBusManager *dbus_mgr; + + priv->ac_path = nm_active_connection_get_next_object_path (); + + dbus_mgr = nm_dbus_manager_get (); + dbus_g_connection_register_g_object (nm_dbus_manager_get_connection (dbus_mgr), + priv->ac_path, + G_OBJECT (req)); + g_object_unref (dbus_mgr); } static void @@ -152,27 +157,6 @@ finalize (GObject *object) G_OBJECT_CLASS (nm_act_request_parent_class)->finalize (object); } -static void -scope_to_value (NMConnection *connection, GValue *value) -{ - if (!connection) { - g_value_set_string (value, ""); - return; - } - - switch (nm_connection_get_scope (connection)) { - case NM_CONNECTION_SCOPE_SYSTEM: - g_value_set_string (value, NM_DBUS_SERVICE_SYSTEM_SETTINGS); - break; - case NM_CONNECTION_SCOPE_USER: - g_value_set_string (value, NM_DBUS_SERVICE_USER_SETTINGS); - break; - default: - g_warning ("%s: unknown connection scope!", __func__); - break; - } -} - static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) @@ -182,7 +166,7 @@ get_property (GObject *object, guint prop_id, switch (prop_id) { case PROP_SERVICE_NAME: - scope_to_value (priv->connection, value); + nm_active_connection_scope_to_value (priv->connection, value); break; case PROP_CONNECTION: g_value_set_boxed (value, nm_connection_get_path (priv->connection)); @@ -194,7 +178,7 @@ get_property (GObject *object, guint prop_id, g_value_set_boxed (value, "/"); break; case PROP_SHARED_SERVICE_NAME: - scope_to_value (priv->shared, value); + nm_active_connection_scope_to_value (priv->shared, value); break; case PROP_SHARED_CONNECTION: if (!priv->shared) { @@ -208,6 +192,9 @@ get_property (GObject *object, guint prop_id, g_ptr_array_add (devices, g_strdup (nm_device_get_udi (priv->device))); g_value_take_boxed (value, devices); break; + case PROP_VPN: + g_value_set_boolean (value, FALSE); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -269,6 +256,13 @@ nm_act_request_class_init (NMActRequestClass *req_class) "Devices", dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), G_PARAM_READABLE)); + g_object_class_install_property + (object_class, PROP_VPN, + g_param_spec_boolean (NM_ACTIVE_CONNECTION_VPN, + "VPN", + "Is a VPN connection", + FALSE, + G_PARAM_READABLE)); /* Signals */ signals[CONNECTION_SECRETS_UPDATED] = @@ -295,8 +289,7 @@ nm_act_request_class_init (NMActRequestClass *req_class) nm_properties_changed_signal_new (object_class, G_STRUCT_OFFSET (NMActRequestClass, properties_changed)); - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (req_class), - &dbus_glib_nm_active_connection_object_info); + nm_active_connection_install_type_info (object_class); } typedef struct GetSecretsInfo { diff --git a/src/nm-activation-request.h b/src/nm-activation-request.h index 2ed7427de..b7f43e707 100644 --- a/src/nm-activation-request.h +++ b/src/nm-activation-request.h @@ -25,6 +25,7 @@ #include #include #include "nm-connection.h" +#include "nm-active-connection.h" #define NM_TYPE_ACT_REQUEST (nm_act_request_get_type ()) #define NM_ACT_REQUEST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_ACT_REQUEST, NMActRequest)) @@ -33,13 +34,6 @@ #define NM_IS_ACT_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_ACT_REQUEST)) #define NM_ACT_REQUEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_ACT_REQUEST, NMActRequestClass)) -#define NM_ACTIVE_CONNECTION_SERVICE_NAME "service-name" -#define NM_ACTIVE_CONNECTION_CONNECTION "connection" -#define NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT "specific-object" -#define NM_ACTIVE_CONNECTION_SHARED_SERVICE_NAME "shared-service-name" -#define NM_ACTIVE_CONNECTION_SHARED_CONNECTION "shared-connection" -#define NM_ACTIVE_CONNECTION_DEVICES "devices" - typedef struct { GObject parent; } NMActRequest; diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c new file mode 100644 index 000000000..dc6342675 --- /dev/null +++ b/src/nm-active-connection.c @@ -0,0 +1,63 @@ +/* NetworkManager -- Network link manager + * + * Dan Williams + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * (C) Copyright 2008 Red Hat, Inc. + */ + +#include +#include "nm-active-connection.h" +#include "NetworkManager.h" +#include "nm-active-connection-glue.h" + +char * +nm_active_connection_get_next_object_path (void) +{ + static guint32 counter = 0; + + return g_strdup_printf (NM_DBUS_PATH "/ActiveConnection/%d", counter++); +} + +void +nm_active_connection_install_type_info (GObjectClass *klass) +{ + dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_active_connection_object_info); +} + +void +nm_active_connection_scope_to_value (NMConnection *connection, GValue *value) +{ + if (!connection) { + g_value_set_string (value, ""); + return; + } + + switch (nm_connection_get_scope (connection)) { + case NM_CONNECTION_SCOPE_SYSTEM: + g_value_set_string (value, NM_DBUS_SERVICE_SYSTEM_SETTINGS); + break; + case NM_CONNECTION_SCOPE_USER: + g_value_set_string (value, NM_DBUS_SERVICE_USER_SETTINGS); + break; + default: + g_warning ("%s: unknown connection scope!", __func__); + break; + } +} + + diff --git a/src/nm-active-connection.h b/src/nm-active-connection.h new file mode 100644 index 000000000..699836b43 --- /dev/null +++ b/src/nm-active-connection.h @@ -0,0 +1,42 @@ +/* NetworkManager -- Network link manager + * + * Dan Williams + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * (C) Copyright 2008 Red Hat, Inc. + */ + +#ifndef NM_ACTIVE_CONNECTION_H +#define NM_ACTIVE_CONNECTION_H + +#include +#include "nm-connection.h" + +#define NM_ACTIVE_CONNECTION_SERVICE_NAME "service-name" +#define NM_ACTIVE_CONNECTION_CONNECTION "connection" +#define NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT "specific-object" +#define NM_ACTIVE_CONNECTION_SHARED_SERVICE_NAME "shared-service-name" +#define NM_ACTIVE_CONNECTION_SHARED_CONNECTION "shared-connection" +#define NM_ACTIVE_CONNECTION_DEVICES "devices" +#define NM_ACTIVE_CONNECTION_VPN "vpn" + +char *nm_active_connection_get_next_object_path (void); + +void nm_active_connection_install_type_info (GObjectClass *klass); + +void nm_active_connection_scope_to_value (NMConnection *connection, GValue *value); + +#endif /* NM_ACTIVE_CONNECTION_H */ diff --git a/src/nm-manager.c b/src/nm-manager.c index 9982f2f70..e1595ec16 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -6,12 +6,14 @@ #include "nm-manager.h" #include "nm-utils.h" #include "nm-dbus-manager.h" +#include "nm-vpn-manager.h" #include "nm-device-interface.h" #include "nm-device-802-11-wireless.h" #include "NetworkManagerSystem.h" #include "nm-properties-changed-signal.h" #include "nm-setting-connection.h" #include "nm-setting-wireless.h" +#include "nm-setting-vpn.h" #include "nm-marshal.h" static gboolean impl_manager_get_devices (NMManager *manager, GPtrArray **devices, GError **err); @@ -49,10 +51,10 @@ static void connection_added_default_handler (NMManager *manager, typedef struct { DBusGMethodInvocation *context; - NMDevice *device; NMConnectionScope scope; char *connection_path; char *specific_object_path; + char *device_path; guint timeout_id; } PendingConnectionInfo; @@ -74,6 +76,11 @@ typedef struct { gboolean sleeping; guint poke_id; + + NMVPNManager *vpn_manager; + guint vpn_manager_id; + + gboolean disposed; } NMManagerPrivate; #define NM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MANAGER, NMManagerPrivate)) @@ -159,10 +166,21 @@ nm_manager_error_get_type (void) return etype; } +static void +vpn_manager_connection_deactivated_cb (NMVPNManager *manager, + NMVPNConnection *vpn, + NMVPNConnectionState state, + NMVPNConnectionStateReason reason, + gpointer user_data) +{ + g_object_notify (G_OBJECT (user_data), NM_MANAGER_ACTIVE_CONNECTIONS); +} + static void nm_manager_init (NMManager *manager) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); + guint id; priv->wireless_enabled = TRUE; priv->wireless_hw_enabled = TRUE; @@ -180,6 +198,11 @@ nm_manager_init (NMManager *manager) g_str_equal, g_free, g_object_unref); + + priv->vpn_manager = nm_vpn_manager_get (); + id = g_signal_connect (G_OBJECT (priv->vpn_manager), "connection-deactivated", + G_CALLBACK (vpn_manager_connection_deactivated_cb), manager); + priv->vpn_manager_id = id; } NMState @@ -239,17 +262,23 @@ pending_connection_info_destroy (PendingConnectionInfo *info) g_free (info->connection_path); g_free (info->specific_object_path); - g_object_unref (info->device); + g_free (info->device_path); g_slice_free (PendingConnectionInfo, info); } static void -finalize (GObject *object) +dispose (GObject *object) { NMManager *manager = NM_MANAGER (object); NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); + if (priv->disposed) { + G_OBJECT_CLASS (nm_manager_parent_class)->dispose (object); + return; + } + priv->disposed = TRUE; + pending_connection_info_destroy (priv->pending_connection_info); priv->pending_connection_info = NULL; @@ -269,10 +298,15 @@ finalize (GObject *object) priv->poke_id = 0; } - if (priv->dbus_mgr) - g_object_unref (priv->dbus_mgr); + if (priv->vpn_manager_id) { + g_source_remove (priv->vpn_manager_id); + priv->vpn_manager_id = 0; + } + g_object_unref (priv->vpn_manager); - G_OBJECT_CLASS (nm_manager_parent_class)->finalize (object); + g_object_unref (priv->dbus_mgr); + + G_OBJECT_CLASS (nm_manager_parent_class)->dispose (object); } static void @@ -289,15 +323,49 @@ set_property (GObject *object, guint prop_id, } } +static GPtrArray * +get_active_connections (NMManager *manager, NMConnection *filter) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); + NMVPNManager *vpn_manager; + GPtrArray *active; + GSList *iter; + + active = g_ptr_array_sized_new (3); + + /* Add active device connections */ + for (iter = priv->devices; iter; iter = g_slist_next (iter)) { + NMActRequest *req; + const char *path; + + req = nm_device_get_act_request (NM_DEVICE (iter->data)); + if (!req) + continue; + + if (!filter || (nm_act_request_get_connection (req) == filter)) { + path = nm_act_request_get_active_connection_path (req); + g_ptr_array_add (active, g_strdup (path)); + } + } + + /* Add active VPN connections */ + vpn_manager = nm_vpn_manager_get (); + nm_vpn_manager_add_active_connections (vpn_manager, filter, active); + g_object_unref (vpn_manager); + + return active; +} + static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (object); + NMManager *self = NM_MANAGER (object); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); switch (prop_id) { case PROP_STATE: - nm_manager_update_state (NM_MANAGER (object)); + nm_manager_update_state (self); g_value_set_uint (value, priv->state); break; case PROP_WIRELESS_ENABLED: @@ -306,25 +374,9 @@ get_property (GObject *object, guint prop_id, case PROP_WIRELESS_HARDWARE_ENABLED: g_value_set_boolean (value, priv->wireless_hw_enabled); break; - case PROP_ACTIVE_CONNECTIONS: { - GPtrArray *active; - GSList *iter; - - active = g_ptr_array_sized_new (2); - for (iter = priv->devices; iter; iter = g_slist_next (iter)) { - NMActRequest *req; - const char *path; - - req = nm_device_get_act_request (NM_DEVICE (iter->data)); - if (!req) - continue; - - path = nm_act_request_get_active_connection_path (req); - g_ptr_array_add (active, g_strdup (path)); - } - g_value_take_boxed (value, active); + case PROP_ACTIVE_CONNECTIONS: + g_value_take_boxed (value, get_active_connections (self, NULL)); break; - } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -343,7 +395,7 @@ nm_manager_class_init (NMManagerClass *manager_class) object_class->set_property = set_property; object_class->get_property = get_property; - object_class->finalize = finalize; + object_class->dispose = dispose; /* properties */ g_object_class_install_property @@ -1261,6 +1313,37 @@ nm_manager_get_device_by_udi (NMManager *manager, const char *udi) return NULL; } +static NMActRequest * +nm_manager_get_act_request_by_path (NMManager *manager, + const char *path, + NMDevice **device) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); + GSList *iter; + + g_return_val_if_fail (manager != NULL, NULL); + g_return_val_if_fail (path != NULL, NULL); + g_return_val_if_fail (device != NULL, NULL); + g_return_val_if_fail (*device == NULL, NULL); + + for (iter = priv->devices; iter; iter = g_slist_next (iter)) { + NMActRequest *req; + const char *ac_path; + + req = nm_device_get_act_request (NM_DEVICE (iter->data)); + if (!req) + continue; + + ac_path = nm_act_request_get_active_connection_path (req); + if (!strcmp (path, ac_path)) { + *device = NM_DEVICE (iter->data); + return req; + } + } + + return NULL; +} + static gboolean check_connection_allowed (NMManager *manager, NMDeviceInterface *dev_iface, @@ -1296,13 +1379,13 @@ check_connection_allowed (NMManager *manager, return allowed; } -const char * -nm_manager_activate_device (NMManager *manager, - NMDevice *device, - NMConnection *connection, - const char *specific_object, - gboolean user_requested, - GError **error) +static const char * +internal_activate_device (NMManager *manager, + NMDevice *device, + NMConnection *connection, + const char *specific_object, + gboolean user_requested, + GError **error) { NMActRequest *req; NMDeviceInterface *dev_iface; @@ -1348,16 +1431,11 @@ wait_for_connection_expired (gpointer data) g_return_val_if_fail (info != NULL, FALSE); - nm_info ("%s: didn't receive connection details soon enough for activation.", - nm_device_get_iface (info->device)); - g_set_error (&error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_CONNECTION, "%s", "Connection was not provided by any settings service"); - nm_warning ("Failed to activate device %s: (%d) %s", - nm_device_get_iface (info->device), - error->code, - error->message); + nm_warning ("Connection (%d) %s failed to activate (timeout): (%d) %s", + info->scope, info->connection_path, error->code, error->message); dbus_g_method_return_error (info->context, error); g_error_free (error); @@ -1368,6 +1446,74 @@ wait_for_connection_expired (gpointer data) return FALSE; } +const char * +nm_manager_activate_connection (NMManager *manager, + NMConnection *connection, + const char *specific_object, + const char *device_path, + gboolean user_requested, + GError **error) +{ + NMDevice *device = NULL; + char *path = NULL; + NMSettingConnection *s_con; + + g_return_val_if_fail (manager != NULL, NULL); + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (error != NULL, NULL); + g_return_val_if_fail (*error == NULL, NULL); + + s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION)); + g_assert (s_con); + + if (!strcmp (s_con->type, NM_SETTING_VPN_SETTING_NAME)) { + NMActRequest *req; + NMVPNManager *vpn_manager; + + /* VPN connection */ + req = nm_manager_get_act_request_by_path (manager, specific_object, &device); + if (!req) { + g_set_error (error, + NM_MANAGER_ERROR, NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE, + "%s", "Base connection for VPN connection not active."); + return NULL; + } + + if (!device) { + g_set_error (error, + NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "%s", "Source connection had no active device."); + return NULL; + } + + vpn_manager = nm_vpn_manager_get (); + path = (char *) nm_vpn_manager_activate_connection (vpn_manager, + connection, + req, + device, + error); + g_object_unref (vpn_manager); + } else { + /* Device-based connection */ + device = nm_manager_get_device_by_path (manager, device_path); + if (!device) { + g_set_error (error, + NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "%s", "Device not found"); + return NULL; + } + + path = (char *) internal_activate_device (manager, + device, + connection, + specific_object, + user_requested, + error); + } + + return path; +} + static void connection_added_default_handler (NMManager *manager, NMConnection *connection, @@ -1390,21 +1536,19 @@ connection_added_default_handler (NMManager *manager, /* Will destroy below; can't be valid during the initial activation start */ priv->pending_connection_info = NULL; - path = nm_manager_activate_device (manager, - info->device, - connection, - info->specific_object_path, - TRUE, - &error); + path = nm_manager_activate_connection (manager, + connection, + info->specific_object_path, + info->device_path, + TRUE, + &error); if (path) { dbus_g_method_return (info->context, path); g_object_notify (G_OBJECT (manager), NM_MANAGER_ACTIVE_CONNECTIONS); } else { dbus_g_method_return_error (info->context, error); - nm_warning ("Failed to activate device %s: (%d) %s", - nm_device_get_iface (info->device), - error->code, - error->message); + nm_warning ("Connection (%d) %s failed to activate: (%d) %s", + scope, info->connection_path, error->code, error->message); g_error_free (error); } @@ -1419,21 +1563,11 @@ impl_manager_activate_connection (NMManager *manager, const char *specific_object_path, DBusGMethodInvocation *context) { - NMDevice *device; - NMConnectionScope scope; + NMConnectionScope scope = NM_CONNECTION_SCOPE_UNKNOWN; NMConnection *connection; GError *error = NULL; char *real_sop = NULL; - - device = nm_manager_get_device_by_path (manager, device_path); - if (!device) { - g_set_error (&error, - NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, - "%s", "Device not found"); - goto err; - } - - nm_info ("User request for activation of %s.", nm_device_get_iface (device)); + char *path = NULL; if (!strcmp (service_name, NM_DBUS_SERVICE_USER_SETTINGS)) scope = NM_CONNECTION_SCOPE_USER; @@ -1452,14 +1586,12 @@ impl_manager_activate_connection (NMManager *manager, connection = nm_manager_get_connection_by_object_path (manager, scope, connection_path); if (connection) { - const char *path; - - path = nm_manager_activate_device (manager, - device, - connection, - real_sop, - TRUE, - &error); + path = (char *) nm_manager_activate_connection (manager, + connection, + real_sop, + device_path, + TRUE, + &error); if (path) { dbus_g_method_return (context, path); g_object_notify (G_OBJECT (manager), NM_MANAGER_ACTIVE_CONNECTIONS); @@ -1479,7 +1611,7 @@ impl_manager_activate_connection (NMManager *manager, info = g_slice_new0 (PendingConnectionInfo); info->context = context; - info->device = g_object_ref (device); + info->device_path = g_strdup (device_path); info->scope = scope; info->connection_path = g_strdup (connection_path); info->specific_object_path = g_strdup (real_sop); @@ -1492,24 +1624,25 @@ impl_manager_activate_connection (NMManager *manager, err: if (error) { dbus_g_method_return_error (context, error); - nm_warning ("Failed to activate device %s: (%d) %s", - nm_device_get_iface (device), - error->code, - error->message); + nm_warning ("Connection (%d) %s failed to activate: (%d) %s", + scope, connection_path, error->code, error->message); g_error_free (error); } g_free (real_sop); } -static gboolean -impl_manager_deactivate_connection (NMManager *manager, - const char *connection_path, - GError **error) +gboolean +nm_manager_deactivate_connection (NMManager *manager, + const char *connection_path, + GError **error) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); + NMVPNManager *vpn_manager; GSList *iter; + gboolean success = FALSE; + /* Check for device connections first */ for (iter = priv->devices; iter; iter = g_slist_next (iter)) { NMDevice *device = NM_DEVICE (iter->data); NMActRequest *req; @@ -1521,15 +1654,33 @@ impl_manager_deactivate_connection (NMManager *manager, if (!strcmp (connection_path, nm_act_request_get_active_connection_path (req))) { nm_device_interface_deactivate (NM_DEVICE_INTERFACE (device)); g_object_notify (G_OBJECT (manager), NM_MANAGER_ACTIVE_CONNECTIONS); - return TRUE; + success = TRUE; + goto done; } } - g_set_error (error, - NM_MANAGER_ERROR, NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE, - "%s", "The connection was not active."); - - return FALSE; + /* Check for VPN connections next */ + vpn_manager = nm_vpn_manager_get (); + if (nm_vpn_manager_deactivate_connection (vpn_manager, connection_path)) { + success = TRUE; + } else { + g_set_error (error, + NM_MANAGER_ERROR, NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE, + "%s", "The connection was not active."); + } + g_object_unref (vpn_manager); + +done: + g_object_notify (G_OBJECT (manager), NM_MANAGER_ACTIVE_CONNECTIONS); + return success; +} + +static gboolean +impl_manager_deactivate_connection (NMManager *manager, + const char *connection_path, + GError **error) +{ + return nm_manager_deactivate_connection (manager, connection_path, error); } gboolean @@ -1611,23 +1762,6 @@ impl_manager_sleep (NMManager *manager, gboolean sleep, GError **err) return TRUE; } -NMDevice * -nm_manager_get_active_device (NMManager *manager) -{ - GSList *iter; - - g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); - - for (iter = nm_manager_get_devices (manager); iter; iter = iter->next) { - NMDevice *dev = NM_DEVICE (iter->data); - - if (nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED) - return dev; - } - - return NULL; -} - /* Legacy 0.6 compatibility interface */ static gboolean @@ -1732,3 +1866,10 @@ nm_manager_get_connection_by_object_path (NMManager *manager, return connection; } +GPtrArray * +nm_manager_get_active_connections_by_connection (NMManager *manager, + NMConnection *connection) +{ + return get_active_connections (manager, connection); +} + diff --git a/src/nm-manager.h b/src/nm-manager.h index 69627567a..bf19a0043 100644 --- a/src/nm-manager.h +++ b/src/nm-manager.h @@ -62,14 +62,16 @@ GSList *nm_manager_get_devices (NMManager *manager); NMDevice *nm_manager_get_device_by_path (NMManager *manager, const char *path); NMDevice *nm_manager_get_device_by_udi (NMManager *manager, const char *udi); -NMDevice *nm_manager_get_active_device (NMManager *manager); +const char * nm_manager_activate_connection (NMManager *manager, + NMConnection *connection, + const char *specific_object, + const char *device_path, + gboolean user_requested, + GError **error); -const char *nm_manager_activate_device (NMManager *manager, - NMDevice *device, - NMConnection *connection, - const char *specific_object, - gboolean user_requested, - GError **error); +gboolean nm_manager_deactivate_connection (NMManager *manager, + const char *connection_path, + GError **error); gboolean nm_manager_activation_pending (NMManager *manager); @@ -90,4 +92,7 @@ NMConnection * nm_manager_get_connection_by_object_path (NMManager *manager, NMConnectionScope scope, const char *path); +GPtrArray * nm_manager_get_active_connections_by_connection (NMManager *manager, + NMConnection *connection); + #endif /* NM_MANAGER_H */ diff --git a/src/vpn-manager/Makefile.am b/src/vpn-manager/Makefile.am index 5c4fa6a3f..9b8b0a589 100644 --- a/src/vpn-manager/Makefile.am +++ b/src/vpn-manager/Makefile.am @@ -28,9 +28,6 @@ libvpn_manager_la_LIBADD = \ $(top_builddir)/src/marshallers/libmarshallers.la \ $(top_builddir)/libnm-util/libnm-util.la -nm-vpn-manager-glue.h: $(top_srcdir)/introspection/nm-vpn-manager.xml - dbus-binding-tool --prefix=nm_vpn_manager --mode=glib-server --output=nm-vpn-manager-glue.h $(top_srcdir)/introspection/nm-vpn-manager.xml - nm-vpn-connection-glue.h: $(top_srcdir)/introspection/nm-vpn-connection.xml dbus-binding-tool --prefix=nm_vpn_connection --mode=glib-server --output=nm-vpn-connection-glue.h $(top_srcdir)/introspection/nm-vpn-connection.xml @@ -39,7 +36,6 @@ nm-vpn-plugin-bindings.h: $(top_srcdir)/introspection/nm-vpn-plugin.xml built_sources = \ - nm-vpn-manager-glue.h \ nm-vpn-connection-glue.h \ nm-vpn-plugin-bindings.h diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c index b540b5bfb..3a43b655b 100644 --- a/src/vpn-manager/nm-vpn-connection.c +++ b/src/vpn-manager/nm-vpn-connection.c @@ -18,7 +18,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - * (C) Copyright 2005 Red Hat, Inc. + * (C) Copyright 2008 Red Hat, Inc. */ @@ -39,8 +39,8 @@ #include "nm-utils.h" #include "nm-vpn-plugin-bindings.h" #include "nm-marshal.h" - -static gboolean impl_vpn_connection_disconnect (NMVPNConnection *connection, GError **err); +#include "nm-active-connection.h" +#include "nm-properties-changed-signal.h" #define CONNECTION_GET_SECRETS_CALL_TAG "get-secrets-call" @@ -49,10 +49,13 @@ static gboolean impl_vpn_connection_disconnect (NMVPNConnection *connection, GEr G_DEFINE_TYPE (NMVPNConnection, nm_vpn_connection, G_TYPE_OBJECT) typedef struct { + gboolean disposed; + NMConnection *connection; + NMActRequest *act_request; NMDevice *parent_dev; - char *object_path; - + char *ac_path; + NMVPNConnectionState state; gulong device_monitor; DBusGProxy *proxy; @@ -65,6 +68,7 @@ typedef struct { #define NM_VPN_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_VPN_CONNECTION, NMVPNConnectionPrivate)) enum { + PROPERTIES_CHANGED, STATE_CHANGED, LAST_SIGNAL @@ -74,7 +78,13 @@ static guint signals[LAST_SIGNAL] = { 0 }; enum { PROP_0, - PROP_NAME, + PROP_SERVICE_NAME, + PROP_CONNECTION, + PROP_SPECIFIC_OBJECT, + PROP_SHARED_SERVICE_NAME, + PROP_SHARED_CONNECTION, + PROP_DEVICES, + PROP_VPN, PROP_STATE, PROP_BANNER, @@ -116,12 +126,14 @@ device_state_changed (NMDevice *device, NMDeviceState state, gpointer user_data) NMVPNConnection * nm_vpn_connection_new (NMConnection *connection, - NMDevice *parent_device) + NMActRequest *act_request, + NMDevice *parent_device) { NMVPNConnection *vpn_connection; NMVPNConnectionPrivate *priv; g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); + g_return_val_if_fail (NM_IS_ACT_REQUEST (act_request), NULL); g_return_val_if_fail (NM_IS_DEVICE (parent_device), NULL); vpn_connection = (NMVPNConnection *) g_object_new (NM_TYPE_VPN_CONNECTION, NULL); @@ -131,6 +143,7 @@ nm_vpn_connection_new (NMConnection *connection, priv = NM_VPN_CONNECTION_GET_PRIVATE (vpn_connection); priv->connection = g_object_ref (connection); + priv->act_request = g_object_ref (act_request); priv->parent_dev = g_object_ref (parent_device); priv->device_monitor = g_signal_connect (parent_device, "state-changed", @@ -167,24 +180,27 @@ plugin_state_changed (DBusGProxy *proxy, { NMVPNConnection *connection = NM_VPN_CONNECTION (user_data); - nm_debug ("plugin state changed: %d", state); + nm_info ("VPN plugin state changed: %d", state); - if (state == NM_VPN_SERVICE_STATE_STOPPED) { - switch (nm_vpn_connection_get_state (connection)) { - case NM_VPN_CONNECTION_STATE_CONNECT: - case NM_VPN_CONNECTION_STATE_IP_CONFIG_GET: - nm_vpn_connection_set_state (connection, - NM_VPN_CONNECTION_STATE_FAILED, - NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED); - break; - case NM_VPN_CONNECTION_STATE_ACTIVATED: - nm_vpn_connection_set_state (connection, - NM_VPN_CONNECTION_STATE_DISCONNECTED, - NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED); - break; - default: - break; - } + if (state != NM_VPN_SERVICE_STATE_STOPPED) + return; + + switch (nm_vpn_connection_get_state (connection)) { + case NM_VPN_CONNECTION_STATE_PREPARE: + case NM_VPN_CONNECTION_STATE_NEED_AUTH: + case NM_VPN_CONNECTION_STATE_CONNECT: + case NM_VPN_CONNECTION_STATE_IP_CONFIG_GET: + nm_vpn_connection_set_state (connection, + NM_VPN_CONNECTION_STATE_FAILED, + NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED); + break; + case NM_VPN_CONNECTION_STATE_ACTIVATED: + nm_vpn_connection_set_state (connection, + NM_VPN_CONNECTION_STATE_DISCONNECTED, + NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED); + break; + default: + break; } } @@ -431,11 +447,11 @@ nm_vpn_connection_activate (NMVPNConnection *connection) } const char * -nm_vpn_connection_get_object_path (NMVPNConnection *connection) +nm_vpn_connection_get_active_connection_path (NMVPNConnection *connection) { g_return_val_if_fail (NM_IS_VPN_CONNECTION (connection), NULL); - return NM_VPN_CONNECTION_GET_PRIVATE (connection)->object_path; + return NM_VPN_CONNECTION_GET_PRIVATE (connection)->ac_path; } const char * @@ -452,6 +468,14 @@ nm_vpn_connection_get_name (NMVPNConnection *connection) return setting->id; } +NMConnection * +nm_vpn_connection_get_connection (NMVPNConnection *connection) +{ + g_return_val_if_fail (NM_IS_VPN_CONNECTION (connection), NULL); + + return NM_VPN_CONNECTION_GET_PRIVATE (connection)->connection; +} + NMVPNConnectionState nm_vpn_connection_get_state (NMVPNConnection *connection) { @@ -490,14 +514,6 @@ nm_vpn_connection_disconnect (NMVPNConnection *connection, reason); } -static gboolean -impl_vpn_connection_disconnect (NMVPNConnection *connection, GError **err) -{ - nm_vpn_connection_disconnect (connection, NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED); - - return TRUE; -} - /******************************************************************************/ static void @@ -737,12 +753,15 @@ connection_state_changed (NMVPNConnection *connection, } if (priv->ip4_config) { + NMIP4Config *dev_ip4_config; + /* Remove attributes of the VPN's IP4 Config */ nm_system_vpn_device_unset_from_ip4_config (priv->parent_dev, priv->tundev, priv->ip4_config); /* Reset routes, nameservers, and domains of the currently active device */ - nm_device_set_ip4_config (priv->parent_dev, - NM_IP4_CONFIG (g_object_ref (nm_device_get_ip4_config (priv->parent_dev)))); + dev_ip4_config = nm_device_get_ip4_config (priv->parent_dev); + if (dev_ip4_config) + nm_device_set_ip4_config (priv->parent_dev, g_object_ref (dev_ip4_config)); } if (priv->banner) { @@ -760,23 +779,28 @@ nm_vpn_connection_init (NMVPNConnection *connection) { NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); NMDBusManager *dbus_mgr; - static guint32 counter = 0; priv->state = NM_VPN_CONNECTION_STATE_PREPARE; - priv->object_path = g_strdup_printf (NM_DBUS_PATH_VPN_CONNECTION "/%d", counter++); + priv->ac_path = nm_active_connection_get_next_object_path (); dbus_mgr = nm_dbus_manager_get (); dbus_g_connection_register_g_object (nm_dbus_manager_get_connection (dbus_mgr), - priv->object_path, + priv->ac_path, G_OBJECT (connection)); g_object_unref (dbus_mgr); } static void -finalize (GObject *object) +dispose (GObject *object) { NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (object); + if (priv->disposed) { + G_OBJECT_CLASS (nm_vpn_connection_parent_class)->dispose (object); + return; + } + priv->disposed = TRUE; + if (priv->parent_dev) { if (priv->device_monitor) g_signal_handler_disconnect (priv->parent_dev, priv->device_monitor); @@ -784,11 +808,6 @@ finalize (GObject *object) g_object_unref (priv->parent_dev); } - if (priv->banner) - g_free (priv->banner); - - g_free (priv->tundev); - if (priv->ip4_config) g_object_unref (priv->ip4_config); @@ -800,7 +819,17 @@ finalize (GObject *object) g_object_unref (priv->connection); - g_free (priv->object_path); + G_OBJECT_CLASS (nm_vpn_connection_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (object); + + g_free (priv->banner); + g_free (priv->tundev); + g_free (priv->ac_path); G_OBJECT_CLASS (nm_vpn_connection_parent_class)->finalize (object); } @@ -809,18 +838,35 @@ static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - const char *tmp; + NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (object); switch (prop_id) { - case PROP_NAME: - g_value_set_string (value, nm_vpn_connection_get_name (NM_VPN_CONNECTION (object))); + case PROP_SERVICE_NAME: + nm_active_connection_scope_to_value (priv->connection, value); + break; + case PROP_CONNECTION: + g_value_set_boxed (value, nm_connection_get_path (priv->connection)); + break; + case PROP_SPECIFIC_OBJECT: + g_value_set_boxed (value, nm_act_request_get_active_connection_path (priv->act_request)); + break; + case PROP_SHARED_SERVICE_NAME: + g_value_set_string (value, ""); + break; + case PROP_SHARED_CONNECTION: + g_value_set_boxed (value, "/"); + break; + case PROP_DEVICES: + g_value_take_boxed (value, g_ptr_array_new ()); + break; + case PROP_VPN: + g_value_set_boolean (value, TRUE); break; case PROP_STATE: g_value_set_uint (value, nm_vpn_connection_get_state (NM_VPN_CONNECTION (object))); break; case PROP_BANNER: - tmp = nm_vpn_connection_get_banner (NM_VPN_CONNECTION (object)); - g_value_set_string (value, tmp ? tmp : ""); + g_value_set_string (value, priv->banner ? priv->banner : ""); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -838,16 +884,59 @@ nm_vpn_connection_class_init (NMVPNConnectionClass *connection_class) /* virtual methods */ connection_class->state_changed = connection_state_changed; object_class->get_property = get_property; + object_class->dispose = dispose; object_class->finalize = finalize; /* properties */ g_object_class_install_property - (object_class, PROP_NAME, - g_param_spec_string (NM_VPN_CONNECTION_NAME, - "Name", - "Connection name", - NULL, - G_PARAM_READABLE)); + (object_class, PROP_SERVICE_NAME, + g_param_spec_string (NM_ACTIVE_CONNECTION_SERVICE_NAME, + "Service name", + "Service name", + NULL, + G_PARAM_READABLE)); + g_object_class_install_property + (object_class, PROP_CONNECTION, + g_param_spec_boxed (NM_ACTIVE_CONNECTION_CONNECTION, + "Connection", + "Connection", + DBUS_TYPE_G_OBJECT_PATH, + G_PARAM_READABLE)); + g_object_class_install_property + (object_class, PROP_SPECIFIC_OBJECT, + g_param_spec_string (NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT, + "Specific object", + "Specific object", + NULL, + G_PARAM_READABLE)); + g_object_class_install_property + (object_class, PROP_SHARED_SERVICE_NAME, + g_param_spec_string (NM_ACTIVE_CONNECTION_SHARED_SERVICE_NAME, + "Shared service name", + "Shared service name", + NULL, + G_PARAM_READABLE)); + g_object_class_install_property + (object_class, PROP_SHARED_CONNECTION, + g_param_spec_boxed (NM_ACTIVE_CONNECTION_SHARED_CONNECTION, + "Shared connection", + "Shared connection", + DBUS_TYPE_G_OBJECT_PATH, + G_PARAM_READABLE)); + g_object_class_install_property + (object_class, PROP_DEVICES, + g_param_spec_boxed (NM_ACTIVE_CONNECTION_DEVICES, + "Devices", + "Devices", + dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), + G_PARAM_READABLE)); + g_object_class_install_property + (object_class, PROP_VPN, + g_param_spec_boolean (NM_ACTIVE_CONNECTION_VPN, + "VPN", + "Is a VPN connection", + TRUE, + G_PARAM_READABLE)); g_object_class_install_property (object_class, PROP_STATE, @@ -878,6 +967,11 @@ nm_vpn_connection_class_init (NMVPNConnectionClass *connection_class) G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (connection_class), - &dbus_glib_nm_vpn_connection_object_info); + signals[PROPERTIES_CHANGED] = + nm_properties_changed_signal_new (object_class, + G_STRUCT_OFFSET (NMVPNConnectionClass, properties_changed)); + + dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (object_class), + &dbus_glib_nm_vpn_connection_object_info); } + diff --git a/src/vpn-manager/nm-vpn-connection.h b/src/vpn-manager/nm-vpn-connection.h index f3b4f9d3f..dc3e004e5 100644 --- a/src/vpn-manager/nm-vpn-connection.h +++ b/src/vpn-manager/nm-vpn-connection.h @@ -27,6 +27,7 @@ #include #include "NetworkManagerVPN.h" #include "nm-device.h" +#include "nm-activation-request.h" #define NM_TYPE_VPN_CONNECTION (nm_vpn_connection_get_type ()) #define NM_VPN_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VPN_CONNECTION, NMVPNConnection)) @@ -35,7 +36,6 @@ #define NM_IS_VPN_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_VPN_CONNECTION)) #define NM_VPN_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_VPN_CONNECTION, NMVPNConnectionClass)) -#define NM_VPN_CONNECTION_NAME "name" #define NM_VPN_CONNECTION_STATE "state" #define NM_VPN_CONNECTION_BANNER "banner" @@ -50,16 +50,20 @@ typedef struct { void (*state_changed) (NMVPNConnection *connection, NMVPNConnectionState state, NMVPNConnectionStateReason reason); + + void (*properties_changed) (NMVPNConnection *connection, GHashTable *properties); } NMVPNConnectionClass; GType nm_vpn_connection_get_type (void); -NMVPNConnection *nm_vpn_connection_new (NMConnection *connection, - NMDevice *parent_device); +NMVPNConnection * nm_vpn_connection_new (NMConnection *connection, + NMActRequest *act_request, + NMDevice *parent_device); void nm_vpn_connection_activate (NMVPNConnection *connection); -const char *nm_vpn_connection_get_object_path (NMVPNConnection *connection); -const char *nm_vpn_connection_get_name (NMVPNConnection *connection); +NMConnection * nm_vpn_connection_get_connection (NMVPNConnection *connection); +const char * nm_vpn_connection_get_active_connection_path (NMVPNConnection *connection); +const char * nm_vpn_connection_get_name (NMVPNConnection *connection); NMVPNConnectionState nm_vpn_connection_get_state (NMVPNConnection *connection); const char * nm_vpn_connection_get_banner (NMVPNConnection *connection); void nm_vpn_connection_fail (NMVPNConnection *connection, @@ -67,5 +71,4 @@ void nm_vpn_connection_fail (NMVPNConnection *connect void nm_vpn_connection_disconnect (NMVPNConnection *connection, NMVPNConnectionStateReason reason); - #endif /* NM_VPN_CONNECTION_H */ diff --git a/src/vpn-manager/nm-vpn-manager.c b/src/vpn-manager/nm-vpn-manager.c index 495d514de..e3b5fa64b 100644 --- a/src/vpn-manager/nm-vpn-manager.c +++ b/src/vpn-manager/nm-vpn-manager.c @@ -6,33 +6,70 @@ #include "nm-vpn-service.h" #include "nm-vpn-connection.h" #include "nm-setting-vpn.h" -#include "nm-manager.h" #include "nm-dbus-manager.h" #include "NetworkManagerVPN.h" #include "nm-utils.h" - -static gboolean impl_vpn_manager_connect (NMVPNManager *manager, - const char *connection_type, - const char *connection_path, - const char *device_path, - char **connection, - GError **err); - -static gboolean impl_vpn_manager_get_connections (NMVPNManager *manager, - GPtrArray **connections, - GError **err); - -#include "nm-vpn-manager-glue.h" +#include "nm-marshal.h" G_DEFINE_TYPE (NMVPNManager, nm_vpn_manager, G_TYPE_OBJECT) +#define NM_VPN_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_VPN_MANAGER, NMVPNManagerPrivate)) + typedef struct { - NMManager *nm_manager; - NMDBusManager *dbus_mgr; GSList *services; } NMVPNManagerPrivate; -#define NM_VPN_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_VPN_MANAGER, NMVPNManagerPrivate)) +enum { + CONNECTION_DEACTIVATED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +typedef enum +{ + NM_VPN_MANAGER_ERROR_DEVICE_NOT_ACTIVE = 0, + NM_VPN_MANAGER_ERROR_CONNECTION_INVALID, + NM_VPN_MANAGER_ERROR_SERVICE_INVALID, +} NMVPNManagerError; + +#define NM_VPN_MANAGER_ERROR (nm_vpn_manager_error_quark ()) +#define NM_TYPE_VPN_MANAGER_ERROR (nm_vpn_manager_error_get_type ()) + +static GQuark +nm_vpn_manager_error_quark (void) +{ + static GQuark quark = 0; + if (!quark) + quark = g_quark_from_static_string ("nm-vpn-manager-error"); + return quark; +} + +/* This should really be standard. */ +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +static GType +nm_vpn_manager_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + /* The base device for the VPN connection is not active. */ + ENUM_ENTRY (NM_VPN_MANAGER_ERROR_DEVICE_NOT_ACTIVE, "BaseDeviceNotActive"), + /* The requested VPN connection was invalid. */ + ENUM_ENTRY (NM_VPN_MANAGER_ERROR_CONNECTION_INVALID, "ConnectionInvalid"), + /* The VPN service required by this VPN connection did not exist or was invalid. */ + ENUM_ENTRY (NM_VPN_MANAGER_ERROR_SERVICE_INVALID, "ServiceInvalid"), + { 0, 0, 0 } + }; + etype = g_enum_register_static ("NMVPNManagerError", values); + } + return etype; +} + + static NMVPNService * nm_vpn_manager_get_service (NMVPNManager *manager, const char *service_name) @@ -66,24 +103,87 @@ nm_vpn_manager_add_service (NMVPNManager *manager, NMVPNService *service) g_object_weak_ref (G_OBJECT (service), remove_service, manager); } -NMVPNConnection * -nm_vpn_manager_connect (NMVPNManager *manager, - NMConnection *connection, - NMDevice *device) +static NMVPNConnection * +find_active_vpn_connection_by_connection (NMVPNManager *manager, NMConnection *connection) { - NMSettingVPN *vpn_setting; - NMVPNService *service; + NMVPNManagerPrivate *priv; + GSList *iter; g_return_val_if_fail (NM_IS_VPN_MANAGER (manager), NULL); g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - g_return_val_if_fail (NM_IS_DEVICE (device), NULL); - if (nm_device_get_state (device) != NM_DEVICE_STATE_ACTIVATED) + priv = NM_VPN_MANAGER_GET_PRIVATE (manager); + for (iter = priv->services; iter; iter = g_slist_next (iter)) { + GSList *connections, *elt; + + connections = nm_vpn_service_get_active_connections (NM_VPN_SERVICE (iter->data)); + for (elt = connections; elt; elt = g_slist_next (elt)) { + NMVPNConnection *vpn = NM_VPN_CONNECTION (elt->data); + + if (nm_vpn_connection_get_connection (vpn) == connection) + return vpn; + } + } + return NULL; +} + +static void +connection_state_changed (NMVPNConnection *connection, + NMVPNConnectionState state, + NMVPNConnectionStateReason reason, + gpointer user_data) +{ + NMVPNManager *manager = NM_VPN_MANAGER (user_data); + + switch (state) { + case NM_VPN_CONNECTION_STATE_FAILED: + case NM_VPN_CONNECTION_STATE_DISCONNECTED: + g_signal_emit (manager, signals[CONNECTION_DEACTIVATED], 0, connection, state, reason); + break; + default: + break; + } +} + +const char * +nm_vpn_manager_activate_connection (NMVPNManager *manager, + NMConnection *connection, + NMActRequest *act_request, + NMDevice *device, + GError **error) +{ + NMSettingVPN *vpn_setting; + NMVPNService *service; + char *path = NULL; + NMVPNConnection *vpn; + + g_return_val_if_fail (NM_IS_VPN_MANAGER (manager), NULL); + g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); + g_return_val_if_fail (NM_IS_ACT_REQUEST (act_request), NULL); + g_return_val_if_fail (NM_IS_DEVICE (device), NULL); + g_return_val_if_fail (error != NULL, NULL); + g_return_val_if_fail (*error == NULL, NULL); + + if (nm_device_get_state (device) != NM_DEVICE_STATE_ACTIVATED) { + g_set_error (error, + NM_VPN_MANAGER_ERROR, NM_VPN_MANAGER_ERROR_DEVICE_NOT_ACTIVE, + "%s", "The base device for the VPN connection was not active."); return NULL; + } vpn_setting = (NMSettingVPN *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN); - if (!vpn_setting) + if (!vpn_setting) { + g_set_error (error, + NM_VPN_MANAGER_ERROR, NM_VPN_MANAGER_ERROR_CONNECTION_INVALID, + "%s", "The connection was not a VPN connection."); return NULL; + } + + vpn = find_active_vpn_connection_by_connection (manager, connection); + if (vpn) { + nm_vpn_connection_disconnect (vpn, NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED); + vpn = NULL; + } service = nm_vpn_manager_get_service (manager, vpn_setting->service_type); if (!service) { @@ -92,134 +192,93 @@ nm_vpn_manager_connect (NMVPNManager *manager, nm_vpn_manager_add_service (manager, service); } - if (service) - return nm_vpn_service_activate (service, connection, device); + if (service) { + vpn = nm_vpn_service_activate (service, connection, act_request, device, error); + if (vpn) { + path = (char *) nm_vpn_connection_get_active_connection_path (vpn); + g_signal_connect (vpn, "state-changed", + G_CALLBACK (connection_state_changed), + manager); + } + } else { + g_set_error (error, + NM_VPN_MANAGER_ERROR, NM_VPN_MANAGER_ERROR_SERVICE_INVALID, + "%s", "The VPN service was invalid."); + } - return NULL; + return path; } -static GError * -new_vpn_error (const gchar *format, ...) +gboolean +nm_vpn_manager_deactivate_connection (NMVPNManager *manager, const char *path) { - GError *err; - va_list args; - gchar *msg; - static GQuark domain_quark = 0; - - if (domain_quark == 0) - domain_quark = g_quark_from_static_string ("nm_vpn_error"); - - va_start (args, format); - msg = g_strdup_vprintf (format, args); - va_end (args); - - err = g_error_new_literal (domain_quark, 1, (const gchar *) msg); - - g_free (msg); - - return err; -} - -static gboolean -impl_vpn_manager_connect (NMVPNManager *manager, - const char *connection_type, - const char *connection_path, - const char *device_path, - char **vpn_connection_path, - GError **err) -{ - NMDevice *device; - NMConnection *connection = NULL; - NMVPNConnection *vpn_connection = NULL; NMVPNManagerPrivate *priv; + GSList *iter; + gboolean found = FALSE; - *vpn_connection_path = NULL; + g_return_val_if_fail (NM_IS_VPN_MANAGER (manager), FALSE); + g_return_val_if_fail (path != NULL, FALSE); priv = NM_VPN_MANAGER_GET_PRIVATE (manager); - device = nm_manager_get_device_by_path (priv->nm_manager, device_path); - if (!device) { - *err = new_vpn_error ("%s.%d: No active device was found.", - __FILE__, __LINE__); - goto out; + for (iter = priv->services; iter; iter = g_slist_next (iter)) { + GSList *connections, *elt; + + connections = nm_vpn_service_get_active_connections (NM_VPN_SERVICE (iter->data)); + for (elt = connections; elt; elt = g_slist_next (elt)) { + NMVPNConnection *vpn = NM_VPN_CONNECTION (elt->data); + const char *vpn_path; + + vpn_path = nm_vpn_connection_get_active_connection_path (vpn); + if (!strcmp (path, vpn_path)) { + nm_vpn_connection_disconnect (vpn, NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED); + found = TRUE; + } + } } - if (!strcmp (connection_type, NM_DBUS_SERVICE_USER_SETTINGS)) - connection = nm_manager_get_connection_by_object_path (NM_VPN_MANAGER_GET_PRIVATE (manager)->nm_manager, - NM_CONNECTION_SCOPE_USER, - connection_path); - else if (!strcmp (connection_type, NM_DBUS_SERVICE_SYSTEM_SETTINGS)) - connection = nm_manager_get_connection_by_object_path (NM_VPN_MANAGER_GET_PRIVATE (manager)->nm_manager, - NM_CONNECTION_SCOPE_SYSTEM, - connection_path); - if (connection == NULL) { - *err = new_vpn_error ("%s.%d: VPN connection could not be found.", - __FILE__, __LINE__); - goto out; - } - - vpn_connection = nm_vpn_manager_connect (manager, connection, device); - if (vpn_connection) - *vpn_connection_path = g_strdup (nm_vpn_connection_get_object_path (vpn_connection)); - else { - *err = new_vpn_error ("%s.%d: VPN connection could not be started.", - __FILE__, __LINE__); - } - - out: - return *vpn_connection_path != NULL; + return found ? TRUE : FALSE; } -static void -get_connections (gpointer data, gpointer user_data) +void +nm_vpn_manager_add_active_connections (NMVPNManager *manager, + NMConnection *filter, + GPtrArray *array) { - NMVPNService *service = NM_VPN_SERVICE (data); - GSList **list = (GSList **) user_data; - - *list = g_slist_concat (*list, nm_vpn_service_get_connections (service)); -} - -GSList * -nm_vpn_manager_get_connections (NMVPNManager *manager) -{ - GSList *list = NULL; - - g_return_val_if_fail (NM_IS_VPN_MANAGER (manager), NULL); - - g_slist_foreach (NM_VPN_MANAGER_GET_PRIVATE (manager)->services, get_connections, &list); - - return list; -} - -static gboolean -impl_vpn_manager_get_connections (NMVPNManager *manager, GPtrArray **connections, GError **err) -{ - GSList *list; + NMVPNManagerPrivate *priv; GSList *iter; - list = nm_vpn_manager_get_connections (manager); - *connections = g_ptr_array_sized_new (g_slist_length (list)); + g_return_if_fail (NM_IS_VPN_MANAGER (manager)); + g_return_if_fail (array != NULL); - for (iter = list; iter; iter = iter->next) - g_ptr_array_add (*connections, - g_strdup (nm_vpn_connection_get_object_path (NM_VPN_CONNECTION (iter->data)))); + priv = NM_VPN_MANAGER_GET_PRIVATE (manager); + for (iter = priv->services; iter; iter = g_slist_next (iter)) { + GSList *active, *elt; - g_slist_free (list); + active = nm_vpn_service_get_active_connections (NM_VPN_SERVICE (iter->data)); + for (elt = active; elt; elt = g_slist_next (elt)) { + NMVPNConnection *vpn = NM_VPN_CONNECTION (elt->data); + const char *path; - return TRUE; + if (!filter || (nm_vpn_connection_get_connection (vpn) == filter)) { + path = nm_vpn_connection_get_active_connection_path (vpn); + g_ptr_array_add (array, g_strdup (path)); + } + } + } } NMVPNManager * -nm_vpn_manager_new (NMManager *nm_manager) +nm_vpn_manager_get (void) { - NMVPNManager *manager; + static NMVPNManager *singleton = NULL; - g_return_val_if_fail (NM_IS_MANAGER (nm_manager), NULL); + if (!singleton) + singleton = NM_VPN_MANAGER (g_object_new (NM_TYPE_VPN_MANAGER, NULL)); + else + g_object_ref (singleton); - manager = (NMVPNManager *) g_object_new (NM_TYPE_VPN_MANAGER, NULL); - if (manager) - NM_VPN_MANAGER_GET_PRIVATE (manager)->nm_manager = g_object_ref (nm_manager); - - return manager; + g_assert (singleton); + return singleton; } /******************************************************************************/ @@ -227,12 +286,6 @@ nm_vpn_manager_new (NMManager *nm_manager) static void nm_vpn_manager_init (NMVPNManager *manager) { - NMVPNManagerPrivate *priv = NM_VPN_MANAGER_GET_PRIVATE (manager); - - priv->dbus_mgr = nm_dbus_manager_get (); - dbus_g_connection_register_g_object (nm_dbus_manager_get_connection (priv->dbus_mgr), - NM_DBUS_PATH_VPN, - G_OBJECT (manager)); } static void @@ -241,8 +294,6 @@ finalize (GObject *object) NMVPNManagerPrivate *priv = NM_VPN_MANAGER_GET_PRIVATE (object); g_slist_foreach (priv->services, (GFunc) g_object_unref, NULL); - g_object_unref (priv->dbus_mgr); - g_object_unref (priv->nm_manager); G_OBJECT_CLASS (nm_vpn_manager_parent_class)->finalize (object); } @@ -257,7 +308,17 @@ nm_vpn_manager_class_init (NMVPNManagerClass *manager_class) /* virtual methods */ object_class->finalize = finalize; - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (manager_class), - &dbus_glib_nm_vpn_manager_object_info); + /* signals */ + signals[CONNECTION_DEACTIVATED] = + g_signal_new ("connection-deactivated", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMVPNManagerClass, connection_deactivated), + NULL, NULL, + nm_marshal_VOID__OBJECT_UINT_UINT, + G_TYPE_NONE, 3, + G_TYPE_OBJECT, G_TYPE_UINT, G_TYPE_UINT); + dbus_g_error_domain_register (NM_VPN_MANAGER_ERROR, NULL, NM_TYPE_VPN_MANAGER_ERROR); } + diff --git a/src/vpn-manager/nm-vpn-manager.h b/src/vpn-manager/nm-vpn-manager.h index a5e506c20..3d064b2dd 100644 --- a/src/vpn-manager/nm-vpn-manager.h +++ b/src/vpn-manager/nm-vpn-manager.h @@ -5,8 +5,8 @@ #include #include -#include "nm-manager.h" #include "nm-vpn-connection.h" +#include "nm-activation-request.h" #define NM_TYPE_VPN_MANAGER (nm_vpn_manager_get_type ()) #define NM_VPN_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VPN_MANAGER, NMVPNManager)) @@ -21,17 +21,29 @@ typedef struct { typedef struct { GObjectClass parent; + + /* Signals */ + void (*connection_deactivated) (NMVPNManager *manager, + NMVPNConnection *connection, + NMVPNConnectionState state, + NMVPNConnectionStateReason reason); } NMVPNManagerClass; GType nm_vpn_manager_get_type (void); -NMVPNManager *nm_vpn_manager_new (NMManager *nm_manager); +NMVPNManager *nm_vpn_manager_get (void); -NMVPNConnection *nm_vpn_manager_connect (NMVPNManager *manager, - NMConnection *connection, - NMDevice *device); +const char *nm_vpn_manager_activate_connection (NMVPNManager *manager, + NMConnection *connection, + NMActRequest *act_request, + NMDevice *device, + GError **error); -GSList *nm_vpn_manager_get_connections (NMVPNManager *manager); +gboolean nm_vpn_manager_deactivate_connection (NMVPNManager *manager, + const char *path); +void nm_vpn_manager_add_active_connections (NMVPNManager *manager, + NMConnection *filter, + GPtrArray *list); #endif /* NM_VPN_VPN_MANAGER_H */ diff --git a/src/vpn-manager/nm-vpn-service.c b/src/vpn-manager/nm-vpn-service.c index b9bd29de7..478105a9e 100644 --- a/src/vpn-manager/nm-vpn-service.c +++ b/src/vpn-manager/nm-vpn-service.c @@ -311,37 +311,43 @@ connection_state_changed (NMVPNConnection *connection, NMVPNConnection * nm_vpn_service_activate (NMVPNService *service, - NMConnection *connection, - NMDevice *device) + NMConnection *connection, + NMActRequest *act_request, + NMDevice *device, + GError **error) { - NMVPNConnection *vpn_connection; + NMVPNConnection *vpn; NMVPNServicePrivate *priv; g_return_val_if_fail (NM_IS_VPN_SERVICE (service), NULL); g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); + g_return_val_if_fail (NM_IS_ACT_REQUEST (act_request), NULL); g_return_val_if_fail (NM_IS_DEVICE (device), NULL); + g_return_val_if_fail (error != NULL, NULL); + g_return_val_if_fail (*error == NULL, NULL); priv = NM_VPN_SERVICE_GET_PRIVATE (service); - vpn_connection = nm_vpn_connection_new (connection, device); - g_signal_connect (vpn_connection, "state-changed", + vpn = nm_vpn_connection_new (connection, act_request, device); + g_signal_connect (vpn, "state-changed", G_CALLBACK (connection_state_changed), service); - priv->connections = g_slist_prepend (priv->connections, vpn_connection); + priv->connections = g_slist_prepend (priv->connections, vpn); - if (nm_dbus_manager_name_has_owner (priv->dbus_mgr, priv->dbus_service)) - nm_vpn_connection_activate (vpn_connection); - else if (priv->service_start_timeout == 0) { + if (nm_dbus_manager_name_has_owner (priv->dbus_mgr, priv->dbus_service)) { + // FIXME: fill in error when errors happen + nm_vpn_connection_activate (vpn); + } else if (priv->service_start_timeout == 0) { nm_info ("VPN service '%s' exec scheduled...", nm_vpn_service_get_name (service)); g_idle_add (nm_vpn_service_daemon_exec, service); } - return vpn_connection; + return vpn; } GSList * -nm_vpn_service_get_connections (NMVPNService *service) +nm_vpn_service_get_active_connections (NMVPNService *service) { g_return_val_if_fail (NM_IS_VPN_SERVICE (service), NULL); diff --git a/src/vpn-manager/nm-vpn-service.h b/src/vpn-manager/nm-vpn-service.h index 8037b320d..6a0dee066 100644 --- a/src/vpn-manager/nm-vpn-service.h +++ b/src/vpn-manager/nm-vpn-service.h @@ -7,6 +7,7 @@ #include #include "nm-device.h" #include "nm-vpn-connection.h" +#include "nm-activation-request.h" #define NM_TYPE_VPN_SERVICE (nm_vpn_service_get_type ()) #define NM_VPN_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VPN_SERVICE, NMVPNService)) @@ -25,13 +26,16 @@ typedef struct { GType nm_vpn_service_get_type (void); -NMVPNService *nm_vpn_service_new (const char *service_name); -const char *nm_vpn_service_get_name (NMVPNService *service); +NMVPNService * nm_vpn_service_new (const char *service_name); -NMVPNConnection *nm_vpn_service_activate (NMVPNService *service, - NMConnection *connection, - NMDevice *device); +const char * nm_vpn_service_get_name (NMVPNService *service); -GSList *nm_vpn_service_get_connections (NMVPNService *service); +NMVPNConnection * nm_vpn_service_activate (NMVPNService *service, + NMConnection *connection, + NMActRequest *act_request, + NMDevice *device, + GError **error); + +GSList * nm_vpn_service_get_active_connections (NMVPNService *service); #endif /* NM_VPN_VPN_SERVICE_H */