From fdb5ef29c10137f53e960072109a93fd9c685845 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 17 Sep 2009 14:07:53 -0700 Subject: [PATCH 1/5] nm-tool: don't depend on private NM includes --- test/nm-tool.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/nm-tool.c b/test/nm-tool.c index d9874bc2df..9d1a245718 100644 --- a/test/nm-tool.c +++ b/test/nm-tool.c @@ -43,7 +43,12 @@ #include #include -#include "nm-dbus-glib-types.h" +/* Don't use nm-dbus-glib-types.h so that we can keep nm-tool + * building standalone outside of the NM tree. + */ +#define DBUS_TYPE_G_MAP_OF_VARIANT (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE)) +#define DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, DBUS_TYPE_G_MAP_OF_VARIANT)) +#define DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH)) static GHashTable *user_connections = NULL; static GHashTable *system_connections = NULL; From 2be94b44c348313262778c72123274f73262d5e2 Mon Sep 17 00:00:00 2001 From: Alexander Sack Date: Wed, 16 Sep 2009 13:18:24 +0200 Subject: [PATCH 2/5] core: implement manual disconnect feature In the past networkmanager did not allow to manually disconnect devices. Manually disconnected devices will not be automatically reconnected until one of the following events occur: 1. user activates a connection for the currently disconnected device 2. network manager awakes from hibernate/suspend 3. network manager is restarted (e.g. reboot) Add a Disconnect method to generic NMDevice dbus interface; set a new private autoconnect_inhibit flag if Disconnect method is called through dbus. Based on this auto activation for devices gets inhibited until one of the above events occur. --- introspection/nm-device.xml | 6 ++++++ src/nm-device-interface.c | 20 ++++++++++++++++++++ src/nm-device-interface.h | 5 ++++- src/nm-device.c | 31 ++++++++++++++++++++++++++++++- src/nm-device.h | 2 ++ src/nm-manager.c | 1 + 6 files changed, 63 insertions(+), 2 deletions(-) diff --git a/introspection/nm-device.xml b/introspection/nm-device.xml index a8362acba5..950085c8b8 100644 --- a/introspection/nm-device.xml +++ b/introspection/nm-device.xml @@ -58,6 +58,12 @@ + + + Manually disconnect a device + + + diff --git a/src/nm-device-interface.c b/src/nm-device-interface.c index 5e72afab9d..60db27f2ca 100644 --- a/src/nm-device-interface.c +++ b/src/nm-device-interface.c @@ -25,6 +25,9 @@ #include "nm-utils.h" #include "nm-properties-changed-signal.h" +static gboolean impl_device_disconnect (NMDeviceInterface *device, + GError **error); + #include "nm-device-interface-glue.h" GQuark @@ -270,6 +273,23 @@ nm_device_interface_activate (NMDeviceInterface *device, return success; } +gboolean +nm_device_interface_disconnect (NMDeviceInterface *device, + GError **error) +{ + g_return_val_if_fail (device, FALSE); + + return NM_DEVICE_INTERFACE_GET_INTERFACE (device)->disconnect (device, error); +} + + +static gboolean +impl_device_disconnect (NMDeviceInterface *device, + GError **error) +{ + return nm_device_interface_disconnect (device, error); +} + void nm_device_interface_deactivate (NMDeviceInterface *device, NMDeviceStateReason reason) { diff --git a/src/nm-device-interface.h b/src/nm-device-interface.h index 0273c750d2..ffa7e1c0ef 100644 --- a/src/nm-device-interface.h +++ b/src/nm-device-interface.h @@ -68,7 +68,7 @@ typedef enum { NM_DEVICE_INTERFACE_PROP_STATE, NM_DEVICE_INTERFACE_PROP_DEVICE_TYPE, NM_DEVICE_INTERFACE_PROP_MANAGED, - NM_DEVICE_INTERFACE_PROP_TYPE_DESC + NM_DEVICE_INTERFACE_PROP_TYPE_DESC, } NMDeviceInterfaceProp; @@ -87,6 +87,7 @@ struct _NMDeviceInterface { GError **error); void (*deactivate) (NMDeviceInterface *device, NMDeviceStateReason reason); + gboolean (*disconnect) (NMDeviceInterface *device, GError **error); gboolean (*spec_match_list) (NMDeviceInterface *device, const GSList *specs); @@ -102,6 +103,8 @@ struct _NMDeviceInterface { GQuark nm_device_interface_error_quark (void); GType nm_device_interface_error_get_type (void); +gboolean nm_device_interface_disconnect (NMDeviceInterface *device, GError **error); + GType nm_device_interface_get_type (void); gboolean nm_device_interface_check_connection_compatible (NMDeviceInterface *device, diff --git a/src/nm-device.c b/src/nm-device.c index ec08f58106..155f689a19 100644 --- a/src/nm-device.c +++ b/src/nm-device.c @@ -127,6 +127,9 @@ typedef struct { gulong ip6_addrconf_sigid; gulong ip6_config_changed_sigid; gboolean ip6_waiting_for_config; + + /* inhibit autoconnect feature */ + gboolean autoconnect_inhibit; } NMDevicePrivate; static gboolean check_connection_compatible (NMDeviceInterface *device, @@ -136,6 +139,7 @@ static gboolean nm_device_activate (NMDeviceInterface *device, NMActRequest *req, GError **error); static void nm_device_deactivate (NMDeviceInterface *device, NMDeviceStateReason reason); +static gboolean device_disconnect (NMDeviceInterface *device, GError **error); static gboolean spec_match_list (NMDeviceInterface *device, const GSList *specs); static NMConnection *connection_match_config (NMDeviceInterface *device, const GSList *connections); @@ -162,6 +166,7 @@ device_interface_init (NMDeviceInterface *device_interface_class) device_interface_class->check_connection_compatible = check_connection_compatible; device_interface_class->activate = nm_device_activate; device_interface_class->deactivate = nm_device_deactivate; + device_interface_class->disconnect = device_disconnect; device_interface_class->spec_match_list = spec_match_list; device_interface_class->connection_match_config = connection_match_config; } @@ -410,6 +415,7 @@ autoconnect_allowed_accumulator (GSignalInvocationHint *ihint, gboolean nm_device_autoconnect_allowed (NMDevice *self) { + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); GValue instance = { 0, }; GValue retval = { 0, }; @@ -417,7 +423,10 @@ nm_device_autoconnect_allowed (NMDevice *self) g_value_take_object (&instance, self); g_value_init (&retval, G_TYPE_BOOLEAN); - g_value_set_boolean (&retval, TRUE); + if (priv->autoconnect_inhibit) + g_value_set_boolean (&retval, FALSE); + else + g_value_set_boolean (&retval, TRUE); /* Use g_signal_emitv() rather than g_signal_emit() to avoid the return * value being changed if no handlers are connected */ @@ -2066,6 +2075,17 @@ nm_device_deactivate (NMDeviceInterface *device, NMDeviceStateReason reason) NM_DEVICE_GET_CLASS (self)->deactivate (self); } +static gboolean +device_disconnect (NMDeviceInterface *device, + GError **error) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (NM_DEVICE (device)); + priv->autoconnect_inhibit = TRUE; + nm_device_deactivate (device, NM_DEVICE_STATE_REASON_USER_REQUESTED); + nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_USER_REQUESTED); + return TRUE; +} + static gboolean check_connection_compatible (NMDeviceInterface *dev_iface, NMConnection *connection, @@ -3061,6 +3081,7 @@ nm_device_state_changed (NMDevice *device, nm_device_interface_deactivate (NM_DEVICE_INTERFACE (device), reason); break; default: + priv->autoconnect_inhibit = FALSE; break; } @@ -3198,3 +3219,11 @@ nm_device_set_dhcp_anycast_address (NMDevice *device, guint8 *addr) } +void +nm_device_clear_autoconnect_inhibit (NMDevice *device) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + g_return_if_fail (priv); + priv->autoconnect_inhibit = FALSE; +} + diff --git a/src/nm-device.h b/src/nm-device.h index c8f67dcc76..b81c460d6e 100644 --- a/src/nm-device.h +++ b/src/nm-device.h @@ -179,6 +179,8 @@ void nm_device_set_managed (NMDevice *device, void nm_device_set_dhcp_timeout (NMDevice *device, guint32 timeout); void nm_device_set_dhcp_anycast_address (NMDevice *device, guint8 *addr); +void nm_device_clear_autoconnect_inhibit (NMDevice *device); + G_END_DECLS #endif /* NM_DEVICE_H */ diff --git a/src/nm-manager.c b/src/nm-manager.c index 2fd1cbd2d9..72a01345c5 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -2393,6 +2393,7 @@ impl_manager_sleep (NMManager *self, gboolean sleep, GError **error) for (iter = priv->devices; iter; iter = iter->next) { NMDevice *device = NM_DEVICE (iter->data); + nm_device_clear_autoconnect_inhibit (device); if (nm_device_interface_spec_match_list (NM_DEVICE_INTERFACE (device), unmanaged_specs)) nm_device_set_managed (device, FALSE, NM_DEVICE_STATE_REASON_NOW_UNMANAGED); else From 109f7e772a41b2342fa41ff0db1101ce91251eb1 Mon Sep 17 00:00:00 2001 From: Alexander Sack Date: Fri, 18 Sep 2009 01:55:31 +0200 Subject: [PATCH 3/5] libnm-glib: add nm_device_disconnect function to glib API --- libnm-glib/Makefile.am | 2 +- libnm-glib/libnm-glib.ver | 1 + libnm-glib/nm-device.c | 13 +++++++++++++ libnm-glib/nm-device.h | 2 ++ 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/libnm-glib/Makefile.am b/libnm-glib/Makefile.am index 8d659ea0b7..f91623e1b9 100644 --- a/libnm-glib/Makefile.am +++ b/libnm-glib/Makefile.am @@ -105,7 +105,7 @@ libnm_glib_la_LIBADD = \ $(GUDEV_LIBS) libnm_glib_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libnm-glib.ver \ - -version-info "2:0:0" + -version-info "3:0:1" noinst_PROGRAMS = libnm-glib-test diff --git a/libnm-glib/libnm-glib.ver b/libnm-glib/libnm-glib.ver index 342f713dcc..25556391dd 100644 --- a/libnm-glib/libnm-glib.ver +++ b/libnm-glib/libnm-glib.ver @@ -48,6 +48,7 @@ global: nm_dbus_settings_system_get_type; nm_dbus_settings_system_get_unmanaged_devices; nm_dbus_settings_system_new; + nm_device_disconnect; nm_device_bt_new; nm_device_bt_get_capabilities; nm_device_bt_get_hw_address; diff --git a/libnm-glib/nm-device.c b/libnm-glib/nm-device.c index 6cc38a8f51..f316535357 100644 --- a/libnm-glib/nm-device.c +++ b/libnm-glib/nm-device.c @@ -1065,3 +1065,16 @@ nm_device_get_vendor (NMDevice *device) return priv->vendor; } +void +nm_device_disconnect (NMDevice *device, GError **error) +{ + NMDevicePrivate *priv; + + g_return_if_fail (NM_IS_DEVICE (device)); + priv = NM_DEVICE_GET_PRIVATE (device); + g_return_if_fail (priv); + + if (!org_freedesktop_NetworkManager_Device_disconnect (priv->proxy, error)) + g_warning ("Error in disconnect: %s", error && *error ? (*error)->message : "unknown"); +} + diff --git a/libnm-glib/nm-device.h b/libnm-glib/nm-device.h index 442643214d..11ffc642d5 100644 --- a/libnm-glib/nm-device.h +++ b/libnm-glib/nm-device.h @@ -85,6 +85,8 @@ NMDeviceState nm_device_get_state (NMDevice *device); const char * nm_device_get_product (NMDevice *device); const char * nm_device_get_vendor (NMDevice *device); +void nm_device_disconnect (NMDevice *device, GError **error); + G_END_DECLS #endif /* NM_DEVICE_H */ From 7239863d8fe824250f86f4f9993e58c918309229 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 18 Sep 2009 08:38:29 -0700 Subject: [PATCH 4/5] libnm-glib: make nm_device_disconnect() async --- libnm-glib/nm-device.c | 60 ++++++++++++++++++++++++++++++++++++------ libnm-glib/nm-device.h | 6 ++++- 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/libnm-glib/nm-device.c b/libnm-glib/nm-device.c index f316535357..226b30587c 100644 --- a/libnm-glib/nm-device.c +++ b/libnm-glib/nm-device.c @@ -1065,16 +1065,60 @@ nm_device_get_vendor (NMDevice *device) return priv->vendor; } -void -nm_device_disconnect (NMDevice *device, GError **error) +typedef struct { + NMDevice *device; + NMDeviceDeactivateFn fn; + gpointer user_data; +} DeactivateInfo; + +static void +deactivate_cb (DBusGProxy *proxy, + GError *error, + gpointer user_data) { - NMDevicePrivate *priv; + DeactivateInfo *info = user_data; - g_return_if_fail (NM_IS_DEVICE (device)); - priv = NM_DEVICE_GET_PRIVATE (device); - g_return_if_fail (priv); + if (info->fn) + info->fn (info->device, error, info->user_data); + else if (error) { + g_warning ("%s: device %s deactivation failed: (%d) %s", + __func__, + nm_object_get_path (NM_OBJECT (info->device)), + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + } - if (!org_freedesktop_NetworkManager_Device_disconnect (priv->proxy, error)) - g_warning ("Error in disconnect: %s", error && *error ? (*error)->message : "unknown"); + g_object_unref (info->device); + g_slice_free (DeactivateInfo, info); +} + +/** + * nm_device_disconnect: + * @device: a #NMDevice + * @error: a location to store an error on failure + * + * Disconnects the device if currently connected, and prevents the device from + * automatically connecting to networks until the next manual network connection + * request. + * + * Returns: TRUE on success, FALSE if an error occurred. + **/ +void +nm_device_disconnect (NMDevice *device, + NMDeviceDeactivateFn callback, + gpointer user_data) +{ + DeactivateInfo *info; + + g_return_if_fail (NM_IS_DEVICE (device)); + + info = g_slice_new (DeactivateInfo); + info->fn = callback; + info->user_data = user_data; + info->device = g_object_ref (device); + + org_freedesktop_NetworkManager_Device_disconnect_async (NM_DEVICE_GET_PRIVATE (device)->proxy, + deactivate_cb, + info); } diff --git a/libnm-glib/nm-device.h b/libnm-glib/nm-device.h index 11ffc642d5..7e016f4598 100644 --- a/libnm-glib/nm-device.h +++ b/libnm-glib/nm-device.h @@ -85,7 +85,11 @@ NMDeviceState nm_device_get_state (NMDevice *device); const char * nm_device_get_product (NMDevice *device); const char * nm_device_get_vendor (NMDevice *device); -void nm_device_disconnect (NMDevice *device, GError **error); +typedef void (*NMDeviceDeactivateFn) (NMDevice *device, GError *error, gpointer user_data); + +void nm_device_disconnect (NMDevice *device, + NMDeviceDeactivateFn callback, + gpointer user_data); G_END_DECLS From 99fb8446575a53ff59e40bf4fd219e981e7db393 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 18 Sep 2009 09:05:11 -0700 Subject: [PATCH 5/5] core: device disconnection cleanups Return an error when trying to disconnect an already-disconnected or deactivated device. --- introspection/nm-device.xml | 2 +- src/nm-device-interface.c | 24 +++++++++++++++++++++--- src/nm-device-interface.h | 1 + src/nm-device.c | 2 +- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/introspection/nm-device.xml b/introspection/nm-device.xml index 950085c8b8..c23b596c4b 100644 --- a/introspection/nm-device.xml +++ b/introspection/nm-device.xml @@ -60,7 +60,7 @@ - Manually disconnect a device + Disconnects a device and prevents the device from automatically activating further connections without user intervention. diff --git a/src/nm-device-interface.c b/src/nm-device-interface.c index 60db27f2ca..c8475df4ca 100644 --- a/src/nm-device-interface.c +++ b/src/nm-device-interface.c @@ -53,6 +53,8 @@ nm_device_interface_error_get_type (void) ENUM_ENTRY (NM_DEVICE_INTERFACE_ERROR_CONNECTION_ACTIVATING, "ConnectionActivating"), /* Connection is invalid for this device. */ ENUM_ENTRY (NM_DEVICE_INTERFACE_ERROR_CONNECTION_INVALID, "ConnectionInvalid"), + /* Operation could not be performed because the device is not active. */ + ENUM_ENTRY (NM_DEVICE_INTERFACE_ERROR_NOT_ACTIVE, "NotActive"), { 0, 0, 0 } }; etype = g_enum_register_static ("NMDeviceInterfaceError", values); @@ -277,12 +279,28 @@ gboolean nm_device_interface_disconnect (NMDeviceInterface *device, GError **error) { - g_return_val_if_fail (device, FALSE); + gboolean success = FALSE; - return NM_DEVICE_INTERFACE_GET_INTERFACE (device)->disconnect (device, error); + g_return_val_if_fail (NM_IS_DEVICE_INTERFACE (device), FALSE); + + switch (nm_device_interface_get_state (device)) { + case NM_DEVICE_STATE_UNKNOWN: + case NM_DEVICE_STATE_UNMANAGED: + case NM_DEVICE_STATE_UNAVAILABLE: + case NM_DEVICE_STATE_DISCONNECTED: + g_set_error_literal (error, + NM_DEVICE_INTERFACE_ERROR, + NM_DEVICE_INTERFACE_ERROR_NOT_ACTIVE, + "Cannot disconnect an inactive device."); + break; + default: + success = NM_DEVICE_INTERFACE_GET_INTERFACE (device)->disconnect (device, error); + break; + } + + return success; } - static gboolean impl_device_disconnect (NMDeviceInterface *device, GError **error) diff --git a/src/nm-device-interface.h b/src/nm-device-interface.h index ffa7e1c0ef..0867bc2923 100644 --- a/src/nm-device-interface.h +++ b/src/nm-device-interface.h @@ -36,6 +36,7 @@ typedef enum { NM_DEVICE_INTERFACE_ERROR_CONNECTION_ACTIVATING = 0, NM_DEVICE_INTERFACE_ERROR_CONNECTION_INVALID, + NM_DEVICE_INTERFACE_ERROR_NOT_ACTIVE, } NMDeviceInterfaceError; #define NM_DEVICE_INTERFACE_ERROR (nm_device_interface_error_quark ()) diff --git a/src/nm-device.c b/src/nm-device.c index 155f689a19..d7e6e256c6 100644 --- a/src/nm-device.c +++ b/src/nm-device.c @@ -2080,8 +2080,8 @@ device_disconnect (NMDeviceInterface *device, GError **error) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (NM_DEVICE (device)); + priv->autoconnect_inhibit = TRUE; - nm_device_deactivate (device, NM_DEVICE_STATE_REASON_USER_REQUESTED); nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_USER_REQUESTED); return TRUE; }