mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-05 04:30:16 +01:00
devices: improve master/slave handling of assumed connections
https://bugzilla.gnome.org/show_bug.cgi?id=729843 https://bugzilla.redhat.com/show_bug.cgi?id=1066706
This commit is contained in:
commit
d3a51b6e4a
13 changed files with 468 additions and 172 deletions
|
|
@ -421,42 +421,56 @@ enslave_slave (NMDevice *device,
|
|||
success = nm_platform_link_enslave (nm_device_get_ip_ifindex (device),
|
||||
nm_device_get_ip_ifindex (slave));
|
||||
nm_device_bring_up (slave, TRUE, &no_firmware);
|
||||
}
|
||||
|
||||
if (success) {
|
||||
if (!success)
|
||||
return FALSE;
|
||||
|
||||
nm_log_info (LOGD_BOND, "(%s): enslaved bond slave %s", iface, slave_iface);
|
||||
g_object_notify (G_OBJECT (device), "slaves");
|
||||
}
|
||||
} else
|
||||
nm_log_info (LOGD_BOND, "(%s): bond slave %s was enslaved", iface, slave_iface);
|
||||
|
||||
return success;
|
||||
g_object_notify (G_OBJECT (device), NM_DEVICE_BOND_SLAVES);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
release_slave (NMDevice *device, NMDevice *slave)
|
||||
release_slave (NMDevice *device,
|
||||
NMDevice *slave,
|
||||
gboolean configure)
|
||||
{
|
||||
gboolean success, no_firmware = FALSE;
|
||||
gboolean success = TRUE, no_firmware = FALSE;
|
||||
|
||||
success = nm_platform_link_release (nm_device_get_ip_ifindex (device),
|
||||
nm_device_get_ip_ifindex (slave));
|
||||
if (configure) {
|
||||
success = nm_platform_link_release (nm_device_get_ip_ifindex (device),
|
||||
nm_device_get_ip_ifindex (slave));
|
||||
|
||||
if (success) {
|
||||
nm_log_info (LOGD_BOND, "(%s): released bond slave %s",
|
||||
nm_device_get_ip_iface (device),
|
||||
nm_device_get_ip_iface (slave));
|
||||
if (success) {
|
||||
nm_log_info (LOGD_BOND, "(%s): released bond slave %s",
|
||||
nm_device_get_ip_iface (device),
|
||||
nm_device_get_ip_iface (slave));
|
||||
} else {
|
||||
nm_log_warn (LOGD_BOND, "(%s): failed to release bond slave %s",
|
||||
nm_device_get_ip_iface (device),
|
||||
nm_device_get_ip_iface (slave));
|
||||
}
|
||||
} else {
|
||||
nm_log_warn (LOGD_BOND, "(%s): failed to release bond slave %s",
|
||||
nm_log_info (LOGD_BOND, "(%s): bond slave %s was released",
|
||||
nm_device_get_ip_iface (device),
|
||||
nm_device_get_ip_iface (slave));
|
||||
}
|
||||
g_object_notify (G_OBJECT (device), "slaves");
|
||||
|
||||
/* Kernel bonding code "closes" the slave when releasing it, (which clears
|
||||
* IFF_UP), so we must bring it back up here to ensure carrier changes and
|
||||
* other state is noticed by the now-released slave.
|
||||
*/
|
||||
if (!nm_device_bring_up (slave, TRUE, &no_firmware)) {
|
||||
nm_log_warn (LOGD_BOND, "(%s): released bond slave could not be brought up.",
|
||||
nm_device_get_iface (slave));
|
||||
if (success)
|
||||
g_object_notify (G_OBJECT (device), NM_DEVICE_BOND_SLAVES);
|
||||
|
||||
if (configure) {
|
||||
/* Kernel bonding code "closes" the slave when releasing it, (which clears
|
||||
* IFF_UP), so we must bring it back up here to ensure carrier changes and
|
||||
* other state is noticed by the now-released slave.
|
||||
*/
|
||||
if (!nm_device_bring_up (slave, TRUE, &no_firmware)) {
|
||||
nm_log_warn (LOGD_BOND, "(%s): released bond slave could not be brought up.",
|
||||
nm_device_get_iface (slave));
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
|
|
|
|||
|
|
@ -391,30 +391,43 @@ enslave_slave (NMDevice *device,
|
|||
return FALSE;
|
||||
|
||||
commit_slave_options (slave, nm_connection_get_setting_bridge_port (connection));
|
||||
|
||||
nm_log_info (LOGD_BRIDGE, "(%s): attached bridge port %s",
|
||||
nm_device_get_ip_iface (device),
|
||||
nm_device_get_ip_iface (slave));
|
||||
} else {
|
||||
nm_log_info (LOGD_BRIDGE, "(%s): bridge port %s was attached",
|
||||
nm_device_get_ip_iface (device),
|
||||
nm_device_get_ip_iface (slave));
|
||||
}
|
||||
|
||||
nm_log_info (LOGD_BRIDGE, "(%s): attached bridge port %s",
|
||||
nm_device_get_ip_iface (device),
|
||||
nm_device_get_ip_iface (slave));
|
||||
g_object_notify (G_OBJECT (device), NM_DEVICE_BRIDGE_SLAVES);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
release_slave (NMDevice *device, NMDevice *slave)
|
||||
release_slave (NMDevice *device,
|
||||
NMDevice *slave,
|
||||
gboolean configure)
|
||||
{
|
||||
gboolean success;
|
||||
gboolean success = TRUE;
|
||||
|
||||
success = nm_platform_link_release (nm_device_get_ip_ifindex (device),
|
||||
nm_device_get_ip_ifindex (slave));
|
||||
if (configure) {
|
||||
success = nm_platform_link_release (nm_device_get_ip_ifindex (device),
|
||||
nm_device_get_ip_ifindex (slave));
|
||||
|
||||
if (success) {
|
||||
nm_log_info (LOGD_BRIDGE, "(%s): detached bridge port %s",
|
||||
nm_device_get_ip_iface (device),
|
||||
nm_device_get_ip_iface (slave));
|
||||
if (success) {
|
||||
nm_log_info (LOGD_BRIDGE, "(%s): detached bridge port %s",
|
||||
nm_device_get_ip_iface (device),
|
||||
nm_device_get_ip_iface (slave));
|
||||
} else {
|
||||
nm_log_warn (LOGD_BRIDGE, "(%s): failed to detach bridge port %s",
|
||||
nm_device_get_ip_iface (device),
|
||||
nm_device_get_ip_iface (slave));
|
||||
}
|
||||
} else {
|
||||
nm_log_warn (LOGD_BRIDGE, "(%s): failed to detach bridge port %s",
|
||||
nm_log_info (LOGD_BRIDGE, "(%s): bridge port %s was detached",
|
||||
nm_device_get_ip_iface (device),
|
||||
nm_device_get_ip_iface (slave));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,5 +97,6 @@ void nm_device_master_check_slave_physical_port (NMDevice *dev, NMDevice *slave,
|
|||
void nm_device_set_carrier (NMDevice *device, gboolean carrier);
|
||||
|
||||
void nm_device_emit_recheck_auto_activate (NMDevice *device);
|
||||
void nm_device_queue_recheck_assume (NMDevice *device);
|
||||
|
||||
#endif /* NM_DEVICE_PRIVATE_H */
|
||||
|
|
|
|||
|
|
@ -691,42 +691,57 @@ enslave_slave (NMDevice *device,
|
|||
success = nm_platform_link_enslave (nm_device_get_ip_ifindex (device),
|
||||
nm_device_get_ip_ifindex (slave));
|
||||
nm_device_bring_up (slave, TRUE, &no_firmware);
|
||||
}
|
||||
|
||||
if (success) {
|
||||
if (!success)
|
||||
return FALSE;
|
||||
|
||||
nm_log_info (LOGD_TEAM, "(%s): enslaved team port %s", iface, slave_iface);
|
||||
g_object_notify (G_OBJECT (device), "slaves");
|
||||
}
|
||||
} else
|
||||
nm_log_info (LOGD_TEAM, "(%s): team port %s was enslaved", iface, slave_iface);
|
||||
|
||||
return success;
|
||||
g_object_notify (G_OBJECT (device), NM_DEVICE_TEAM_SLAVES);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
release_slave (NMDevice *device, NMDevice *slave)
|
||||
release_slave (NMDevice *device,
|
||||
NMDevice *slave,
|
||||
gboolean configure)
|
||||
{
|
||||
gboolean success, no_firmware = FALSE;
|
||||
gboolean success = TRUE, no_firmware = FALSE;
|
||||
|
||||
success = nm_platform_link_release (nm_device_get_ip_ifindex (device),
|
||||
nm_device_get_ip_ifindex (slave));
|
||||
if (configure) {
|
||||
success = nm_platform_link_release (nm_device_get_ip_ifindex (device),
|
||||
nm_device_get_ip_ifindex (slave));
|
||||
|
||||
if (success) {
|
||||
nm_log_info (LOGD_TEAM, "(%s): released team port %s",
|
||||
nm_device_get_ip_iface (device),
|
||||
nm_device_get_ip_iface (slave));
|
||||
if (success) {
|
||||
nm_log_info (LOGD_TEAM, "(%s): released team port %s",
|
||||
nm_device_get_ip_iface (device),
|
||||
nm_device_get_ip_iface (slave));
|
||||
} else {
|
||||
nm_log_warn (LOGD_TEAM, "(%s): failed to release team port %s",
|
||||
nm_device_get_ip_iface (device),
|
||||
nm_device_get_ip_iface (slave));
|
||||
}
|
||||
} else {
|
||||
nm_log_warn (LOGD_TEAM, "(%s): failed to release team port %s",
|
||||
nm_log_info (LOGD_TEAM, "(%s): team port %s was released",
|
||||
nm_device_get_ip_iface (device),
|
||||
nm_device_get_ip_iface (slave));
|
||||
}
|
||||
g_object_notify (G_OBJECT (device), "slaves");
|
||||
|
||||
/* Kernel team code "closes" the port when releasing it, (which clears
|
||||
* IFF_UP), so we must bring it back up here to ensure carrier changes and
|
||||
* other state is noticed by the now-released port.
|
||||
*/
|
||||
if (!nm_device_bring_up (slave, TRUE, &no_firmware)) {
|
||||
nm_log_warn (LOGD_TEAM, "(%s): released team port could not be brought up.",
|
||||
nm_device_get_iface (slave));
|
||||
if (success)
|
||||
g_object_notify (G_OBJECT (device), NM_DEVICE_TEAM_SLAVES);
|
||||
|
||||
if (configure) {
|
||||
/* Kernel team code "closes" the port when releasing it, (which clears
|
||||
* IFF_UP), so we must bring it back up here to ensure carrier changes and
|
||||
* other state is noticed by the now-released port.
|
||||
*/
|
||||
if (!nm_device_bring_up (slave, TRUE, &no_firmware)) {
|
||||
nm_log_warn (LOGD_TEAM, "(%s): released team port could not be brought up.",
|
||||
nm_device_get_iface (slave));
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ enum {
|
|||
IP6_CONFIG_CHANGED,
|
||||
REMOVED,
|
||||
RECHECK_AUTO_ACTIVATE,
|
||||
RECHECK_ASSUME,
|
||||
LAST_SIGNAL,
|
||||
};
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
|
@ -237,6 +238,7 @@ typedef struct {
|
|||
gpointer act_source_func;
|
||||
guint act_source6_id;
|
||||
gpointer act_source6_func;
|
||||
guint recheck_assume_id;
|
||||
|
||||
/* Link stuff */
|
||||
guint link_connected_id;
|
||||
|
|
@ -855,6 +857,17 @@ nm_device_get_type_desc (NMDevice *self)
|
|||
return NM_DEVICE_GET_PRIVATE (self)->type_desc;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
nm_device_uses_generated_connection (NMDevice *self)
|
||||
{
|
||||
NMConnection *connection;
|
||||
|
||||
connection = nm_device_get_connection (self);
|
||||
if (!connection)
|
||||
return FALSE;
|
||||
return nm_settings_connection_get_nm_generated (NM_SETTINGS_CONNECTION (connection));
|
||||
}
|
||||
|
||||
static SlaveInfo *
|
||||
find_slave_info (NMDevice *self, NMDevice *slave)
|
||||
{
|
||||
|
|
@ -883,7 +896,7 @@ free_slave_info (SlaveInfo *info)
|
|||
* nm_device_enslave_slave:
|
||||
* @dev: the master device
|
||||
* @slave: the slave device to enslave
|
||||
* @connection: the slave device's connection
|
||||
* @connection: (allow-none): the slave device's connection
|
||||
*
|
||||
* If @dev is capable of enslaving other devices (ie it's a bridge, bond, team,
|
||||
* etc) then this function enslaves @slave.
|
||||
|
|
@ -896,20 +909,27 @@ nm_device_enslave_slave (NMDevice *dev, NMDevice *slave, NMConnection *connectio
|
|||
{
|
||||
SlaveInfo *info;
|
||||
gboolean success = FALSE;
|
||||
gboolean configure;
|
||||
|
||||
g_return_val_if_fail (dev != NULL, FALSE);
|
||||
g_return_val_if_fail (slave != NULL, FALSE);
|
||||
g_return_val_if_fail (nm_device_get_state (slave) >= NM_DEVICE_STATE_DISCONNECTED, FALSE);
|
||||
g_return_val_if_fail (NM_DEVICE_GET_CLASS (dev)->enslave_slave != NULL, FALSE);
|
||||
|
||||
info = find_slave_info (dev, slave);
|
||||
if (!info)
|
||||
return FALSE;
|
||||
|
||||
g_warn_if_fail (info->enslaved == FALSE);
|
||||
success = NM_DEVICE_GET_CLASS (dev)->enslave_slave (dev, slave, connection, info->configure);
|
||||
if (info->enslaved)
|
||||
success = TRUE;
|
||||
else {
|
||||
configure = (info->configure && connection != NULL);
|
||||
if (configure)
|
||||
g_return_val_if_fail (nm_device_get_state (slave) >= NM_DEVICE_STATE_DISCONNECTED, FALSE);
|
||||
|
||||
success = NM_DEVICE_GET_CLASS (dev)->enslave_slave (dev, slave, connection, configure);
|
||||
info->enslaved = success;
|
||||
}
|
||||
|
||||
info->enslaved = success;
|
||||
nm_device_slave_notify_enslave (info->slave, success);
|
||||
|
||||
/* Ensure the device's hardware address is up-to-date; it often changes
|
||||
|
|
@ -936,15 +956,17 @@ nm_device_enslave_slave (NMDevice *dev, NMDevice *slave, NMConnection *connectio
|
|||
* nm_device_release_one_slave:
|
||||
* @dev: the master device
|
||||
* @slave: the slave device to release
|
||||
* @configure: whether @dev needs to actually release @slave
|
||||
*
|
||||
* If @dev is capable of enslaving other devices (ie it's a bridge, bond, team,
|
||||
* etc) then this function releases the previously enslaved @slave.
|
||||
* etc) then this function releases the previously enslaved @slave and/or
|
||||
* updates the state of @dev and @slave to reflect its release.
|
||||
*
|
||||
* Returns: %TRUE on success, %FALSE on failure, if this device cannot enslave
|
||||
* other devices, or if @slave was never enslaved.
|
||||
*/
|
||||
static gboolean
|
||||
nm_device_release_one_slave (NMDevice *dev, NMDevice *slave)
|
||||
nm_device_release_one_slave (NMDevice *dev, NMDevice *slave, gboolean configure)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (dev);
|
||||
SlaveInfo *info;
|
||||
|
|
@ -960,13 +982,15 @@ nm_device_release_one_slave (NMDevice *dev, NMDevice *slave)
|
|||
priv->slaves = g_slist_remove (priv->slaves, info);
|
||||
|
||||
if (info->enslaved) {
|
||||
success = NM_DEVICE_GET_CLASS (dev)->release_slave (dev, slave);
|
||||
success = NM_DEVICE_GET_CLASS (dev)->release_slave (dev, slave, configure);
|
||||
/* The release_slave() implementation logs success/failure (in the
|
||||
* correct device-specific log domain), so we don't have to do anything.
|
||||
*/
|
||||
}
|
||||
|
||||
if (priv->state == NM_DEVICE_STATE_FAILED)
|
||||
if (!configure)
|
||||
reason = NM_DEVICE_STATE_REASON_NONE;
|
||||
else if (priv->state == NM_DEVICE_STATE_FAILED)
|
||||
reason = NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED;
|
||||
else
|
||||
reason = priv->state_reason;
|
||||
|
|
@ -1195,6 +1219,29 @@ device_link_changed (NMDevice *device, NMPlatformLink *info)
|
|||
nm_device_emit_recheck_auto_activate (device);
|
||||
}
|
||||
|
||||
/* Update slave status for external changes */
|
||||
if (info->master && !priv->enslaved) {
|
||||
NMDevice *master;
|
||||
|
||||
master = nm_manager_get_device_by_ifindex (nm_manager_get (), info->master);
|
||||
if (master && NM_DEVICE_GET_CLASS (master)->enslave_slave) {
|
||||
g_clear_object (&priv->master);
|
||||
priv->master = g_object_ref (master);
|
||||
nm_device_master_add_slave (master, device, FALSE);
|
||||
nm_device_enslave_slave (master, device, NULL);
|
||||
} else if (master) {
|
||||
nm_log_info (LOGD_DEVICE, "(%s): enslaved to non-master-type device %s; ignoring",
|
||||
nm_device_get_iface (device),
|
||||
nm_device_get_iface (master));
|
||||
} else {
|
||||
nm_log_warn (LOGD_DEVICE, "(%s): enslaved to unknown device %d %s",
|
||||
nm_device_get_iface (device),
|
||||
info->master,
|
||||
nm_platform_link_get_name (info->master));
|
||||
}
|
||||
} else if (priv->enslaved && !info->master)
|
||||
nm_device_release_one_slave (priv->master, device, FALSE);
|
||||
|
||||
if (klass->link_changed)
|
||||
klass->link_changed (device, info);
|
||||
|
||||
|
|
@ -1317,8 +1364,6 @@ slave_state_changed (NMDevice *slave,
|
|||
slave_new_state,
|
||||
state_to_string (slave_new_state));
|
||||
|
||||
g_assert (priv->state > NM_DEVICE_STATE_DISCONNECTED);
|
||||
|
||||
/* Don't try to enslave slaves until the master is ready */
|
||||
if (priv->state < NM_DEVICE_STATE_CONFIG)
|
||||
return;
|
||||
|
|
@ -1334,7 +1379,7 @@ slave_state_changed (NMDevice *slave,
|
|||
}
|
||||
|
||||
if (release) {
|
||||
nm_device_release_one_slave (self, slave);
|
||||
nm_device_release_one_slave (self, slave, TRUE);
|
||||
/* Bridge/bond/team interfaces are left up until manually deactivated */
|
||||
if (priv->slaves == NULL && priv->state == NM_DEVICE_STATE_ACTIVATED) {
|
||||
nm_log_dbg (LOGD_DEVICE, "(%s): last slave removed; remaining activated",
|
||||
|
|
@ -1363,9 +1408,11 @@ nm_device_master_add_slave (NMDevice *dev, NMDevice *slave, gboolean configure)
|
|||
|
||||
g_return_val_if_fail (dev != NULL, FALSE);
|
||||
g_return_val_if_fail (slave != NULL, FALSE);
|
||||
g_return_val_if_fail (nm_device_get_state (slave) >= NM_DEVICE_STATE_DISCONNECTED, FALSE);
|
||||
g_return_val_if_fail (NM_DEVICE_GET_CLASS (dev)->enslave_slave != NULL, FALSE);
|
||||
|
||||
if (configure)
|
||||
g_return_val_if_fail (nm_device_get_state (slave) >= NM_DEVICE_STATE_DISCONNECTED, FALSE);
|
||||
|
||||
if (!find_slave_info (dev, slave)) {
|
||||
info = g_malloc0 (sizeof (SlaveInfo));
|
||||
info->slave = g_object_ref (slave);
|
||||
|
|
@ -1480,10 +1527,14 @@ nm_device_master_release_slaves (NMDevice *self)
|
|||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
/* Don't release the slaves if this connection doesn't belong to NM. */
|
||||
if (nm_device_uses_generated_connection (self))
|
||||
return;
|
||||
|
||||
while (priv->slaves) {
|
||||
SlaveInfo *info = priv->slaves->data;
|
||||
|
||||
nm_device_release_one_slave (self, info->slave);
|
||||
nm_device_release_one_slave (self, info->slave, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1522,31 +1573,42 @@ nm_device_slave_notify_enslave (NMDevice *dev, gboolean success)
|
|||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (dev);
|
||||
NMConnection *connection = nm_device_get_connection (dev);
|
||||
gboolean activating = (priv->state == NM_DEVICE_STATE_IP_CONFIG);
|
||||
|
||||
g_assert (priv->master);
|
||||
g_warn_if_fail (priv->enslaved == FALSE);
|
||||
g_warn_if_fail (priv->state == NM_DEVICE_STATE_IP_CONFIG);
|
||||
|
||||
if (success) {
|
||||
nm_log_info (LOGD_DEVICE,
|
||||
"Activation (%s) connection '%s' enslaved, continuing activation",
|
||||
nm_device_get_iface (dev),
|
||||
nm_connection_get_id (connection));
|
||||
if (!priv->enslaved) {
|
||||
if (success) {
|
||||
if (activating) {
|
||||
nm_log_info (LOGD_DEVICE,
|
||||
"Activation (%s) connection '%s' enslaved, continuing activation",
|
||||
nm_device_get_iface (dev),
|
||||
nm_connection_get_id (connection));
|
||||
} else {
|
||||
nm_log_info (LOGD_DEVICE,
|
||||
"(%s): enslaved to %s",
|
||||
nm_device_get_iface (dev),
|
||||
nm_device_get_iface (priv->master));
|
||||
}
|
||||
|
||||
priv->enslaved = TRUE;
|
||||
g_object_notify (G_OBJECT (dev), NM_DEVICE_MASTER);
|
||||
} else {
|
||||
nm_log_warn (LOGD_DEVICE,
|
||||
"Activation (%s) connection '%s' could not be enslaved",
|
||||
nm_device_get_iface (dev),
|
||||
nm_connection_get_id (connection));
|
||||
priv->enslaved = TRUE;
|
||||
g_object_notify (G_OBJECT (dev), NM_DEVICE_MASTER);
|
||||
} else if (activating) {
|
||||
nm_log_warn (LOGD_DEVICE,
|
||||
"Activation (%s) connection '%s' could not be enslaved",
|
||||
nm_device_get_iface (dev),
|
||||
nm_connection_get_id (connection));
|
||||
}
|
||||
}
|
||||
|
||||
priv->ip4_state = IP_DONE;
|
||||
priv->ip6_state = IP_DONE;
|
||||
nm_device_queue_state (dev,
|
||||
success ? NM_DEVICE_STATE_SECONDARIES : NM_DEVICE_STATE_FAILED,
|
||||
NM_DEVICE_STATE_REASON_NONE);
|
||||
if (activating) {
|
||||
priv->ip4_state = IP_DONE;
|
||||
priv->ip6_state = IP_DONE;
|
||||
nm_device_queue_state (dev,
|
||||
success ? NM_DEVICE_STATE_SECONDARIES : NM_DEVICE_STATE_FAILED,
|
||||
NM_DEVICE_STATE_REASON_NONE);
|
||||
} else
|
||||
nm_device_queue_recheck_assume (dev);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1564,7 +1626,8 @@ nm_device_slave_notify_release (NMDevice *dev, NMDeviceStateReason reason)
|
|||
NMDeviceState new_state;
|
||||
const char *master_status;
|
||||
|
||||
if ( priv->state > NM_DEVICE_STATE_DISCONNECTED
|
||||
if ( reason != NM_DEVICE_STATE_REASON_NONE
|
||||
&& priv->state > NM_DEVICE_STATE_DISCONNECTED
|
||||
&& priv->state <= NM_DEVICE_STATE_ACTIVATED) {
|
||||
if (reason == NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED) {
|
||||
new_state = NM_DEVICE_STATE_FAILED;
|
||||
|
|
@ -1584,6 +1647,11 @@ nm_device_slave_notify_release (NMDevice *dev, NMDeviceStateReason reason)
|
|||
master_status);
|
||||
|
||||
nm_device_queue_state (dev, new_state, reason);
|
||||
} else {
|
||||
nm_log_info (LOGD_DEVICE,
|
||||
"(%s): released from master %s",
|
||||
nm_device_get_iface (dev),
|
||||
nm_device_get_iface (priv->master));
|
||||
}
|
||||
|
||||
if (priv->enslaved) {
|
||||
|
|
@ -1786,6 +1854,19 @@ nm_device_generate_connection (NMDevice *device)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (ifindex)
|
||||
master_ifindex = nm_platform_link_get_master (ifindex);
|
||||
if (master_ifindex) {
|
||||
NMDevice *master;
|
||||
|
||||
master = nm_manager_get_device_by_ifindex (nm_manager_get (), master_ifindex);
|
||||
if (!master || !nm_device_get_act_request (master)) {
|
||||
nm_log_dbg (LOGD_DEVICE, "(%s): cannot generate connection for slave before its master (%s)",
|
||||
ifname, nm_platform_link_get_name (master_ifindex));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
connection = nm_connection_new ();
|
||||
s_con = nm_setting_connection_new ();
|
||||
uuid = nm_utils_uuid_generate ();
|
||||
|
|
@ -1803,9 +1884,7 @@ nm_device_generate_connection (NMDevice *device)
|
|||
nm_connection_add_setting (connection, s_con);
|
||||
|
||||
/* If the device is a slave, update various slave settings */
|
||||
if (ifindex)
|
||||
master_ifindex = nm_platform_link_get_master (ifindex);
|
||||
if (master_ifindex > 0) {
|
||||
if (master_ifindex) {
|
||||
const char *master_iface = nm_platform_link_get_name (master_ifindex);
|
||||
const char *slave_type = NULL;
|
||||
gboolean success = FALSE;
|
||||
|
|
@ -1837,19 +1916,11 @@ nm_device_generate_connection (NMDevice *device)
|
|||
NULL);
|
||||
} else {
|
||||
/* Only regular and master devices get IP configuration; slaves do not */
|
||||
s_ip4 = nm_setting_ip4_config_new ();
|
||||
s_ip4 = nm_ip4_config_create_setting (priv->ip4_config);
|
||||
nm_connection_add_setting (connection, s_ip4);
|
||||
if (priv->ip4_config)
|
||||
nm_ip4_config_update_setting (priv->ip4_config, (NMSettingIP4Config *) s_ip4);
|
||||
else
|
||||
g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_DISABLED, NULL);
|
||||
|
||||
s_ip6 = nm_setting_ip6_config_new ();
|
||||
s_ip6 = nm_ip6_config_create_setting (priv->ip6_config);
|
||||
nm_connection_add_setting (connection, s_ip6);
|
||||
if (priv->ip6_config)
|
||||
nm_ip6_config_update_setting (priv->ip6_config, (NMSettingIP6Config *) s_ip6);
|
||||
else
|
||||
g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
|
||||
}
|
||||
|
||||
klass->update_connection (device, connection);
|
||||
|
|
@ -1870,9 +1941,8 @@ nm_device_generate_connection (NMDevice *device)
|
|||
ip6_method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG);
|
||||
if ( g_strcmp0 (ip4_method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0
|
||||
&& g_strcmp0 (ip6_method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) == 0
|
||||
&& !nm_setting_connection_get_master (NM_SETTING_CONNECTION (s_con))
|
||||
&& !nm_platform_link_supports_slaves (priv->ifindex)) {
|
||||
nm_log_dbg (LOGD_DEVICE, "(%s): ignoring generated connection (no IP, not master, no slaves)", ifname);
|
||||
&& !nm_setting_connection_get_master (NM_SETTING_CONNECTION (s_con))) {
|
||||
nm_log_dbg (LOGD_DEVICE, "(%s): ignoring generated connection (no IP and not slave)", ifname);
|
||||
g_object_unref (connection);
|
||||
connection = NULL;
|
||||
}
|
||||
|
|
@ -2013,6 +2083,26 @@ nm_device_can_assume_connections (NMDevice *device)
|
|||
return !!NM_DEVICE_GET_CLASS (device)->update_connection;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
nm_device_emit_recheck_assume (gpointer self)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
priv->recheck_assume_id = 0;
|
||||
if (!nm_device_get_act_request (self) && (priv->ip4_config || priv->ip6_config))
|
||||
g_signal_emit (self, signals[RECHECK_ASSUME], 0);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
void
|
||||
nm_device_queue_recheck_assume (NMDevice *self)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
if (nm_device_can_assume_connections (self) && !priv->recheck_assume_id)
|
||||
priv->recheck_assume_id = g_idle_add (nm_device_emit_recheck_assume, self);
|
||||
}
|
||||
|
||||
void
|
||||
nm_device_emit_recheck_auto_activate (NMDevice *self)
|
||||
{
|
||||
|
|
@ -2293,9 +2383,13 @@ nm_device_activate_stage2_device_config (gpointer user_data)
|
|||
/* If we have slaves that aren't yet enslaved, do that now */
|
||||
for (iter = priv->slaves; iter; iter = g_slist_next (iter)) {
|
||||
SlaveInfo *info = iter->data;
|
||||
NMDeviceState slave_state = nm_device_get_state (info->slave);
|
||||
|
||||
if (nm_device_get_state (info->slave) == NM_DEVICE_STATE_IP_CONFIG)
|
||||
if (slave_state == NM_DEVICE_STATE_IP_CONFIG)
|
||||
nm_device_enslave_slave (self, info->slave, nm_device_get_connection (info->slave));
|
||||
else if ( nm_device_uses_generated_connection (self)
|
||||
&& slave_state <= NM_DEVICE_STATE_DISCONNECTED)
|
||||
nm_device_queue_recheck_assume (info->slave);
|
||||
}
|
||||
|
||||
nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 2 of 5 (Device Configure) successful.", iface);
|
||||
|
|
@ -5229,6 +5323,19 @@ nm_device_set_ip4_config (NMDevice *self,
|
|||
|
||||
if (old_config != priv->ip4_config && old_config)
|
||||
g_object_unref (old_config);
|
||||
|
||||
if (nm_device_uses_generated_connection (self)) {
|
||||
NMConnection *connection = nm_device_get_connection (self);
|
||||
NMSetting *s_ip4;
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (connection));
|
||||
nm_connection_remove_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
|
||||
s_ip4 = nm_ip4_config_create_setting (priv->ip4_config);
|
||||
nm_connection_add_setting (connection, s_ip4);
|
||||
g_object_thaw_notify (G_OBJECT (connection));
|
||||
}
|
||||
|
||||
nm_device_queue_recheck_assume (self);
|
||||
}
|
||||
|
||||
if (reason)
|
||||
|
|
@ -5320,6 +5427,19 @@ nm_device_set_ip6_config (NMDevice *self,
|
|||
|
||||
if (old_config != priv->ip6_config && old_config)
|
||||
g_object_unref (old_config);
|
||||
|
||||
if (nm_device_uses_generated_connection (self)) {
|
||||
NMConnection *connection = nm_device_get_connection (self);
|
||||
NMSetting *s_ip6;
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (connection));
|
||||
nm_connection_remove_setting (connection, NM_TYPE_SETTING_IP6_CONFIG);
|
||||
s_ip6 = nm_ip6_config_create_setting (priv->ip6_config);
|
||||
nm_connection_add_setting (connection, s_ip6);
|
||||
g_object_thaw_notify (G_OBJECT (connection));
|
||||
}
|
||||
|
||||
nm_device_queue_recheck_assume (self);
|
||||
}
|
||||
|
||||
if (reason)
|
||||
|
|
@ -5764,6 +5884,11 @@ dispose (GObject *object)
|
|||
|
||||
g_clear_pointer (&priv->ip6_saved_properties, g_hash_table_unref);
|
||||
|
||||
if (priv->recheck_assume_id) {
|
||||
g_source_remove (priv->recheck_assume_id);
|
||||
priv->recheck_assume_id = 0;
|
||||
}
|
||||
|
||||
link_disconnect_action_cancel (self);
|
||||
|
||||
if (priv->con_provider) {
|
||||
|
|
@ -6412,6 +6537,13 @@ nm_device_class_init (NMDeviceClass *klass)
|
|||
0, NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
signals[RECHECK_ASSUME] =
|
||||
g_signal_new (NM_DEVICE_RECHECK_ASSUME,
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
0, NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
nm_dbus_manager_register_exported_type (nm_dbus_manager_get (),
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
&dbus_glib_nm_device_object_info);
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@
|
|||
#define NM_DEVICE_IP6_CONFIG_CHANGED "ip6-config-changed"
|
||||
#define NM_DEVICE_REMOVED "removed"
|
||||
#define NM_DEVICE_RECHECK_AUTO_ACTIVATE "recheck-auto-activate"
|
||||
#define NM_DEVICE_RECHECK_ASSUME "recheck-assume"
|
||||
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
|
@ -197,7 +198,8 @@ typedef struct {
|
|||
gboolean configure);
|
||||
|
||||
gboolean (* release_slave) (NMDevice *self,
|
||||
NMDevice *slave);
|
||||
NMDevice *slave,
|
||||
gboolean configure);
|
||||
|
||||
gboolean (* have_any_ready_slaves) (NMDevice *self,
|
||||
const GSList *slaves);
|
||||
|
|
|
|||
|
|
@ -379,16 +379,23 @@ nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIP4Config *setting)
|
|||
g_object_thaw_notify (G_OBJECT (config));
|
||||
}
|
||||
|
||||
void
|
||||
nm_ip4_config_update_setting (const NMIP4Config *config, NMSettingIP4Config *setting)
|
||||
NMSetting *
|
||||
nm_ip4_config_create_setting (const NMIP4Config *config)
|
||||
{
|
||||
NMSettingIP4Config *s_ip4;
|
||||
guint32 gateway;
|
||||
guint naddresses, nroutes, nnameservers, nsearches;
|
||||
const char *method = NULL;
|
||||
int i;
|
||||
|
||||
if (!config)
|
||||
return;
|
||||
s_ip4 = NM_SETTING_IP4_CONFIG (nm_setting_ip4_config_new ());
|
||||
|
||||
if (!config) {
|
||||
g_object_set (s_ip4,
|
||||
NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
|
||||
NULL);
|
||||
return NM_SETTING (s_ip4);
|
||||
}
|
||||
|
||||
gateway = nm_ip4_config_get_gateway (config);
|
||||
naddresses = nm_ip4_config_get_num_addresses (config);
|
||||
|
|
@ -422,17 +429,16 @@ nm_ip4_config_update_setting (const NMIP4Config *config, NMSettingIP4Config *set
|
|||
nm_ip4_address_set_gateway (s_addr, gateway);
|
||||
|
||||
if (*address->label)
|
||||
NM_UTIL_PRIVATE_CALL (nm_setting_ip4_config_add_address_with_label (setting, s_addr, address->label));
|
||||
NM_UTIL_PRIVATE_CALL (nm_setting_ip4_config_add_address_with_label (s_ip4, s_addr, address->label));
|
||||
else
|
||||
nm_setting_ip4_config_add_address (setting, s_addr);
|
||||
nm_setting_ip4_config_add_address (s_ip4, s_addr);
|
||||
nm_ip4_address_unref (s_addr);
|
||||
}
|
||||
|
||||
/* Only use 'disabled' if the method wasn't previously set */
|
||||
if (!method && !nm_setting_ip4_config_get_method (setting))
|
||||
/* Use 'disabled' if the method wasn't previously set */
|
||||
if (!method)
|
||||
method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
|
||||
if (method)
|
||||
g_object_set (setting, NM_SETTING_IP4_CONFIG_METHOD, method, NULL);
|
||||
g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, method, NULL);
|
||||
|
||||
/* Routes */
|
||||
for (i = 0; i < nroutes; i++) {
|
||||
|
|
@ -449,7 +455,7 @@ nm_ip4_config_update_setting (const NMIP4Config *config, NMSettingIP4Config *set
|
|||
nm_ip4_route_set_next_hop (s_route, route->gateway);
|
||||
nm_ip4_route_set_metric (s_route, route->metric);
|
||||
|
||||
nm_setting_ip4_config_add_route (setting, s_route);
|
||||
nm_setting_ip4_config_add_route (s_ip4, s_route);
|
||||
nm_ip4_route_unref (s_route);
|
||||
}
|
||||
|
||||
|
|
@ -457,13 +463,15 @@ nm_ip4_config_update_setting (const NMIP4Config *config, NMSettingIP4Config *set
|
|||
for (i = 0; i < nnameservers; i++) {
|
||||
guint32 nameserver = nm_ip4_config_get_nameserver (config, i);
|
||||
|
||||
nm_setting_ip4_config_add_dns (setting, nameserver);
|
||||
nm_setting_ip4_config_add_dns (s_ip4, nameserver);
|
||||
}
|
||||
for (i = 0; i < nsearches; i++) {
|
||||
const char *search = nm_ip4_config_get_search (config, i);
|
||||
|
||||
nm_setting_ip4_config_add_dns_search (setting, search);
|
||||
nm_setting_ip4_config_add_dns_search (s_ip4, search);
|
||||
}
|
||||
|
||||
return NM_SETTING (s_ip4);
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ const char * nm_ip4_config_get_dbus_path (const NMIP4Config *config);
|
|||
NMIP4Config *nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf);
|
||||
gboolean nm_ip4_config_commit (const NMIP4Config *config, int ifindex, int priority);
|
||||
void nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIP4Config *setting);
|
||||
void nm_ip4_config_update_setting (const NMIP4Config *config, NMSettingIP4Config *setting);
|
||||
NMSetting *nm_ip4_config_create_setting (const NMIP4Config *config);
|
||||
|
||||
/* Utility functions */
|
||||
void nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src);
|
||||
|
|
|
|||
|
|
@ -481,16 +481,23 @@ nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIP6Config *setting)
|
|||
g_object_thaw_notify (G_OBJECT (config));
|
||||
}
|
||||
|
||||
void
|
||||
nm_ip6_config_update_setting (const NMIP6Config *config, NMSettingIP6Config *setting)
|
||||
NMSetting *
|
||||
nm_ip6_config_create_setting (const NMIP6Config *config)
|
||||
{
|
||||
NMSettingIP6Config *s_ip6;
|
||||
const struct in6_addr *gateway;
|
||||
guint naddresses, nroutes, nnameservers, nsearches;
|
||||
const char *method = NULL;
|
||||
int i;
|
||||
|
||||
if (!config)
|
||||
return;
|
||||
s_ip6 = NM_SETTING_IP6_CONFIG (nm_setting_ip6_config_new ());
|
||||
|
||||
if (!config) {
|
||||
g_object_set (s_ip6,
|
||||
NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
|
||||
NULL);
|
||||
return NM_SETTING (s_ip6);
|
||||
}
|
||||
|
||||
gateway = nm_ip6_config_get_gateway (config);
|
||||
naddresses = nm_ip6_config_get_num_addresses (config);
|
||||
|
|
@ -527,15 +534,14 @@ nm_ip6_config_update_setting (const NMIP6Config *config, NMSettingIP6Config *set
|
|||
if (gateway)
|
||||
nm_ip6_address_set_gateway (s_addr, gateway);
|
||||
|
||||
nm_setting_ip6_config_add_address (setting, s_addr);
|
||||
nm_setting_ip6_config_add_address (s_ip6, s_addr);
|
||||
nm_ip6_address_unref (s_addr);
|
||||
}
|
||||
|
||||
/* Only use 'ignore' if the method wasn't previously set */
|
||||
if (!method && !nm_setting_ip6_config_get_method (setting))
|
||||
/* Use 'ignore' if the method wasn't previously set */
|
||||
if (!method)
|
||||
method = NM_SETTING_IP6_CONFIG_METHOD_IGNORE;
|
||||
if (method)
|
||||
g_object_set (setting, NM_SETTING_IP6_CONFIG_METHOD, method, NULL);
|
||||
g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_METHOD, method, NULL);
|
||||
|
||||
/* Routes */
|
||||
for (i = 0; i < nroutes; i++) {
|
||||
|
|
@ -557,7 +563,7 @@ nm_ip6_config_update_setting (const NMIP6Config *config, NMSettingIP6Config *set
|
|||
nm_ip6_route_set_next_hop (s_route, &route->gateway);
|
||||
nm_ip6_route_set_metric (s_route, route->metric);
|
||||
|
||||
nm_setting_ip6_config_add_route (setting, s_route);
|
||||
nm_setting_ip6_config_add_route (s_ip6, s_route);
|
||||
nm_ip6_route_unref (s_route);
|
||||
}
|
||||
|
||||
|
|
@ -565,13 +571,15 @@ nm_ip6_config_update_setting (const NMIP6Config *config, NMSettingIP6Config *set
|
|||
for (i = 0; i < nnameservers; i++) {
|
||||
const struct in6_addr *nameserver = nm_ip6_config_get_nameserver (config, i);
|
||||
|
||||
nm_setting_ip6_config_add_dns (setting, nameserver);
|
||||
nm_setting_ip6_config_add_dns (s_ip6, nameserver);
|
||||
}
|
||||
for (i = 0; i < nsearches; i++) {
|
||||
const char *search = nm_ip6_config_get_search (config, i);
|
||||
|
||||
nm_setting_ip6_config_add_dns_search (setting, search);
|
||||
nm_setting_ip6_config_add_dns_search (s_ip6, search);
|
||||
}
|
||||
|
||||
return NM_SETTING (s_ip6);
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ const char * nm_ip6_config_get_dbus_path (const NMIP6Config *config);
|
|||
NMIP6Config *nm_ip6_config_capture (int ifindex, gboolean capture_resolv_conf, NMSettingIP6ConfigPrivacy use_temporary);
|
||||
gboolean nm_ip6_config_commit (const NMIP6Config *config, int ifindex, int priority);
|
||||
void nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIP6Config *setting);
|
||||
void nm_ip6_config_update_setting (const NMIP6Config *config, NMSettingIP6Config *setting);
|
||||
NMSetting *nm_ip6_config_create_setting (const NMIP6Config *config);
|
||||
|
||||
/* Utility functions */
|
||||
void nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src);
|
||||
|
|
|
|||
131
src/nm-manager.c
131
src/nm-manager.c
|
|
@ -1572,7 +1572,9 @@ get_existing_connection (NMManager *manager, NMDevice *device)
|
|||
nm_connection_get_id (connection));
|
||||
|
||||
added = nm_settings_add_connection (priv->settings, connection, FALSE, &error);
|
||||
if (!added) {
|
||||
if (added)
|
||||
nm_settings_connection_set_nm_generated (added);
|
||||
else {
|
||||
nm_log_warn (LOGD_SETTINGS, "(%s) Couldn't save generated connection '%s': %s",
|
||||
nm_device_get_iface (device),
|
||||
nm_connection_get_id (connection),
|
||||
|
|
@ -1584,6 +1586,89 @@ get_existing_connection (NMManager *manager, NMDevice *device)
|
|||
return added ? NM_CONNECTION (added) : NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
assume_connection (NMManager *self, NMDevice *device, NMConnection *connection)
|
||||
{
|
||||
NMActiveConnection *active, *master_ac;
|
||||
NMAuthSubject *subject;
|
||||
GError *error = NULL;
|
||||
|
||||
nm_log_dbg (LOGD_DEVICE, "(%s): will attempt to assume connection",
|
||||
nm_device_get_iface (device));
|
||||
|
||||
/* Move device to DISCONNECTED to activate the connection */
|
||||
if (nm_device_get_state (device) == NM_DEVICE_STATE_UNAVAILABLE) {
|
||||
nm_device_state_changed (device,
|
||||
NM_DEVICE_STATE_DISCONNECTED,
|
||||
NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED);
|
||||
}
|
||||
g_return_if_fail (nm_device_get_state (device) >= NM_DEVICE_STATE_DISCONNECTED);
|
||||
|
||||
subject = nm_auth_subject_new_internal ();
|
||||
active = _new_active_connection (self, connection, NULL, device, subject, &error);
|
||||
g_object_unref (subject);
|
||||
|
||||
if (!active) {
|
||||
nm_log_warn (LOGD_DEVICE, "assumed connection %s failed to activate: (%d) %s",
|
||||
nm_connection_get_path (connection),
|
||||
error ? error->code : -1,
|
||||
error && error->message ? error->message : "(unknown)");
|
||||
g_error_free (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* If the device is a slave or VLAN, find the master ActiveConnection */
|
||||
master_ac = NULL;
|
||||
if (find_master (self, connection, device, NULL, NULL, &master_ac, NULL) && master_ac)
|
||||
nm_active_connection_set_master (active, master_ac);
|
||||
|
||||
nm_active_connection_set_assumed (active, TRUE);
|
||||
nm_active_connection_export (active);
|
||||
active_connection_add (self, active);
|
||||
nm_device_queue_activation (device, NM_ACT_REQUEST (active));
|
||||
g_object_unref (active);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
recheck_assume_connection (NMDevice *device, gpointer user_data)
|
||||
{
|
||||
NMManager *self = user_data;
|
||||
NMConnection *connection;
|
||||
gboolean was_unmanaged = FALSE;
|
||||
|
||||
if (manager_sleeping (self))
|
||||
return;
|
||||
if (nm_device_get_unmanaged_flag (device, NM_UNMANAGED_USER))
|
||||
return;
|
||||
|
||||
connection = get_existing_connection (self, device);
|
||||
if (!connection) {
|
||||
nm_log_dbg (LOGD_DEVICE, "(%s): can't assume; no connection",
|
||||
nm_device_get_iface (device));
|
||||
return;
|
||||
}
|
||||
|
||||
if (nm_device_get_state (device) == NM_DEVICE_STATE_UNMANAGED) {
|
||||
was_unmanaged = TRUE;
|
||||
nm_device_state_changed (device,
|
||||
NM_DEVICE_STATE_UNAVAILABLE,
|
||||
NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED);
|
||||
}
|
||||
|
||||
if (!assume_connection (self, device, connection)) {
|
||||
if (was_unmanaged) {
|
||||
nm_device_state_changed (device,
|
||||
NM_DEVICE_STATE_UNAVAILABLE,
|
||||
NM_DEVICE_STATE_REASON_CONFIG_FAILED);
|
||||
nm_device_state_changed (device,
|
||||
NM_DEVICE_STATE_UNMANAGED,
|
||||
NM_DEVICE_STATE_REASON_CONFIG_FAILED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* add_device:
|
||||
* @self: the #NMManager
|
||||
|
|
@ -1706,42 +1791,14 @@ add_device (NMManager *self, NMDevice *device, gboolean generate_con)
|
|||
*/
|
||||
system_create_virtual_devices (self);
|
||||
|
||||
/* If the device has a connection it can assume, do that now */
|
||||
if (connection) {
|
||||
NMActiveConnection *active;
|
||||
NMAuthSubject *subject;
|
||||
GError *error = NULL;
|
||||
|
||||
nm_log_dbg (LOGD_DEVICE, "(%s): will attempt to assume connection",
|
||||
nm_device_get_iface (device));
|
||||
|
||||
/* Move device to DISCONNECTED to activate the connection */
|
||||
nm_device_state_changed (device,
|
||||
NM_DEVICE_STATE_DISCONNECTED,
|
||||
NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED);
|
||||
|
||||
subject = nm_auth_subject_new_internal ();
|
||||
active = _new_active_connection (self, connection, NULL, device, subject, &error);
|
||||
if (active) {
|
||||
NMActiveConnection *master_ac = NULL;
|
||||
|
||||
/* If the device is a slave or VLAN, find the master ActiveConnection */
|
||||
if (find_master (self, connection, device, NULL, NULL, &master_ac, NULL) && master_ac)
|
||||
nm_active_connection_set_master (active, master_ac);
|
||||
|
||||
nm_active_connection_set_assumed (active, TRUE);
|
||||
nm_active_connection_export (active);
|
||||
active_connection_add (self, active);
|
||||
nm_device_queue_activation (device, NM_ACT_REQUEST (active));
|
||||
g_object_unref (active);
|
||||
} else {
|
||||
nm_log_warn (LOGD_DEVICE, "assumed connection %s failed to activate: (%d) %s",
|
||||
nm_connection_get_path (connection),
|
||||
error ? error->code : -1,
|
||||
error && error->message ? error->message : "(unknown)");
|
||||
g_error_free (error);
|
||||
}
|
||||
g_object_unref (subject);
|
||||
/* If the device has a connection it can assume, do that now. If it's a
|
||||
* device that we might ever want to assume a connection on, then set that up.
|
||||
*/
|
||||
if (connection)
|
||||
assume_connection (self, device, connection);
|
||||
if (generate_con) {
|
||||
g_signal_connect (device, NM_DEVICE_RECHECK_ASSUME,
|
||||
G_CALLBACK (recheck_assume_connection), self);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -100,6 +100,11 @@ typedef struct {
|
|||
*/
|
||||
gboolean unsaved;
|
||||
|
||||
/* TRUE if the connection was generated by NetworkManager and has
|
||||
* not been saved or modified by the user.
|
||||
*/
|
||||
gboolean nm_generated;
|
||||
|
||||
guint updated_idle_id;
|
||||
|
||||
GSList *pending_auths; /* List of pending authentication requests */
|
||||
|
|
@ -402,6 +407,9 @@ set_unsaved (NMSettingsConnection *self, gboolean now_unsaved)
|
|||
|
||||
if (priv->unsaved != now_unsaved) {
|
||||
priv->unsaved = now_unsaved;
|
||||
if (!priv->unsaved)
|
||||
priv->nm_generated = FALSE;
|
||||
|
||||
g_object_notify (G_OBJECT (self), NM_SETTINGS_CONNECTION_UNSAVED);
|
||||
}
|
||||
}
|
||||
|
|
@ -456,6 +464,8 @@ nm_settings_connection_replace_settings (NMSettingsConnection *self,
|
|||
if (nm_connection_replace_settings_from_connection (NM_CONNECTION (self),
|
||||
new_connection,
|
||||
error)) {
|
||||
priv->nm_generated = FALSE;
|
||||
|
||||
/* Cache the just-updated system secrets in case something calls
|
||||
* nm_connection_clear_secrets() and clears them.
|
||||
*/
|
||||
|
|
@ -1976,6 +1986,39 @@ nm_settings_connection_can_autoconnect (NMSettingsConnection *connection)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_settings_connection_get_nm_generated:
|
||||
* @connection: an #NMSettingsConnection
|
||||
*
|
||||
* Gets the "nm-generated" flag on @connection.
|
||||
*
|
||||
* A connection is "nm-generated" if it was generated by
|
||||
* nm_device_generate_connection() and then assumed by #NMManager, and
|
||||
* it has not been modified or saved by the user since then. In other
|
||||
* words, an "nm-generated" connection reflects state that is entirely
|
||||
* external to NetworkManager.
|
||||
*/
|
||||
gboolean
|
||||
nm_settings_connection_get_nm_generated (NMSettingsConnection *connection)
|
||||
{
|
||||
return NM_SETTINGS_CONNECTION_GET_PRIVATE (connection)->nm_generated;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_settings_connection_set_nm_generated:
|
||||
* @connection: an #NMSettingsConnection
|
||||
*
|
||||
* Sets the "nm-generated" flag on @connection; see
|
||||
* nm_settings_connection_get_nm_generated().
|
||||
*/
|
||||
void
|
||||
nm_settings_connection_set_nm_generated (NMSettingsConnection *connection)
|
||||
{
|
||||
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (connection);
|
||||
|
||||
priv->nm_generated = TRUE;
|
||||
}
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -162,6 +162,9 @@ void nm_settings_connection_set_autoconnect_blocked_reason (NMSettingsConnection
|
|||
|
||||
gboolean nm_settings_connection_can_autoconnect (NMSettingsConnection *connection);
|
||||
|
||||
void nm_settings_connection_set_nm_generated (NMSettingsConnection *connection);
|
||||
gboolean nm_settings_connection_get_nm_generated (NMSettingsConnection *connection);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* NM_SETTINGS_CONNECTION_H */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue