mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-05-08 13:38:43 +02:00
merge: branch 'lr/virtual-parent-bgo762731'
https://bugzilla.gnome.org/show_bug.cgi?id=762731
This commit is contained in:
commit
bbc941245d
5 changed files with 240 additions and 85 deletions
|
|
@ -7735,7 +7735,7 @@ nm_device_queue_activation (NMDevice *self, NMActRequest *req)
|
||||||
|
|
||||||
must_queue = _carrier_wait_check_act_request_must_queue (self, req);
|
must_queue = _carrier_wait_check_act_request_must_queue (self, req);
|
||||||
|
|
||||||
if (!priv->act_request && !must_queue) {
|
if (!priv->act_request && !must_queue && nm_device_is_real (self)) {
|
||||||
/* Just activate immediately */
|
/* Just activate immediately */
|
||||||
if (!_device_activate (self, req))
|
if (!_device_activate (self, req))
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
|
|
@ -9689,39 +9689,55 @@ nm_device_recheck_available_connections (NMDevice *self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nm_device_get_available_connections:
|
* nm_device_get_best_connection:
|
||||||
* @self: the #NMDevice
|
* @self: the #NMDevice
|
||||||
* @specific_object: a specific object path if any
|
* @specific_object: a specific object path if any
|
||||||
|
* @error: reason why no connection was returned
|
||||||
*
|
*
|
||||||
* Returns a list of connections available to activate on the device, taking
|
* Returns a connection that's most suitable for user-initiated activation
|
||||||
* into account any device-specific details given by @specific_object (like
|
* of a device, optionally with a given specific object.
|
||||||
* WiFi access point path).
|
|
||||||
*
|
*
|
||||||
* Returns: caller-owned #GPtrArray of #NMConnections
|
* Returns: the #NMSettingsConnection or %NULL (setting an @error)
|
||||||
*/
|
*/
|
||||||
GPtrArray *
|
NMSettingsConnection *
|
||||||
nm_device_get_available_connections (NMDevice *self, const char *specific_object)
|
nm_device_get_best_connection (NMDevice *self,
|
||||||
|
const char *specific_object,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||||
|
NMSettingsConnection *connection = NULL;
|
||||||
|
NMSettingsConnection *candidate;
|
||||||
|
guint64 best_timestamp = 0;
|
||||||
GHashTableIter iter;
|
GHashTableIter iter;
|
||||||
guint num_available;
|
|
||||||
NMConnection *connection = NULL;
|
|
||||||
GPtrArray *array = NULL;
|
|
||||||
|
|
||||||
num_available = g_hash_table_size (priv->available_connections);
|
g_hash_table_iter_init (&iter, priv->available_connections);
|
||||||
if (num_available > 0) {
|
while (g_hash_table_iter_next (&iter, (gpointer) &candidate, NULL)) {
|
||||||
array = g_ptr_array_sized_new (num_available);
|
guint64 candidate_timestamp = 0;
|
||||||
g_hash_table_iter_init (&iter, priv->available_connections);
|
|
||||||
while (g_hash_table_iter_next (&iter, (gpointer) &connection, NULL)) {
|
/* If a specific object is given, only include connections that are
|
||||||
/* If a specific object is given, only include connections that are
|
* compatible with it.
|
||||||
* compatible with it.
|
*/
|
||||||
*/
|
if ( specific_object /* << Optimization: we know that the connection is available without @specific_object. */
|
||||||
if ( !specific_object /* << Optimization: we know that the connection is available without @specific_object. */
|
&& !nm_device_check_connection_available (self,
|
||||||
|| nm_device_check_connection_available (self, connection, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST, specific_object))
|
NM_CONNECTION (candidate),
|
||||||
g_ptr_array_add (array, connection);
|
_NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST,
|
||||||
|
specific_object))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
nm_settings_connection_get_timestamp (candidate, &candidate_timestamp);
|
||||||
|
if (!connection || (candidate_timestamp > best_timestamp)) {
|
||||||
|
connection = candidate;
|
||||||
|
best_timestamp = candidate_timestamp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return array;
|
|
||||||
|
if (!connection) {
|
||||||
|
g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_CONNECTION,
|
||||||
|
"The device '%s' has no connections available for activation.",
|
||||||
|
nm_device_get_iface (self));
|
||||||
|
}
|
||||||
|
|
||||||
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -10384,7 +10400,8 @@ _set_state_full (NMDevice *self,
|
||||||
if (state <= NM_DEVICE_STATE_UNAVAILABLE) {
|
if (state <= NM_DEVICE_STATE_UNAVAILABLE) {
|
||||||
if (available_connections_del_all (self))
|
if (available_connections_del_all (self))
|
||||||
available_connections_notify (self);
|
available_connections_notify (self);
|
||||||
_clear_queued_act_request (priv);
|
if (old_state > NM_DEVICE_STATE_UNAVAILABLE)
|
||||||
|
_clear_queued_act_request (priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update the available connections list when a device first becomes available */
|
/* Update the available connections list when a device first becomes available */
|
||||||
|
|
|
||||||
|
|
@ -529,8 +529,9 @@ gboolean nm_device_add_pending_action (NMDevice *device, const char *action,
|
||||||
gboolean nm_device_remove_pending_action (NMDevice *device, const char *action, gboolean assert_is_pending);
|
gboolean nm_device_remove_pending_action (NMDevice *device, const char *action, gboolean assert_is_pending);
|
||||||
gboolean nm_device_has_pending_action (NMDevice *device);
|
gboolean nm_device_has_pending_action (NMDevice *device);
|
||||||
|
|
||||||
GPtrArray *nm_device_get_available_connections (NMDevice *device,
|
NMSettingsConnection *nm_device_get_best_connection (NMDevice *device,
|
||||||
const char *specific_object);
|
const char *specific_object,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
gboolean nm_device_check_connection_available (NMDevice *device,
|
gboolean nm_device_check_connection_available (NMDevice *device,
|
||||||
NMConnection *connection,
|
NMConnection *connection,
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,8 @@ typedef struct {
|
||||||
NMActiveConnection *master;
|
NMActiveConnection *master;
|
||||||
gboolean master_ready;
|
gboolean master_ready;
|
||||||
|
|
||||||
|
NMActiveConnection *parent;
|
||||||
|
|
||||||
gboolean assumed;
|
gboolean assumed;
|
||||||
|
|
||||||
NMAuthChain *chain;
|
NMAuthChain *chain;
|
||||||
|
|
@ -98,6 +100,7 @@ enum {
|
||||||
enum {
|
enum {
|
||||||
DEVICE_CHANGED,
|
DEVICE_CHANGED,
|
||||||
DEVICE_METERED_CHANGED,
|
DEVICE_METERED_CHANGED,
|
||||||
|
PARENT_ACTIVE,
|
||||||
LAST_SIGNAL
|
LAST_SIGNAL
|
||||||
};
|
};
|
||||||
static guint signals[LAST_SIGNAL] = { 0 };
|
static guint signals[LAST_SIGNAL] = { 0 };
|
||||||
|
|
@ -678,6 +681,69 @@ nm_active_connection_get_assumed (NMActiveConnection *self)
|
||||||
|
|
||||||
/****************************************************************/
|
/****************************************************************/
|
||||||
|
|
||||||
|
static void unwatch_parent (NMActiveConnection *self);
|
||||||
|
|
||||||
|
static void
|
||||||
|
parent_destroyed (gpointer user_data, GObject *parent)
|
||||||
|
{
|
||||||
|
NMActiveConnection *self = user_data;
|
||||||
|
|
||||||
|
unwatch_parent (self);
|
||||||
|
g_signal_emit (self, signals[PARENT_ACTIVE], 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
parent_state_cb (NMActiveConnection *parent_ac,
|
||||||
|
GParamSpec *pspec,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
NMActiveConnection *self = user_data;
|
||||||
|
NMActiveConnectionState parent_state = nm_active_connection_get_state (parent_ac);
|
||||||
|
|
||||||
|
if (parent_state < NM_ACTIVE_CONNECTION_STATE_ACTIVATED)
|
||||||
|
return;
|
||||||
|
|
||||||
|
unwatch_parent (self);
|
||||||
|
g_signal_emit (self, signals[PARENT_ACTIVE], 0, parent_ac);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
unwatch_parent (NMActiveConnection *self)
|
||||||
|
{
|
||||||
|
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
||||||
|
|
||||||
|
g_signal_handlers_disconnect_by_func (priv->parent,
|
||||||
|
(GCallback) parent_state_cb,
|
||||||
|
self);
|
||||||
|
g_object_weak_unref ((GObject *) priv->parent, parent_destroyed, self);
|
||||||
|
priv->parent = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nm_active_connection_set_parent:
|
||||||
|
* @self: the #NMActiveConnection
|
||||||
|
* @parent: The #NMActiveConnection that must be active before the manager
|
||||||
|
* can proceed progressing the device to disconnected state for us.
|
||||||
|
*
|
||||||
|
* Sets the parent connection of @self. A "parent-active" signal will be
|
||||||
|
* emitted when the parent connection becomes active.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
nm_active_connection_set_parent (NMActiveConnection *self, NMActiveConnection *parent)
|
||||||
|
{
|
||||||
|
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
||||||
|
|
||||||
|
g_return_if_fail (priv->parent == NULL);
|
||||||
|
priv->parent = parent;
|
||||||
|
g_signal_connect (priv->parent,
|
||||||
|
"notify::" NM_ACTIVE_CONNECTION_STATE,
|
||||||
|
(GCallback) parent_state_cb,
|
||||||
|
self);
|
||||||
|
g_object_weak_ref ((GObject *) priv->parent, parent_destroyed, self);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
auth_done (NMAuthChain *chain,
|
auth_done (NMAuthChain *chain,
|
||||||
GError *error,
|
GError *error,
|
||||||
|
|
@ -1028,6 +1094,10 @@ dispose (GObject *object)
|
||||||
self);
|
self);
|
||||||
}
|
}
|
||||||
g_clear_object (&priv->master);
|
g_clear_object (&priv->master);
|
||||||
|
|
||||||
|
if (priv->parent)
|
||||||
|
unwatch_parent (self);
|
||||||
|
|
||||||
g_clear_object (&priv->subject);
|
g_clear_object (&priv->subject);
|
||||||
|
|
||||||
G_OBJECT_CLASS (nm_active_connection_parent_class)->dispose (object);
|
G_OBJECT_CLASS (nm_active_connection_parent_class)->dispose (object);
|
||||||
|
|
@ -1208,6 +1278,14 @@ nm_active_connection_class_init (NMActiveConnectionClass *ac_class)
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
G_TYPE_NONE, 1, G_TYPE_UINT);
|
G_TYPE_NONE, 1, G_TYPE_UINT);
|
||||||
|
|
||||||
|
signals[PARENT_ACTIVE] =
|
||||||
|
g_signal_new (NM_ACTIVE_CONNECTION_PARENT_ACTIVE,
|
||||||
|
G_OBJECT_CLASS_TYPE (object_class),
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
G_STRUCT_OFFSET (NMActiveConnectionClass, parent_active),
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
G_TYPE_NONE, 1, NM_TYPE_ACTIVE_CONNECTION);
|
||||||
|
|
||||||
nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (ac_class),
|
nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (ac_class),
|
||||||
NMDBUS_TYPE_ACTIVE_CONNECTION_SKELETON,
|
NMDBUS_TYPE_ACTIVE_CONNECTION_SKELETON,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@
|
||||||
/* Internal signals*/
|
/* Internal signals*/
|
||||||
#define NM_ACTIVE_CONNECTION_DEVICE_CHANGED "device-changed"
|
#define NM_ACTIVE_CONNECTION_DEVICE_CHANGED "device-changed"
|
||||||
#define NM_ACTIVE_CONNECTION_DEVICE_METERED_CHANGED "device-metered-changed"
|
#define NM_ACTIVE_CONNECTION_DEVICE_METERED_CHANGED "device-metered-changed"
|
||||||
|
#define NM_ACTIVE_CONNECTION_PARENT_ACTIVE "parent-active"
|
||||||
|
|
||||||
struct _NMActiveConnection {
|
struct _NMActiveConnection {
|
||||||
NMExportedObject parent;
|
NMExportedObject parent;
|
||||||
|
|
@ -81,6 +82,8 @@ typedef struct {
|
||||||
|
|
||||||
void (*device_metered_changed) (NMActiveConnection *connection,
|
void (*device_metered_changed) (NMActiveConnection *connection,
|
||||||
NMMetered new_value);
|
NMMetered new_value);
|
||||||
|
|
||||||
|
void (*parent_active) (NMActiveConnection *connection);
|
||||||
} NMActiveConnectionClass;
|
} NMActiveConnectionClass;
|
||||||
|
|
||||||
guint64 nm_active_connection_version_id_get (NMActiveConnection *self);
|
guint64 nm_active_connection_version_id_get (NMActiveConnection *self);
|
||||||
|
|
@ -148,6 +151,9 @@ gboolean nm_active_connection_get_master_ready (NMActiveConnection *self);
|
||||||
void nm_active_connection_set_master (NMActiveConnection *self,
|
void nm_active_connection_set_master (NMActiveConnection *self,
|
||||||
NMActiveConnection *master);
|
NMActiveConnection *master);
|
||||||
|
|
||||||
|
void nm_active_connection_set_parent (NMActiveConnection *self,
|
||||||
|
NMActiveConnection *parent);
|
||||||
|
|
||||||
void nm_active_connection_set_assumed (NMActiveConnection *self,
|
void nm_active_connection_set_assumed (NMActiveConnection *self,
|
||||||
gboolean assumed);
|
gboolean assumed);
|
||||||
|
|
||||||
|
|
|
||||||
171
src/nm-manager.c
171
src/nm-manager.c
|
|
@ -226,6 +226,9 @@ static void active_connection_state_changed (NMActiveConnection *active,
|
||||||
static void active_connection_default_changed (NMActiveConnection *active,
|
static void active_connection_default_changed (NMActiveConnection *active,
|
||||||
GParamSpec *pspec,
|
GParamSpec *pspec,
|
||||||
NMManager *self);
|
NMManager *self);
|
||||||
|
static void active_connection_parent_active (NMActiveConnection *active,
|
||||||
|
NMActiveConnection *parent_ac,
|
||||||
|
NMManager *self);
|
||||||
|
|
||||||
/* Returns: whether to notify D-Bus of the removal or not */
|
/* Returns: whether to notify D-Bus of the removal or not */
|
||||||
static gboolean
|
static gboolean
|
||||||
|
|
@ -244,6 +247,7 @@ active_connection_remove (NMManager *self, NMActiveConnection *active)
|
||||||
g_signal_emit (self, signals[ACTIVE_CONNECTION_REMOVED], 0, active);
|
g_signal_emit (self, signals[ACTIVE_CONNECTION_REMOVED], 0, active);
|
||||||
g_signal_handlers_disconnect_by_func (active, active_connection_state_changed, self);
|
g_signal_handlers_disconnect_by_func (active, active_connection_state_changed, self);
|
||||||
g_signal_handlers_disconnect_by_func (active, active_connection_default_changed, self);
|
g_signal_handlers_disconnect_by_func (active, active_connection_default_changed, self);
|
||||||
|
g_signal_handlers_disconnect_by_func (active, active_connection_parent_active, self);
|
||||||
|
|
||||||
if ( nm_active_connection_get_assumed (active)
|
if ( nm_active_connection_get_assumed (active)
|
||||||
&& (connection = nm_active_connection_get_settings_connection (active))
|
&& (connection = nm_active_connection_get_settings_connection (active))
|
||||||
|
|
@ -2723,6 +2727,71 @@ _internal_activate_vpn (NMManager *self, NMActiveConnection *active, GError **er
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Traverse the device to disconnected state. This means that the device is ready
|
||||||
|
* for connection and will proceed activating if there's an activation request
|
||||||
|
* enqueued.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
unmanaged_to_disconnected (NMDevice *device)
|
||||||
|
{
|
||||||
|
/* when creating the software device, it can happen that the device is
|
||||||
|
* still unmanaged by NM_UNMANAGED_PLATFORM_INIT because we didn't yet
|
||||||
|
* get the udev event. At this point, we can no longer delay the activation
|
||||||
|
* and force the device to be managed. */
|
||||||
|
nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_PLATFORM_INIT, FALSE, NM_DEVICE_STATE_REASON_USER_REQUESTED);
|
||||||
|
|
||||||
|
nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_USER_EXPLICIT, FALSE, NM_DEVICE_STATE_REASON_USER_REQUESTED);
|
||||||
|
|
||||||
|
g_return_if_fail (nm_device_get_managed (device, FALSE));
|
||||||
|
|
||||||
|
if (nm_device_get_state (device) == NM_DEVICE_STATE_UNMANAGED) {
|
||||||
|
nm_device_state_changed (device,
|
||||||
|
NM_DEVICE_STATE_UNAVAILABLE,
|
||||||
|
NM_DEVICE_STATE_REASON_USER_REQUESTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( nm_device_is_available (device, NM_DEVICE_CHECK_DEV_AVAILABLE_FOR_USER_REQUEST)
|
||||||
|
&& (nm_device_get_state (device) == NM_DEVICE_STATE_UNAVAILABLE)) {
|
||||||
|
nm_device_state_changed (device,
|
||||||
|
NM_DEVICE_STATE_DISCONNECTED,
|
||||||
|
NM_DEVICE_STATE_REASON_USER_REQUESTED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The parent connection is ready; we can proceed realizing the device and
|
||||||
|
* progressing the device to disconencted state.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
active_connection_parent_active (NMActiveConnection *active,
|
||||||
|
NMActiveConnection *parent_ac,
|
||||||
|
NMManager *self)
|
||||||
|
{
|
||||||
|
NMDevice *device = nm_active_connection_get_device (active);
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
g_signal_handlers_disconnect_by_func (active,
|
||||||
|
(GCallback) active_connection_parent_active,
|
||||||
|
self);
|
||||||
|
|
||||||
|
if (parent_ac) {
|
||||||
|
NMSettingsConnection *connection = nm_active_connection_get_settings_connection (active);
|
||||||
|
NMDevice *parent = nm_active_connection_get_device (parent_ac);
|
||||||
|
|
||||||
|
if (nm_device_create_and_realize (device, (NMConnection *) connection, parent, &error)) {
|
||||||
|
/* We can now proceed to disconnected state so that activation proceeds. */
|
||||||
|
unmanaged_to_disconnected (device);
|
||||||
|
} else {
|
||||||
|
nm_log_warn (LOGD_CORE, "Could not realize device '%s': %s",
|
||||||
|
nm_device_get_iface (device), error->message);
|
||||||
|
nm_active_connection_set_state (active, NM_ACTIVE_CONNECTION_STATE_DEACTIVATED);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nm_log_warn (LOGD_CORE, "The parent connection device '%s' depended on disappeared.",
|
||||||
|
nm_device_get_iface (device));
|
||||||
|
nm_active_connection_set_state (active, NM_ACTIVE_CONNECTION_STATE_DEACTIVATED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
_internal_activate_device (NMManager *self, NMActiveConnection *active, GError **error)
|
_internal_activate_device (NMManager *self, NMActiveConnection *active, GError **error)
|
||||||
{
|
{
|
||||||
|
|
@ -2782,9 +2851,35 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError *
|
||||||
NMDevice *parent;
|
NMDevice *parent;
|
||||||
|
|
||||||
parent = find_parent_device_for_connection (self, (NMConnection *) connection, NULL);
|
parent = find_parent_device_for_connection (self, (NMConnection *) connection, NULL);
|
||||||
if (!nm_device_create_and_realize (device, (NMConnection *) connection, parent, error)) {
|
|
||||||
g_prefix_error (error, "%s failed to create resources: ", nm_device_get_iface (device));
|
if (parent && !nm_device_is_real (parent)) {
|
||||||
return FALSE;
|
NMSettingsConnection *parent_con;
|
||||||
|
NMActiveConnection *parent_ac;
|
||||||
|
|
||||||
|
parent_con = nm_device_get_best_connection (parent, NULL, error);
|
||||||
|
if (!parent_con) {
|
||||||
|
g_prefix_error (error, "%s failed to create parent: ", nm_device_get_iface (device));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent_ac = nm_manager_activate_connection (self, parent_con, NULL, parent, subject, error);
|
||||||
|
if (!parent_ac) {
|
||||||
|
g_prefix_error (error, "%s failed to activate parent: ", nm_device_get_iface (device));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We can't realize now; defer until the parent device is ready. */
|
||||||
|
g_signal_connect (active,
|
||||||
|
NM_ACTIVE_CONNECTION_PARENT_ACTIVE,
|
||||||
|
(GCallback) active_connection_parent_active,
|
||||||
|
self);
|
||||||
|
nm_active_connection_set_parent (active, parent_ac);
|
||||||
|
} else {
|
||||||
|
/* We can realize now; no need to wait for a parent device. */
|
||||||
|
if (!nm_device_create_and_realize (device, (NMConnection *) connection, parent, error)) {
|
||||||
|
g_prefix_error (error, "%s failed to create resources: ", nm_device_get_iface (device));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2846,28 +2941,9 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError *
|
||||||
if (existing)
|
if (existing)
|
||||||
nm_device_steal_connection (existing, connection);
|
nm_device_steal_connection (existing, connection);
|
||||||
|
|
||||||
/* when creating the software device, it can happen that the device is
|
/* If the device is there, we can ready it for the activation. */
|
||||||
* still unmanaged by NM_UNMANAGED_PLATFORM_INIT because we didn't yet
|
if (nm_device_is_real (device))
|
||||||
* get the udev event. At this point, we can no longer delay the activation
|
unmanaged_to_disconnected (device);
|
||||||
* and force the device to be managed. */
|
|
||||||
nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_PLATFORM_INIT, FALSE, NM_DEVICE_STATE_REASON_USER_REQUESTED);
|
|
||||||
|
|
||||||
nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_USER_EXPLICIT, FALSE, NM_DEVICE_STATE_REASON_USER_REQUESTED);
|
|
||||||
|
|
||||||
g_return_val_if_fail (nm_device_get_managed (device, FALSE), FALSE);
|
|
||||||
|
|
||||||
if (nm_device_get_state (device) == NM_DEVICE_STATE_UNMANAGED) {
|
|
||||||
nm_device_state_changed (device,
|
|
||||||
NM_DEVICE_STATE_UNAVAILABLE,
|
|
||||||
NM_DEVICE_STATE_REASON_USER_REQUESTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( nm_device_is_available (device, NM_DEVICE_CHECK_DEV_AVAILABLE_FOR_USER_REQUEST)
|
|
||||||
&& (nm_device_get_state (device) == NM_DEVICE_STATE_UNAVAILABLE)) {
|
|
||||||
nm_device_state_changed (device,
|
|
||||||
NM_DEVICE_STATE_DISCONNECTED,
|
|
||||||
NM_DEVICE_STATE_REASON_USER_REQUESTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Export the new ActiveConnection to clients and start it on the device */
|
/* Export the new ActiveConnection to clients and start it on the device */
|
||||||
nm_exported_object_export (NM_EXPORTED_OBJECT (active));
|
nm_exported_object_export (NM_EXPORTED_OBJECT (active));
|
||||||
|
|
@ -3325,11 +3401,15 @@ impl_manager_activate_connection (NMManager *self,
|
||||||
* regardless of whether that connection is autoconnect-enabled or not
|
* regardless of whether that connection is autoconnect-enabled or not
|
||||||
* (since this is an explicit request, not an auto-activation request).
|
* (since this is an explicit request, not an auto-activation request).
|
||||||
*/
|
*/
|
||||||
if (!connection_path) {
|
if (connection_path) {
|
||||||
GPtrArray *available;
|
connection = nm_settings_get_connection_by_path (priv->settings, connection_path);
|
||||||
guint64 best_timestamp = 0;
|
if (!connection) {
|
||||||
guint i;
|
error = g_error_new_literal (NM_MANAGER_ERROR,
|
||||||
|
NM_MANAGER_ERROR_UNKNOWN_CONNECTION,
|
||||||
|
"Connection could not be found.");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
/* If no connection is given, find a suitable connection for the given device path */
|
/* If no connection is given, find a suitable connection for the given device path */
|
||||||
if (!device_path) {
|
if (!device_path) {
|
||||||
error = g_error_new_literal (NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE,
|
error = g_error_new_literal (NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE,
|
||||||
|
|
@ -3343,36 +3423,9 @@ impl_manager_activate_connection (NMManager *self,
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
available = nm_device_get_available_connections (device, specific_object_path);
|
connection = nm_device_get_best_connection (device, specific_object_path, &error);
|
||||||
for (i = 0; available && i < available->len; i++) {
|
if (!connection)
|
||||||
NMSettingsConnection *candidate = g_ptr_array_index (available, i);
|
|
||||||
guint64 candidate_timestamp = 0;
|
|
||||||
|
|
||||||
nm_settings_connection_get_timestamp (candidate, &candidate_timestamp);
|
|
||||||
if (!connection_path || (candidate_timestamp > best_timestamp)) {
|
|
||||||
connection_path = nm_connection_get_path (NM_CONNECTION (candidate));
|
|
||||||
best_timestamp = candidate_timestamp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (available)
|
|
||||||
g_ptr_array_free (available, TRUE);
|
|
||||||
|
|
||||||
if (!connection_path) {
|
|
||||||
error = g_error_new_literal (NM_MANAGER_ERROR,
|
|
||||||
NM_MANAGER_ERROR_UNKNOWN_CONNECTION,
|
|
||||||
"The device has no connections available.");
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g_assert (connection_path);
|
|
||||||
connection = nm_settings_get_connection_by_path (priv->settings, connection_path);
|
|
||||||
if (!connection) {
|
|
||||||
error = g_error_new_literal (NM_MANAGER_ERROR,
|
|
||||||
NM_MANAGER_ERROR_UNKNOWN_CONNECTION,
|
|
||||||
"Connection could not be found.");
|
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
subject = validate_activation_request (self,
|
subject = validate_activation_request (self,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue