static void
device_state_changed (NMDevice *device,
                      NMDeviceState new_state,
                      NMDeviceState old_state,
                      NMDeviceStateReason reason,
                      gpointer user_data)
{
	NMActRequest *self = NM_ACT_REQUEST (user_data);
	NMActiveConnectionState new_ac_state;

	/* Set NMActiveConnection state based on the device's state */
	switch (new_state) {
	case NM_DEVICE_STATE_PREPARE:
	case NM_DEVICE_STATE_CONFIG:
	case NM_DEVICE_STATE_NEED_AUTH:
	case NM_DEVICE_STATE_IP_CONFIG:
	case NM_DEVICE_STATE_IP_CHECK:
	case NM_DEVICE_STATE_SECONDARIES:
		new_ac_state = NM_ACTIVE_CONNECTION_STATE_ACTIVATING;
		break;
	case NM_DEVICE_STATE_ACTIVATED:
		new_ac_state = NM_ACTIVE_CONNECTION_STATE_ACTIVATED;
		break;
	case NM_DEVICE_STATE_DEACTIVATING:
		new_ac_state = NM_ACTIVE_CONNECTION_STATE_DEACTIVATING;
		break;
	default:
		new_ac_state = NM_ACTIVE_CONNECTION_STATE_UNKNOWN;
		nm_active_connection_set_default (NM_ACTIVE_CONNECTION (self), FALSE);
		nm_active_connection_set_default6 (NM_ACTIVE_CONNECTION (self), FALSE);
		break;
	}

	nm_active_connection_set_state (NM_ACTIVE_CONNECTION (self), new_ac_state);
}
static void
device_state_changed (NMDevice *device, GParamSpec *pspec, NMActRequest *self)
{
	NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (self);
	NMActiveConnectionState ac_state = NM_ACTIVE_CONNECTION_STATE_UNKNOWN;

	/* Set NMActiveConnection state based on the device's state */
	switch (nm_device_get_state (device)) {
	case NM_DEVICE_STATE_PREPARE:
	case NM_DEVICE_STATE_CONFIG:
	case NM_DEVICE_STATE_NEED_AUTH:
	case NM_DEVICE_STATE_IP_CONFIG:
	case NM_DEVICE_STATE_IP_CHECK:
	case NM_DEVICE_STATE_SECONDARIES:
		ac_state = NM_ACTIVE_CONNECTION_STATE_ACTIVATING;
		break;
	case NM_DEVICE_STATE_ACTIVATED:
		ac_state = NM_ACTIVE_CONNECTION_STATE_ACTIVATED;
		break;
	case NM_DEVICE_STATE_DEACTIVATING:
		ac_state = NM_ACTIVE_CONNECTION_STATE_DEACTIVATING;
		break;
	case NM_DEVICE_STATE_FAILED:
	case NM_DEVICE_STATE_DISCONNECTED:
	case NM_DEVICE_STATE_UNMANAGED:
	case NM_DEVICE_STATE_UNAVAILABLE:
		ac_state = NM_ACTIVE_CONNECTION_STATE_DEACTIVATED;

		/* No longer need to pay attention to device state */
		if (priv->device && priv->device_state_id) {
			g_signal_handler_disconnect (priv->device, priv->device_state_id);
			priv->device_state_id = 0;
		}
		g_clear_object (&priv->device);
		break;
	default:
		break;
	}

	if (   ac_state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED
	    || ac_state == NM_ACTIVE_CONNECTION_STATE_UNKNOWN) {
		nm_active_connection_set_default (NM_ACTIVE_CONNECTION (self), FALSE);
		nm_active_connection_set_default6 (NM_ACTIVE_CONNECTION (self), FALSE);
	}

	nm_active_connection_set_state (NM_ACTIVE_CONNECTION (self), ac_state);
}
static void
device_state_changed (NMDevice *device, GParamSpec *pspec, NMActRequest *self)
{
	NMActiveConnectionState ac_state = NM_ACTIVE_CONNECTION_STATE_UNKNOWN;
	NMActiveConnectionState prev_ac_state = nm_active_connection_get_state (NM_ACTIVE_CONNECTION (self));

	/* Set NMActiveConnection state based on the device's state */
	switch (nm_device_get_state (device)) {
	case NM_DEVICE_STATE_PREPARE:
	case NM_DEVICE_STATE_CONFIG:
	case NM_DEVICE_STATE_NEED_AUTH:
	case NM_DEVICE_STATE_IP_CONFIG:
	case NM_DEVICE_STATE_IP_CHECK:
	case NM_DEVICE_STATE_SECONDARIES:
		ac_state = NM_ACTIVE_CONNECTION_STATE_ACTIVATING;
		break;
	case NM_DEVICE_STATE_ACTIVATED:
		ac_state = NM_ACTIVE_CONNECTION_STATE_ACTIVATED;
		break;
	case NM_DEVICE_STATE_DEACTIVATING:
		ac_state = NM_ACTIVE_CONNECTION_STATE_DEACTIVATING;
		break;
	case NM_DEVICE_STATE_FAILED:
	case NM_DEVICE_STATE_DISCONNECTED:
		ac_state = NM_ACTIVE_CONNECTION_STATE_DEACTIVATED;
		break;
	default:
		break;
	}

	if (   ac_state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED
	    || ac_state == NM_ACTIVE_CONNECTION_STATE_UNKNOWN) {
		nm_active_connection_set_default (NM_ACTIVE_CONNECTION (self), FALSE);
		nm_active_connection_set_default6 (NM_ACTIVE_CONNECTION (self), FALSE);
	}

	/* Only set new state if we are not in DEACTIVATED. Those connections
	 * will be removed. See _active_connection_cleanup() in nm-manager.c
	 */
	if (prev_ac_state != NM_ACTIVE_CONNECTION_STATE_DEACTIVATED)
		nm_active_connection_set_state (NM_ACTIVE_CONNECTION (self), ac_state);
}
static void
master_failed (NMActiveConnection *self)
{
	NMDevice *device;
	NMDeviceState device_state;

	/* If the connection has an active device, fail it */
	device = nm_active_connection_get_device (self);
	if (device) {
		device_state = nm_device_get_state (device);
		if (nm_device_is_activating (device) || (device_state == NM_DEVICE_STATE_ACTIVATED)) {
			nm_device_queue_state (device,
			                       NM_DEVICE_STATE_FAILED,
			                       NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED);
			return;
		}
	}

	/* If no device, or the device wasn't active, just move to deactivated state */
	nm_active_connection_set_state (self, NM_ACTIVE_CONNECTION_STATE_DEACTIVATED);
}
static void
device_state_changed (NMActiveConnection *active,
                      NMDevice *device,
                      NMDeviceState new_state,
                      NMDeviceState old_state)
{
	NMActiveConnectionState cur_ac_state = nm_active_connection_get_state (active);
	NMActiveConnectionState ac_state = NM_ACTIVE_CONNECTION_STATE_UNKNOWN;

	/* Decide which device state changes to handle when this active connection
	 * is not the device's current request.  Two cases here: (a) the AC is
	 * pending and not yet active, and (b) the AC was active but the device is
	 * entering DISCONNECTED state (which clears the device's current AC before
	 * emitting the state change signal).
	 */
	if (NM_ACTIVE_CONNECTION (nm_device_get_act_request (device)) != active) {
		/* Some other request is activating; this one must be pending */
		if (new_state >= NM_DEVICE_STATE_PREPARE)
			return;
		else if (new_state == NM_DEVICE_STATE_DISCONNECTED) {
			/* This request hasn't started activating yet; the device is
			 * disconnecting and cleaning up a previous activation request.
			 */
			if (cur_ac_state < NM_ACTIVE_CONNECTION_STATE_ACTIVATING)
				return;

			/* Catch device disconnections after this request has been active */
		}

		/* All states < DISCONNECTED are fatal and handled */
	}

	/* Set NMActiveConnection state based on the device's state */
	switch (new_state) {
	case NM_DEVICE_STATE_PREPARE:
	case NM_DEVICE_STATE_CONFIG:
	case NM_DEVICE_STATE_NEED_AUTH:
	case NM_DEVICE_STATE_IP_CONFIG:
	case NM_DEVICE_STATE_IP_CHECK:
	case NM_DEVICE_STATE_SECONDARIES:
		ac_state = NM_ACTIVE_CONNECTION_STATE_ACTIVATING;
		break;
	case NM_DEVICE_STATE_ACTIVATED:
		ac_state = NM_ACTIVE_CONNECTION_STATE_ACTIVATED;

		g_signal_connect (device, "notify::" NM_DEVICE_IP4_CONFIG,
		                  G_CALLBACK (device_notify), active);
		g_signal_connect (device, "notify::" NM_DEVICE_DHCP4_CONFIG,
		                  G_CALLBACK (device_notify), active);
		g_signal_connect (device, "notify::" NM_DEVICE_IP6_CONFIG,
		                  G_CALLBACK (device_notify), active);
		g_signal_connect (device, "notify::" NM_DEVICE_DHCP6_CONFIG,
		                  G_CALLBACK (device_notify), active);
		break;
	case NM_DEVICE_STATE_DEACTIVATING:
		ac_state = NM_ACTIVE_CONNECTION_STATE_DEACTIVATING;
		break;
	case NM_DEVICE_STATE_FAILED:
	case NM_DEVICE_STATE_DISCONNECTED:
	case NM_DEVICE_STATE_UNMANAGED:
	case NM_DEVICE_STATE_UNAVAILABLE:
		ac_state = NM_ACTIVE_CONNECTION_STATE_DEACTIVATED;

		g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_notify), active);
		break;
	default:
		break;
	}

	if (   ac_state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED
	    || ac_state == NM_ACTIVE_CONNECTION_STATE_UNKNOWN) {
		nm_active_connection_set_default (active, FALSE);
		nm_active_connection_set_default6 (active, FALSE);
	}

	nm_active_connection_set_state (active, ac_state);
}