diff options
| author | Michael Biebl <biebl@debian.org> | 2011-04-21 10:43:09 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2011-04-21 10:43:09 +0200 |
| commit | 8aefc77115a9b89e96ff224e659e2271912a8295 (patch) | |
| tree | 2aeaf38cdc77553c0bf417fb632c2a3d5e7adbc7 /src/nm-manager.c | |
| parent | 2fbd59597fe985d6feb382bf35145dcf2f481060 (diff) | |
| parent | 8baa1aca8dfd35e3190d7d5655eb83b5b901e263 (diff) | |
Merge commit 'upstream/0.8.4.0'
Diffstat (limited to 'src/nm-manager.c')
| -rw-r--r-- | src/nm-manager.c | 162 |
1 files changed, 105 insertions, 57 deletions
diff --git a/src/nm-manager.c b/src/nm-manager.c index 8b24aa51..e34e9014 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -188,6 +188,7 @@ struct PendingActivation { typedef struct { gboolean user_enabled; + gboolean daemon_enabled; gboolean sw_enabled; gboolean hw_enabled; RfKillType rtype; @@ -196,6 +197,7 @@ typedef struct { const char *prop; const char *hw_prop; RfKillState (*other_enabled_func) (NMManager *); + RfKillState (*daemon_enabled_func) (NMManager *); } RadioState; typedef struct { @@ -917,7 +919,6 @@ static GPtrArray * get_active_connections (NMManager *manager, NMConnection *filter) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - NMVPNManager *vpn_manager; GPtrArray *active; GSList *iter; @@ -939,9 +940,7 @@ get_active_connections (NMManager *manager, NMConnection *filter) } /* 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); + nm_vpn_manager_add_active_connections (priv->vpn_manager, filter, active); return active; } @@ -1651,21 +1650,28 @@ write_value_to_state_file (const char *filename, } static gboolean -radio_enabled_for_rstate (RadioState *rstate) +radio_enabled_for_rstate (RadioState *rstate, gboolean check_daemon_enabled) { - return rstate->user_enabled && rstate->sw_enabled && rstate->hw_enabled; + gboolean enabled; + + enabled = rstate->user_enabled && rstate->sw_enabled && rstate->hw_enabled; + if (rstate->daemon_enabled_func && check_daemon_enabled) + enabled &= rstate->daemon_enabled; + return enabled; } static gboolean -radio_enabled_for_type (NMManager *self, RfKillType rtype) +radio_enabled_for_type (NMManager *self, RfKillType rtype, gboolean check_daemon_enabled) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - return radio_enabled_for_rstate (&priv->radio_states[rtype]); + return radio_enabled_for_rstate (&priv->radio_states[rtype], check_daemon_enabled); } static void -manager_update_radio_enabled (NMManager *self, RadioState *rstate) +manager_update_radio_enabled (NMManager *self, + RadioState *rstate, + gboolean enabled) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); GSList *iter; @@ -1683,7 +1689,6 @@ manager_update_radio_enabled (NMManager *self, RadioState *rstate) /* enable/disable wireless devices as required */ for (iter = priv->devices; iter; iter = iter->next) { RfKillType devtype = RFKILL_TYPE_UNKNOWN; - gboolean enabled = radio_enabled_for_rstate (rstate); g_object_get (G_OBJECT (iter->data), NM_DEVICE_INTERFACE_RFKILL_TYPE, &devtype, NULL); if (devtype == rstate->rtype) { @@ -1830,9 +1835,9 @@ manager_rfkill_update_one_type (NMManager *self, RfKillState other_state = RFKILL_UNBLOCKED; RfKillState composite; gboolean old_enabled, new_enabled, old_rfkilled, new_rfkilled; - gboolean old_hwe; + gboolean old_hwe, old_daemon_enabled = FALSE; - old_enabled = radio_enabled_for_rstate (rstate); + old_enabled = radio_enabled_for_rstate (rstate, TRUE); old_rfkilled = rstate->hw_enabled && rstate->sw_enabled; old_hwe = rstate->hw_enabled; @@ -1851,9 +1856,26 @@ manager_rfkill_update_one_type (NMManager *self, update_rstate_from_rfkill (rstate, composite); + /* If the device has a management daemon that can affect enabled state, check that now */ + if (rstate->daemon_enabled_func) { + old_daemon_enabled = rstate->daemon_enabled; + rstate->daemon_enabled = (rstate->daemon_enabled_func (self) == RFKILL_UNBLOCKED); + if (old_daemon_enabled != rstate->daemon_enabled) { + nm_log_info (LOGD_RFKILL, "%s now %s by management service", + rstate->desc, + rstate->daemon_enabled ? "enabled" : "disabled"); + } + } + + /* Print out all states affecting device enablement */ if (rstate->desc) { - nm_log_dbg (LOGD_RFKILL, "%s hw-enabled %d sw-enabled %d", - rstate->desc, rstate->hw_enabled, rstate->sw_enabled); + if (rstate->daemon_enabled_func) { + nm_log_dbg (LOGD_RFKILL, "%s hw-enabled %d sw-enabled %d daemon-enabled %d", + rstate->desc, rstate->hw_enabled, rstate->sw_enabled, rstate->daemon_enabled); + } else { + nm_log_dbg (LOGD_RFKILL, "%s hw-enabled %d sw-enabled %d", + rstate->desc, rstate->hw_enabled, rstate->sw_enabled); + } } /* Log new killswitch state */ @@ -1870,10 +1892,14 @@ manager_rfkill_update_one_type (NMManager *self, g_object_notify (G_OBJECT (self), rstate->hw_prop); } - /* And finally update the actual device radio state itself */ - new_enabled = radio_enabled_for_rstate (rstate); + /* And finally update the actual device radio state itself; respect the + * daemon state here because this is never called from user-triggered + * radio changes and we only want to ignore the daemon enabled state when + * handling user radio change requests. + */ + new_enabled = radio_enabled_for_rstate (rstate, TRUE); if (new_enabled != old_enabled) - manager_update_radio_enabled (self, rstate); + manager_update_radio_enabled (self, rstate, new_enabled); } static void @@ -1882,14 +1908,13 @@ nm_manager_rfkill_update (NMManager *self, RfKillType rtype) NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); guint i; - if (rtype != RFKILL_TYPE_UNKNOWN) { + if (rtype != RFKILL_TYPE_UNKNOWN) manager_rfkill_update_one_type (self, &priv->radio_states[rtype], rtype); - return; + else { + /* Otherwise sync all radio types */ + for (i = 0; i < RFKILL_TYPE_MAX; i++) + manager_rfkill_update_one_type (self, &priv->radio_states[i], i); } - - /* Otherwise sync all radio types */ - for (i = 0; i < RFKILL_TYPE_MAX; i++) - manager_rfkill_update_one_type (self, &priv->radio_states[i], i); } static void @@ -2084,6 +2109,7 @@ add_device (NMManager *self, NMDevice *device) GHashTableIter iter; gpointer value; gboolean managed = FALSE, enabled = FALSE; + RfKillType rtype = RFKILL_TYPE_UNKNOWN; iface = nm_device_get_ip_iface (device); g_assert (iface); @@ -2117,26 +2143,21 @@ add_device (NMManager *self, NMDevice *device) g_signal_connect (device, "notify::" NM_DEVICE_WIFI_IPW_RFKILL_STATE, G_CALLBACK (manager_ipw_rfkill_state_changed), self); - - /* Update global rfkill state with this device's rfkill state, and - * then set this device's rfkill state based on the global state. - */ - nm_manager_rfkill_update (self, RFKILL_TYPE_WLAN); - enabled = radio_enabled_for_type (self, RFKILL_TYPE_WLAN); - nm_device_interface_set_enabled (NM_DEVICE_INTERFACE (device), enabled); + rtype = RFKILL_TYPE_WLAN; } else if (NM_IS_DEVICE_MODEM (device)) { g_signal_connect (device, NM_DEVICE_MODEM_ENABLE_CHANGED, G_CALLBACK (manager_modem_enabled_changed), self); + rtype = RFKILL_TYPE_WWAN; + } - nm_manager_rfkill_update (self, RFKILL_TYPE_WWAN); - enabled = radio_enabled_for_type (self, RFKILL_TYPE_WWAN); - /* Until we start respecting WWAN rfkill switches the modem itself - * is the source of the enabled/disabled state, so the manager shouldn't - * touch it here. - nm_device_interface_set_enabled (NM_DEVICE_INTERFACE (device), - priv->radio_states[RFKILL_TYPE_WWAN].enabled); - */ + if (rtype != RFKILL_TYPE_UNKNOWN) { + /* Update global rfkill state with this device's rfkill state, and + * then set this device's rfkill state based on the global state. + */ + nm_manager_rfkill_update (self, rtype); + enabled = radio_enabled_for_type (self, rtype, TRUE); + nm_device_interface_set_enabled (NM_DEVICE_INTERFACE (device), enabled); } type_desc = nm_device_get_type_desc (device); @@ -2597,6 +2618,7 @@ user_get_secrets_cb (DBusGProxy *proxy, gpointer user_data) { GetSecretsInfo *info = (GetSecretsInfo *) user_data; + NMManagerPrivate *priv; GHashTable *settings = NULL; GError *error = NULL; GObject *provider; @@ -2605,6 +2627,15 @@ user_get_secrets_cb (DBusGProxy *proxy, g_return_if_fail (info->provider); g_return_if_fail (info->setting_name); + /* Remove the GetSecretsInfo from our internal list just in case + * calling the secrets provider's get_secrets_result() function tries + * to cancel the secrets request, which would cause us to double-free + * the GetSecretsInfo. We know we're going to free it at the end here, + * so there's no need to track it anymore. + */ + priv = NM_MANAGER_GET_PRIVATE (info->manager); + priv->secrets_calls = g_slist_remove (priv->secrets_calls, info); + provider = g_object_ref (info->provider); if (dbus_g_proxy_end_call (proxy, call, &error, @@ -2905,10 +2936,8 @@ nm_manager_activate_connection (NMManager *manager, if (!strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_VPN_SETTING_NAME)) { NMActRequest *req = NULL; - NMVPNManager *vpn_manager; /* VPN connection */ - if (specific_object) { /* Find the specifc connection the client requested we use */ req = nm_manager_get_act_request_by_path (manager, specific_object, &device); @@ -2942,10 +2971,8 @@ nm_manager_activate_connection (NMManager *manager, return NULL; } - vpn_manager = nm_vpn_manager_get (); - vpn_connection = nm_vpn_manager_activate_connection (vpn_manager, + vpn_connection = nm_vpn_manager_activate_connection (priv->vpn_manager, connection, - req, device, error); if (vpn_connection) { @@ -2955,7 +2982,6 @@ nm_manager_activate_connection (NMManager *manager, G_CALLBACK (provider_cancel_secrets), manager); path = nm_vpn_connection_get_active_connection_path (vpn_connection); } - g_object_unref (vpn_manager); } else { NMDeviceState state; @@ -3136,7 +3162,6 @@ nm_manager_deactivate_connection (NMManager *manager, GError **error) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - NMVPNManager *vpn_manager; GSList *iter; gboolean success = FALSE; NMVPNConnectionStateReason vpn_reason = NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED; @@ -3160,17 +3185,15 @@ nm_manager_deactivate_connection (NMManager *manager, } /* Check for VPN connections next */ - vpn_manager = nm_vpn_manager_get (); if (reason == NM_DEVICE_STATE_REASON_CONNECTION_REMOVED) vpn_reason = NM_VPN_CONNECTION_STATE_REASON_CONNECTION_REMOVED; - if (nm_vpn_manager_deactivate_connection (vpn_manager, connection_path, vpn_reason)) { + if (nm_vpn_manager_deactivate_connection (priv->vpn_manager, connection_path, vpn_reason)) { 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); @@ -3383,7 +3406,7 @@ do_sleep_wake (NMManager *self) */ for (i = 0; i < RFKILL_TYPE_MAX; i++) { RadioState *rstate = &priv->radio_states[i]; - gboolean enabled = radio_enabled_for_rstate (rstate); + gboolean enabled = radio_enabled_for_rstate (rstate, TRUE); RfKillType devtype = RFKILL_TYPE_UNKNOWN; if (rstate->desc) { @@ -3997,6 +4020,7 @@ nm_manager_start (NMManager *self) for (i = 0; i < RFKILL_TYPE_MAX; i++) { RadioState *rstate = &priv->radio_states[i]; RfKillState udev_state; + gboolean enabled; if (!rstate->desc) continue; @@ -4010,7 +4034,8 @@ nm_manager_start (NMManager *self) (rstate->hw_enabled && rstate->sw_enabled) ? "enabled" : "disabled", rstate->user_enabled ? "enabled" : "disabled"); } - manager_update_radio_enabled (self, rstate); + enabled = radio_enabled_for_rstate (rstate, TRUE); + manager_update_radio_enabled (self, rstate, enabled); } /* Log overall networking status - enabled/disabled */ @@ -4344,7 +4369,7 @@ dispose (GObject *object) { NMManager *manager = NM_MANAGER (object); NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - GSList *iter; + GSList *iter, *list; DBusGConnection *bus; DBusConnection *dbus_connection; @@ -4390,6 +4415,20 @@ dispose (GObject *object) priv->sys_settings = NULL; } + /* Make sure we disconnect signal handlers from VPN connections that + * might still be alive when the manager dies. + */ + list = nm_vpn_manager_get_active_connections (priv->vpn_manager); + for (iter = list; iter; iter = g_slist_next (iter)) { + g_signal_handlers_disconnect_by_func (G_OBJECT (iter->data), + G_CALLBACK (provider_get_secrets), + manager); + g_signal_handlers_disconnect_by_func (G_OBJECT (iter->data), + G_CALLBACK (provider_cancel_secrets), + manager); + /* unref to balance returned objects from the VPN manager */ + g_object_unref (iter->data); + } if (priv->vpn_manager_id) { g_source_remove (priv->vpn_manager_id); priv->vpn_manager_id = 0; @@ -4472,11 +4511,20 @@ manager_radio_user_toggled (NMManager *self, } } - old_enabled = radio_enabled_for_rstate (rstate); + /* When the user toggles the radio, their request should override any + * daemon (like ModemManager) enabled state that can be changed. For WWAN + * for example, we want the WwanEnabled property to reflect the daemon state + * too so that users can toggle the modem powered, but we don't want that + * daemon state to affect whether or not the user *can* turn it on, which is + * what the kernel rfkill state does. So we ignore daemon enabled state + * when determining what the new state should be since it shouldn't block + * the user's request. + */ + old_enabled = radio_enabled_for_rstate (rstate, TRUE); rstate->user_enabled = enabled; - new_enabled = radio_enabled_for_rstate (rstate); + new_enabled = radio_enabled_for_rstate (rstate, FALSE); if (new_enabled != old_enabled) - manager_update_radio_enabled (self, rstate); + manager_update_radio_enabled (self, rstate, new_enabled); } static void @@ -4526,13 +4574,13 @@ get_property (GObject *object, guint prop_id, g_value_set_boolean (value, priv->net_enabled); break; case PROP_WIRELESS_ENABLED: - g_value_set_boolean (value, radio_enabled_for_type (self, RFKILL_TYPE_WLAN)); + g_value_set_boolean (value, radio_enabled_for_type (self, RFKILL_TYPE_WLAN, TRUE)); break; case PROP_WIRELESS_HARDWARE_ENABLED: g_value_set_boolean (value, priv->radio_states[RFKILL_TYPE_WLAN].hw_enabled); break; case PROP_WWAN_ENABLED: - g_value_set_boolean (value, radio_enabled_for_type (self, RFKILL_TYPE_WWAN)); + g_value_set_boolean (value, radio_enabled_for_type (self, RFKILL_TYPE_WWAN, TRUE)); break; case PROP_WWAN_HARDWARE_ENABLED: g_value_set_boolean (value, priv->radio_states[RFKILL_TYPE_WWAN].hw_enabled); @@ -4599,7 +4647,7 @@ nm_manager_init (NMManager *manager) priv->radio_states[RFKILL_TYPE_WWAN].prop = NM_MANAGER_WWAN_ENABLED; priv->radio_states[RFKILL_TYPE_WWAN].hw_prop = NM_MANAGER_WWAN_HARDWARE_ENABLED; priv->radio_states[RFKILL_TYPE_WWAN].desc = "WWAN"; - priv->radio_states[RFKILL_TYPE_WWAN].other_enabled_func = nm_manager_get_modem_enabled_state; + priv->radio_states[RFKILL_TYPE_WWAN].daemon_enabled_func = nm_manager_get_modem_enabled_state; priv->radio_states[RFKILL_TYPE_WWAN].rtype = RFKILL_TYPE_WWAN; priv->radio_states[RFKILL_TYPE_WIMAX].user_enabled = TRUE; |