diff --git a/src/nm-device.c b/src/nm-device.c index 37fcfb7868..f7c420ca73 100644 --- a/src/nm-device.c +++ b/src/nm-device.c @@ -184,13 +184,15 @@ typedef struct { char * driver; char * driver_version; char * firmware_version; - gboolean managed; /* whether managed by NM or not */ RfKillType rfkill_type; gboolean firmware_missing; GHashTable * available_connections; guint8 hw_addr[NM_UTILS_HWADDR_LEN_MAX]; guint hw_addr_len; + gboolean manager_managed; /* whether managed by NMManager or not */ + gboolean default_unmanaged; /* whether unmanaged by default */ + guint32 ip4_address; NMActRequest * act_request; @@ -1342,6 +1344,22 @@ nm_device_is_available (NMDevice *self) return TRUE; } +gboolean +nm_device_can_activate (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (!priv->manager_managed) + return FALSE; + if (!priv->default_unmanaged && priv->state < NM_DEVICE_STATE_DISCONNECTED) + return FALSE; + + if (priv->state > NM_DEVICE_STATE_DISCONNECTED) + return FALSE; + + return nm_device_is_available (self); +} + gboolean nm_device_ignore_carrier (NMDevice *dev) { @@ -4123,6 +4141,21 @@ nm_device_activate (NMDevice *self, NMActRequest *req) nm_device_get_iface (self), nm_connection_get_id (connection)); + if (priv->state < NM_DEVICE_STATE_DISCONNECTED) { + g_return_if_fail (nm_device_can_activate (self)); + + if (priv->state == NM_DEVICE_STATE_UNMANAGED) { + nm_device_state_changed (self, + NM_DEVICE_STATE_UNAVAILABLE, + NM_DEVICE_STATE_REASON_NONE); + } + if (priv->state == NM_DEVICE_STATE_UNAVAILABLE) { + nm_device_state_changed (self, + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_NONE); + } + } + g_warn_if_fail (priv->state == NM_DEVICE_STATE_DISCONNECTED); priv->act_request = g_object_ref (req); @@ -4524,7 +4557,7 @@ dispose (GObject *object) g_warn_if_fail (priv->slaves == NULL); /* Take the device itself down and clear its IPv4 configuration */ - if (priv->managed && take_down) { + if (nm_device_get_managed (self) && take_down) { NMDeviceStateReason ignored = NM_DEVICE_STATE_REASON_NONE; nm_device_take_down (self, FALSE, NM_DEVICE_STATE_REASON_REMOVED); @@ -4662,9 +4695,6 @@ set_property (GObject *object, guint prop_id, case PROP_IP4_ADDRESS: priv->ip4_address = g_value_get_uint (value); break; - case PROP_MANAGED: - priv->managed = g_value_get_boolean (value); - break; case PROP_AUTOCONNECT: priv->autoconnect = g_value_get_boolean (value); break; @@ -4807,7 +4837,7 @@ get_property (GObject *object, guint prop_id, g_value_set_uint (value, priv->type); break; case PROP_MANAGED: - g_value_set_boolean (value, priv->managed); + g_value_set_boolean (value, nm_device_get_managed (self)); break; case PROP_AUTOCONNECT: g_value_set_boolean (value, priv->autoconnect); @@ -5011,7 +5041,7 @@ nm_device_class_init (NMDeviceClass *klass) "Managed", "Managed", FALSE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + G_PARAM_READABLE)); g_object_class_install_property (object_class, PROP_AUTOCONNECT, @@ -5385,7 +5415,8 @@ nm_device_state_changed (NMDevice *device, * about to assume a connection since that defeats the purpose of * assuming the device's existing connection. */ - if (reason != NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED) + if (reason != NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED && + old_state != NM_DEVICE_STATE_UNMANAGED) nm_device_deactivate (device, reason); break; case NM_DEVICE_STATE_DISCONNECTED: @@ -5416,10 +5447,17 @@ nm_device_state_changed (NMDevice *device, nm_device_get_iface (device)); nm_device_queue_state (device, NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_NONE); } else { - nm_log_dbg (LOGD_DEVICE, "(%s): device not yet available for transition to DISCONNECTED", - nm_device_get_iface (device)); + if (old_state == NM_DEVICE_STATE_UNMANAGED) { + nm_log_dbg (LOGD_DEVICE, "(%s): device not yet available for transition to DISCONNECTED", + nm_device_get_iface (device)); + } else if (old_state > NM_DEVICE_STATE_UNAVAILABLE && priv->default_unmanaged) + nm_device_queue_state (device, NM_DEVICE_STATE_UNMANAGED, NM_DEVICE_STATE_REASON_NONE); } break; + case NM_DEVICE_STATE_DISCONNECTED: + if (old_state > NM_DEVICE_STATE_DISCONNECTED && priv->default_unmanaged) + nm_device_queue_state (device, NM_DEVICE_STATE_UNMANAGED, NM_DEVICE_STATE_REASON_NONE); + break; case NM_DEVICE_STATE_ACTIVATED: nm_log_info (LOGD_DEVICE, "Activation (%s) successful, device activated.", nm_device_get_iface (device)); @@ -5633,39 +5671,79 @@ nm_device_queued_ip_config_change_clear (NMDevice *self) gboolean nm_device_get_managed (NMDevice *device) -{ - g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); - - return NM_DEVICE_GET_PRIVATE (device)->managed; -} - -void -nm_device_set_managed (NMDevice *device, - gboolean managed, - NMDeviceStateReason reason) { NMDevicePrivate *priv; - g_return_if_fail (NM_IS_DEVICE (device)); + g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); priv = NM_DEVICE_GET_PRIVATE (device); - if (priv->managed == managed) - return; - priv->managed = managed; + if (!priv->manager_managed) + return FALSE; + else if (priv->default_unmanaged) + return (priv->state != NM_DEVICE_STATE_UNMANAGED); + else + return TRUE; +} + +static void +nm_device_set_managed_internal (NMDevice *device, + gboolean managed, + NMDeviceStateReason reason) +{ nm_log_dbg (LOGD_DEVICE, "(%s): now %s", nm_device_get_iface (device), managed ? "managed" : "unmanaged"); g_object_notify (G_OBJECT (device), NM_DEVICE_MANAGED); - /* If now managed, jump to unavailable */ if (managed) nm_device_state_changed (device, NM_DEVICE_STATE_UNAVAILABLE, reason); else nm_device_state_changed (device, NM_DEVICE_STATE_UNMANAGED, reason); } +void +nm_device_set_manager_managed (NMDevice *device, + gboolean managed, + NMDeviceStateReason reason) +{ + NMDevicePrivate *priv; + gboolean was_managed, now_managed; + + g_return_if_fail (NM_IS_DEVICE (device)); + + priv = NM_DEVICE_GET_PRIVATE (device); + + was_managed = nm_device_get_managed (device); + priv->manager_managed = managed; + now_managed = nm_device_get_managed (device); + + if (was_managed != now_managed) + nm_device_set_managed_internal (device, now_managed, reason); +} + +void +nm_device_set_default_unmanaged (NMDevice *device, + gboolean default_unmanaged) +{ + NMDevicePrivate *priv; + gboolean was_managed, now_managed; + + g_return_if_fail (NM_IS_DEVICE (device)); + + priv = NM_DEVICE_GET_PRIVATE (device); + + was_managed = nm_device_get_managed (device); + priv->default_unmanaged = default_unmanaged; + now_managed = nm_device_get_managed (device); + + if (was_managed != now_managed) + nm_device_set_managed_internal (device, now_managed, + default_unmanaged ? NM_DEVICE_STATE_REASON_NOW_UNMANAGED : + NM_DEVICE_STATE_REASON_NOW_MANAGED); +} + /** * nm_device_spec_match_list: * @device: an #NMDevice diff --git a/src/nm-device.h b/src/nm-device.h index ea3cc0e706..f6b4f95f4f 100644 --- a/src/nm-device.h +++ b/src/nm-device.h @@ -237,6 +237,8 @@ NMActRequest * nm_device_get_act_request (NMDevice *dev); NMConnection * nm_device_get_connection (NMDevice *dev); gboolean nm_device_is_available (NMDevice *dev); +gboolean nm_device_can_activate (NMDevice *dev); + gboolean nm_device_ignore_carrier (NMDevice *dev); NMConnection * nm_device_get_best_auto_connection (NMDevice *dev, @@ -279,9 +281,11 @@ void nm_device_set_enabled (NMDevice *device, gboolean enabled); RfKillType nm_device_get_rfkill_type (NMDevice *device); gboolean nm_device_get_managed (NMDevice *device); -void nm_device_set_managed (NMDevice *device, - gboolean managed, - NMDeviceStateReason reason); +void nm_device_set_manager_managed (NMDevice *device, + gboolean managed, + NMDeviceStateReason reason); +void nm_device_set_default_unmanaged (NMDevice *device, + gboolean default_unmanaged); gboolean nm_device_get_autoconnect (NMDevice *device); diff --git a/src/nm-manager.c b/src/nm-manager.c index 057bc3c1b7..a82d741ade 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -620,7 +620,7 @@ remove_one_device (NMManager *manager, if ( !nm_device_can_assume_connections (device) || (nm_device_get_state (device) != NM_DEVICE_STATE_ACTIVATED) || !quitting) - nm_device_set_managed (device, FALSE, NM_DEVICE_STATE_REASON_REMOVED); + nm_device_set_manager_managed (device, FALSE, NM_DEVICE_STATE_REASON_REMOVED); } g_signal_handlers_disconnect_by_func (device, manager_device_state_changed, manager); @@ -1362,10 +1362,10 @@ system_unmanaged_devices_changed_cb (NMSettings *settings, gboolean managed; managed = !nm_device_spec_match_list (device, unmanaged_specs); - nm_device_set_managed (device, - managed, - managed ? NM_DEVICE_STATE_REASON_NOW_MANAGED : - NM_DEVICE_STATE_REASON_NOW_UNMANAGED); + nm_device_set_manager_managed (device, + managed, + managed ? NM_DEVICE_STATE_REASON_NOW_MANAGED : + NM_DEVICE_STATE_REASON_NOW_UNMANAGED); } } @@ -1788,7 +1788,7 @@ add_device (NMManager *self, NMDevice *device) static guint32 devcount = 0; const GSList *unmanaged_specs; NMConnection *existing = NULL; - gboolean managed = FALSE, enabled = FALSE; + gboolean enabled = FALSE; RfKillType rtype; NMDeviceType devtype; @@ -1887,11 +1887,10 @@ add_device (NMManager *self, NMDevice *device) unmanaged_specs = nm_settings_get_unmanaged_specs (priv->settings); if ( !manager_sleeping (self) && !nm_device_spec_match_list (device, unmanaged_specs)) { - nm_device_set_managed (device, - TRUE, - existing ? NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED : - NM_DEVICE_STATE_REASON_NOW_MANAGED); - managed = TRUE; + nm_device_set_manager_managed (device, + TRUE, + existing ? NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED : + NM_DEVICE_STATE_REASON_NOW_MANAGED); } nm_settings_device_added (priv->settings, device); @@ -1903,7 +1902,7 @@ add_device (NMManager *self, NMDevice *device) system_create_virtual_devices (self); /* If the device has a connection it can assume, do that now */ - if (existing && managed && nm_device_is_available (device)) { + if (existing && nm_device_can_activate (device)) { NMActiveConnection *ac; GError *error = NULL; @@ -2753,7 +2752,6 @@ nm_manager_activate_connection (NMManager *manager, NMManagerPrivate *priv; NMDevice *device = NULL; gulong sender_uid = G_MAXULONG; - NMDeviceState state; char *iface; NMDevice *master_device = NULL; NMConnection *master_connection = NULL; @@ -2843,22 +2841,10 @@ nm_manager_activate_connection (NMManager *manager, "Failed to create virtual interface"); return NULL; } - - /* A newly created device, if allowed to be managed by NM, will be - * in the UNAVAILABLE state here. Since we want to use it right - * away, we transition it immediately to DISCONNECTED. - */ - if ( nm_device_is_available (device) - && (nm_device_get_state (device) == NM_DEVICE_STATE_UNAVAILABLE)) { - nm_device_state_changed (device, - NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_REASON_NONE); - } } } - state = nm_device_get_state (device); - if (state < NM_DEVICE_STATE_DISCONNECTED) { + if (!nm_device_can_activate (device)) { g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNMANAGED_DEVICE, "Device not managed by NetworkManager or unavailable"); return NULL; @@ -3245,7 +3231,7 @@ do_sleep_wake (NMManager *self) * the manager wakes up. */ for (iter = priv->devices; iter; iter = iter->next) - nm_device_set_managed (NM_DEVICE (iter->data), FALSE, NM_DEVICE_STATE_REASON_SLEEPING); + nm_device_set_manager_managed (NM_DEVICE (iter->data), FALSE, NM_DEVICE_STATE_REASON_SLEEPING); } else { nm_log_info (LOGD_SUSPEND, "waking up and re-enabling..."); @@ -3282,9 +3268,9 @@ do_sleep_wake (NMManager *self) g_object_set (G_OBJECT (device), NM_DEVICE_AUTOCONNECT, TRUE, NULL); if (nm_device_spec_match_list (device, unmanaged_specs)) - nm_device_set_managed (device, FALSE, NM_DEVICE_STATE_REASON_NOW_UNMANAGED); + nm_device_set_manager_managed (device, FALSE, NM_DEVICE_STATE_REASON_NOW_UNMANAGED); else - nm_device_set_managed (device, TRUE, NM_DEVICE_STATE_REASON_NOW_MANAGED); + nm_device_set_manager_managed (device, TRUE, NM_DEVICE_STATE_REASON_NOW_MANAGED); } } diff --git a/src/nm-policy.c b/src/nm-policy.c index 8c034ea6a1..faa9648fa1 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -1146,13 +1146,11 @@ static void schedule_activate_check (NMPolicy *policy, NMDevice *device, guint delay_seconds) { ActivateData *data; - NMDeviceState state; if (nm_manager_get_state (policy->manager) == NM_STATE_ASLEEP) return; - state = nm_device_get_state (device); - if (state < NM_DEVICE_STATE_DISCONNECTED) + if (!nm_device_can_activate (device)) return; if (!nm_device_get_enabled (device))