diff options
author | Thomas Haller <thaller@redhat.com> | 2017-03-16 18:27:44 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2017-03-16 18:27:48 +0100 |
commit | 2d1b85f8d7f1e53b581e56f0f542b63e8a80da98 (patch) | |
tree | 288fab288475b48cf6174b3e49e59900af1beb31 | |
parent | b07f6712e983d901839a785ddf42c79d7e08872a (diff) | |
parent | 850c977953e4de3c8bbee64a3d2e8726c971761c (diff) | |
download | NetworkManager-2d1b85f8d7f1e53b581e56f0f542b63e8a80da98.tar.gz |
core: merge branch 'th/assume-vs-unmanaged-bgo746440'
This branch only does part of what bgo#746440 is about.
But it's a large and necessary step towards the full
solution. It cleanups tracking of whether to assume
a device, treat it as external or fully manage it.
Future work will need to fine tune the behavior.
https://bugzilla.gnome.org/show_bug.cgi?id=746440
https://bugzilla.redhat.com/show_bug.cgi?id=1394579
-rw-r--r-- | shared/nm-utils/nm-macros-internal.h | 25 | ||||
-rw-r--r-- | src/NetworkManagerUtils.c | 23 | ||||
-rw-r--r-- | src/NetworkManagerUtils.h | 2 | ||||
-rw-r--r-- | src/devices/nm-device-vlan.c | 5 | ||||
-rw-r--r-- | src/devices/nm-device.c | 410 | ||||
-rw-r--r-- | src/devices/nm-device.h | 17 | ||||
-rw-r--r-- | src/devices/team/nm-device-team.c | 2 | ||||
-rw-r--r-- | src/nm-act-request.c | 3 | ||||
-rw-r--r-- | src/nm-act-request.h | 1 | ||||
-rw-r--r-- | src/nm-active-connection.c | 119 | ||||
-rw-r--r-- | src/nm-active-connection.h | 6 | ||||
-rw-r--r-- | src/nm-checkpoint.c | 1 | ||||
-rw-r--r-- | src/nm-connectivity.c | 3 | ||||
-rw-r--r-- | src/nm-core-utils.c | 9 | ||||
-rw-r--r-- | src/nm-core-utils.h | 6 | ||||
-rw-r--r-- | src/nm-dispatcher.c | 207 | ||||
-rw-r--r-- | src/nm-dispatcher.h | 73 | ||||
-rw-r--r-- | src/nm-manager.c | 374 | ||||
-rw-r--r-- | src/nm-manager.h | 1 | ||||
-rw-r--r-- | src/nm-policy.c | 5 | ||||
-rw-r--r-- | src/nm-types.h | 16 | ||||
-rw-r--r-- | src/settings/nm-settings-connection.c | 16 | ||||
-rw-r--r-- | src/settings/nm-settings-connection.h | 10 | ||||
-rw-r--r-- | src/settings/nm-settings.c | 2 | ||||
-rw-r--r-- | src/tests/test-general.c | 66 | ||||
-rw-r--r-- | src/vpn/nm-vpn-connection.c | 12 |
26 files changed, 904 insertions, 510 deletions
diff --git a/shared/nm-utils/nm-macros-internal.h b/shared/nm-utils/nm-macros-internal.h index 43b5238efc..90f4e8533d 100644 --- a/shared/nm-utils/nm-macros-internal.h +++ b/shared/nm-utils/nm-macros-internal.h @@ -233,21 +233,34 @@ NM_G_ERROR_MSG (GError *error) #define _NM_IN_SET_EVAL_16(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_15 (op, _x, __VA_ARGS__) #define _NM_IN_SET_EVAL_N2(op, _x, n, ...) (_NM_IN_SET_EVAL_##n(op, _x, __VA_ARGS__)) -#define _NM_IN_SET_EVAL_N(op, x, n, ...) \ +#define _NM_IN_SET_EVAL_N(op, type, x, n, ...) \ ({ \ - typeof(x) _x = (x); \ + type _x = (x); \ + \ + /* trigger a -Wenum-compare warning */ \ + nm_assert (TRUE || _x == (x)); \ + \ !!_NM_IN_SET_EVAL_N2(op, _x, n, __VA_ARGS__); \ }) +#define _NM_IN_SET(op, type, x, ...) _NM_IN_SET_EVAL_N(op, type, x, NM_NARG (__VA_ARGS__), __VA_ARGS__) + /* Beware that this does short-circuit evaluation (use "||" instead of "|") * which has a possibly unexpected non-function-like behavior. * Use NM_IN_SET_SE if you need all arguments to be evaluted. */ -#define NM_IN_SET(x, ...) _NM_IN_SET_EVAL_N(||, x, NM_NARG (__VA_ARGS__), __VA_ARGS__) +#define NM_IN_SET(x, ...) _NM_IN_SET(||, typeof (x), x, __VA_ARGS__) /* "SE" stands for "side-effect". Contrary to NM_IN_SET(), this does not do * short-circuit evaluation, which can make a difference if the arguments have * side-effects. */ -#define NM_IN_SET_SE(x, ...) _NM_IN_SET_EVAL_N(|, x, NM_NARG (__VA_ARGS__), __VA_ARGS__) +#define NM_IN_SET_SE(x, ...) _NM_IN_SET(|, typeof (x), x, __VA_ARGS__) + +/* the *_TYPED forms allow to explicitly select the type of "x". This is useful + * if "x" doesn't support typeof (bitfields) or you want to gracefully convert + * a type using automatic type conversion rules (but not forcing the conversion + * with a cast). */ +#define NM_IN_SET_TYPED(type, x, ...) _NM_IN_SET(||, type, x, __VA_ARGS__) +#define NM_IN_SET_SE_TYPED(type, x, ...) _NM_IN_SET(|, type, x, __VA_ARGS__) /*****************************************************************************/ @@ -278,8 +291,8 @@ _NM_IN_STRSET_streq (const char *x, const char *s) #define _NM_IN_STRSET_EVAL_N(op, x, n, ...) \ ({ \ const char *_x = (x); \ - ( ((_x == NULL) && _NM_IN_SET_EVAL_N2 (op, (const char *) NULL, n, __VA_ARGS__)) \ - || ((_x != NULL) && _NM_IN_STRSET_EVAL_N2 (op, _x, n, __VA_ARGS__)) \ + ( ((_x == NULL) && _NM_IN_SET_EVAL_N2 (op, ((const char *) NULL), n, __VA_ARGS__)) \ + || ((_x != NULL) && _NM_IN_STRSET_EVAL_N2 (op, _x, n, __VA_ARGS__)) \ ); \ }) diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index 20b871622e..fbca3b82f3 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -370,9 +370,9 @@ route_compare (NMIPRoute *route1, NMIPRoute *route2, gint64 default_metric) } static int -route_ptr_compare (const void *a, const void *b) +route_ptr_compare (const void *a, const void *b, gpointer metric) { - return route_compare (*(NMIPRoute **) a, *(NMIPRoute **) b, -1); + return route_compare (*(NMIPRoute **) a, *(NMIPRoute **) b, *((gint64 *) metric)); } static gboolean @@ -384,6 +384,7 @@ check_ip_routes (NMConnection *orig, { gs_free NMIPRoute **routes1 = NULL, **routes2 = NULL; NMSettingIPConfig *s_ip1, *s_ip2; + gint64 m; const char *s_name; GHashTable *props; guint i, num; @@ -415,8 +416,12 @@ check_ip_routes (NMConnection *orig, routes2[i] = nm_setting_ip_config_get_route (s_ip2, i); } - qsort (routes1, num, sizeof (NMIPRoute *), route_ptr_compare); - qsort (routes2, num, sizeof (NMIPRoute *), route_ptr_compare); + m = nm_setting_ip_config_get_route_metric (s_ip2); + if (m != -1) + default_metric = m; + + g_qsort_with_data (routes1, num, sizeof (NMIPRoute *), route_ptr_compare, &default_metric); + g_qsort_with_data (routes2, num, sizeof (NMIPRoute *), route_ptr_compare, &default_metric); for (i = 0; i < num; i++) { if (route_compare (routes1[i], routes2[i], default_metric)) @@ -710,7 +715,7 @@ check_possible_match (NMConnection *orig, * matches well enough. */ NMConnection * -nm_utils_match_connection (GSList *connections, +nm_utils_match_connection (NMConnection *const*connections, NMConnection *original, gboolean device_has_carrier, gint64 default_v4_metric, @@ -719,10 +724,12 @@ nm_utils_match_connection (GSList *connections, gpointer match_filter_data) { NMConnection *best_match = NULL; - GSList *iter; - for (iter = connections; iter; iter = iter->next) { - NMConnection *candidate = NM_CONNECTION (iter->data); + if (!connections) + return NULL; + + for (; *connections; connections++) { + NMConnection *candidate = NM_CONNECTION (*connections); GHashTable *diffs = NULL; if (match_filter_func) { diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h index 9b5b9106fd..c20f2439d4 100644 --- a/src/NetworkManagerUtils.h +++ b/src/NetworkManagerUtils.h @@ -39,7 +39,7 @@ void nm_utils_complete_generic (NMPlatform *platform, typedef gboolean (NMUtilsMatchFilterFunc) (NMConnection *connection, gpointer user_data); -NMConnection *nm_utils_match_connection (GSList *connections, +NMConnection *nm_utils_match_connection (NMConnection *const*connections, NMConnection *original, gboolean device_has_carrier, gint64 default_v4_metric, diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c index 54d0440960..ada4f3295f 100644 --- a/src/devices/nm-device-vlan.c +++ b/src/devices/nm-device-vlan.c @@ -90,13 +90,14 @@ parent_hwaddr_maybe_changed (NMDevice *parent, GParamSpec *pspec, gpointer user_data) { - NMDeviceVlan *self = NM_DEVICE_VLAN (user_data); + NMDevice *device = NM_DEVICE (user_data); + NMDeviceVlan *self = NM_DEVICE_VLAN (device); NMConnection *connection; const char *new_mac, *old_mac; NMSettingIPConfig *s_ip6; /* Never touch assumed devices */ - if (nm_device_uses_assumed_connection ((NMDevice *) self)) + if (nm_device_sys_iface_state_is_external_or_assume (device)) return; connection = nm_device_get_applied_connection ((NMDevice *) self); diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index cb1cc63707..802900f5bc 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -206,6 +206,7 @@ typedef struct _NMDevicePrivate { NMDeviceState state; NMDeviceStateReason reason; } queued_state; + guint queued_ip4_config_id; guint queued_ip6_config_id; GSList *pending_actions; @@ -250,6 +251,8 @@ typedef struct _NMDevicePrivate { NMUtilsStableType current_stable_id_type:3; + bool is_nm_owned:1; /* whether the device is a device owned and created by NM */ + GHashTable * available_connections; char * hw_addr; char * hw_addr_perm; @@ -259,7 +262,6 @@ typedef struct _NMDevicePrivate { NMUnmanagedFlags unmanaged_mask; NMUnmanagedFlags unmanaged_flags; - bool is_nm_owned; /* whether the device is a device owned and created by NM */ DeleteOnDeactivateData *delete_on_deactivate_data; /* data for scheduled cleanup when deleting link (g_idle_add) */ GCancellable *deactivating_cancellable; @@ -289,15 +291,16 @@ typedef struct _NMDevicePrivate { guint link_connected_id; guint link_disconnected_id; guint carrier_defer_id; - bool carrier; guint carrier_wait_id; - bool ignore_carrier; gulong ignore_carrier_id; guint32 mtu; guint32 ip6_mtu; guint32 mtu_initial; guint32 ip6_mtu_initial; + bool carrier:1; + bool ignore_carrier:1; + bool mtu_initialized:1; bool up:1; /* IFF_UP */ @@ -305,6 +308,8 @@ typedef struct _NMDevicePrivate { bool v4_commit_first_time:1; bool v6_commit_first_time:1; + NMDeviceSysIfaceState sys_iface_state:2; + /* Generic DHCP stuff */ guint32 dhcp_timeout; char * dhcp_anycast_address; @@ -471,7 +476,7 @@ static gboolean nm_device_set_ip6_config (NMDevice *self, static gboolean ip6_config_merge_and_apply (NMDevice *self, gboolean commit); -static void nm_device_master_add_slave (NMDevice *self, NMDevice *slave, gboolean configure); +static gboolean nm_device_master_add_slave (NMDevice *self, NMDevice *slave, gboolean configure); static void nm_device_slave_notify_enslave (NMDevice *self, gboolean success); static void nm_device_slave_notify_release (NMDevice *self, NMDeviceStateReason reason); @@ -498,7 +503,9 @@ static gboolean ip_config_valid (NMDeviceState state); static NMActStageReturn dhcp4_start (NMDevice *self, NMConnection *connection); static gboolean dhcp6_start (NMDevice *self, gboolean wait_for_ll); static void nm_device_start_ip_check (NMDevice *self); -static void realize_start_setup (NMDevice *self, const NMPlatformLink *plink); +static void realize_start_setup (NMDevice *self, + const NMPlatformLink *plink, + NMUnmanFlagOp unmanaged_user_explicit); static void _commit_mtu (NMDevice *self, const NMIP4Config *config); static void dhcp_schedule_restart (NMDevice *self, int family, const char *reason); static void _cancel_activation (NMDevice *self); @@ -606,6 +613,69 @@ nm_device_get_settings (NMDevice *self) return NM_DEVICE_GET_PRIVATE (self)->settings; } +/*****************************************************************************/ + +NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_sys_iface_state_to_str, NMDeviceSysIfaceState, + NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT ("unknown"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_SYS_IFACE_STATE_EXTERNAL, "external"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_SYS_IFACE_STATE_ASSUME, "assume"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_SYS_IFACE_STATE_MANAGED, "managed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_SYS_IFACE_STATE_REMOVED, "removed"), +); + +NMDeviceSysIfaceState +nm_device_sys_iface_state_get (NMDevice *self) +{ + g_return_val_if_fail (NM_IS_DEVICE (self), NM_DEVICE_SYS_IFACE_STATE_EXTERNAL); + + return NM_DEVICE_GET_PRIVATE (self)->sys_iface_state; +} + +gboolean +nm_device_sys_iface_state_is_external (NMDevice *self) +{ + return NM_IN_SET (nm_device_sys_iface_state_get (self), + NM_DEVICE_SYS_IFACE_STATE_EXTERNAL); +} + +gboolean +nm_device_sys_iface_state_is_external_or_assume (NMDevice *self) +{ + return NM_IN_SET (nm_device_sys_iface_state_get (self), + NM_DEVICE_SYS_IFACE_STATE_EXTERNAL, + NM_DEVICE_SYS_IFACE_STATE_ASSUME); +} + +void +nm_device_sys_iface_state_set (NMDevice *self, + NMDeviceSysIfaceState sys_iface_state) +{ + NMDevicePrivate *priv; + + g_return_if_fail (NM_IS_DEVICE (self)); + g_return_if_fail (NM_IN_SET (sys_iface_state, + NM_DEVICE_SYS_IFACE_STATE_EXTERNAL, + NM_DEVICE_SYS_IFACE_STATE_ASSUME, + NM_DEVICE_SYS_IFACE_STATE_MANAGED, + NM_DEVICE_SYS_IFACE_STATE_REMOVED)); + + priv = NM_DEVICE_GET_PRIVATE (self); + if (priv->sys_iface_state != sys_iface_state) { + _LOGT (LOGD_DEVICE, "sys-iface-state: %s -> %s", + _sys_iface_state_to_str (priv->sys_iface_state), + _sys_iface_state_to_str (sys_iface_state)); + priv->sys_iface_state = sys_iface_state; + } + + /* this function only sets a flag, no immediate actions are initiated. + * + * If you change this, make sure that all callers are fine with such actions. */ + + nm_assert (priv->sys_iface_state == sys_iface_state); +} + +/*****************************************************************************/ + static void init_ip4_config_dns_priority (NMDevice *self, NMIP4Config *config) { @@ -1532,7 +1602,7 @@ nm_device_has_carrier (NMDevice *self) NMActRequest * nm_device_get_act_request (NMDevice *self) { - g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (NM_IS_DEVICE (self), NULL); return NM_DEVICE_GET_PRIVATE (self)->act_request; } @@ -1593,33 +1663,6 @@ nm_device_get_physical_port_id (NMDevice *self) /*****************************************************************************/ -static gboolean -nm_device_uses_generated_assumed_connection (NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMSettingsConnection *connection; - - if ( priv->act_request - && nm_active_connection_get_assumed (NM_ACTIVE_CONNECTION (priv->act_request))) { - connection = nm_act_request_get_settings_connection (priv->act_request); - if ( connection - && nm_settings_connection_get_nm_generated_assumed (connection)) - return TRUE; - } - return FALSE; -} - -gboolean -nm_device_uses_assumed_connection (NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - - if ( priv->act_request - && nm_active_connection_get_assumed (NM_ACTIVE_CONNECTION (priv->act_request))) - return TRUE; - return FALSE; -} - static SlaveInfo * find_slave_info (NMDevice *self, NMDevice *slave) { @@ -1725,7 +1768,7 @@ nm_device_master_release_one_slave (NMDevice *self, NMDevice *slave, gboolean co info = find_slave_info (self, slave); - _LOGt (LOGD_CORE, "master: release one slave %p/%s%s", slave, nm_device_get_iface (slave), + _LOGT (LOGD_CORE, "master: release one slave %p/%s%s", slave, nm_device_get_iface (slave), !info ? " (not registered)" : ""); if (!info) @@ -2371,6 +2414,8 @@ link_type_compatible (NMDevice *self, * nm_device_realize_start(): * @self: the #NMDevice * @plink: an existing platform link or %NULL + * @unmanaged_user_explicit: the user-explicit unmanaged flag to apply + * on the device initially. * @out_compatible: %TRUE on return if @self is compatible with @plink * @error: location to store error, or %NULL * @@ -2386,6 +2431,7 @@ link_type_compatible (NMDevice *self, gboolean nm_device_realize_start (NMDevice *self, const NMPlatformLink *plink, + NMUnmanFlagOp unmanaged_user_explicit, gboolean *out_compatible, GError **error) { @@ -2409,7 +2455,7 @@ nm_device_realize_start (NMDevice *self, plink_copy = *plink; plink = &plink_copy; } - realize_start_setup (self, plink); + realize_start_setup (self, plink, unmanaged_user_explicit); return TRUE; } @@ -2449,7 +2495,7 @@ nm_device_create_and_realize (NMDevice *self, plink = &plink_copy; } - realize_start_setup (self, plink); + realize_start_setup (self, plink, NM_UNMAN_FLAG_OP_FORGET); nm_device_realize_finish (self, plink); if (nm_device_get_managed (self, FALSE)) { @@ -2530,6 +2576,7 @@ realize_start_notify (NMDevice *self, * realize_start_setup(): * @self: the #NMDevice * @plink: the #NMPlatformLink if backed by a kernel netdevice + * @unmanaged_user_explicit: the user-explict unmanaged flag to set. * * Update the device from backing resource properties (like hardware * addresses, carrier states, driver/firmware info, etc). This function @@ -2538,7 +2585,9 @@ realize_start_notify (NMDevice *self, * stuff). */ static void -realize_start_setup (NMDevice *self, const NMPlatformLink *plink) +realize_start_setup (NMDevice *self, + const NMPlatformLink *plink, + NMUnmanFlagOp unmanaged_user_explicit) { NMDevicePrivate *priv; NMDeviceClass *klass; @@ -2576,6 +2625,8 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink) _notify (self, PROP_MTU); } + nm_device_sys_iface_state_set (self, NM_DEVICE_SYS_IFACE_STATE_EXTERNAL); + if (plink) { g_return_if_fail (link_type_compatible (self, plink->type, NULL, NULL)); update_device_from_platform_link (self, plink); @@ -2659,6 +2710,11 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink) klass->realize_start_notify (self, plink); + nm_assert (!nm_device_get_unmanaged_mask (self, NM_UNMANAGED_USER_EXPLICIT)); + nm_device_set_unmanaged_flags (self, + NM_UNMANAGED_USER_EXPLICIT, + unmanaged_user_explicit); + /* Do not manage externally created software devices until they are IFF_UP * or have IP addressing */ nm_device_set_unmanaged_flags (self, @@ -2944,7 +3000,6 @@ slave_state_changed (NMDevice *slave, { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); gboolean release = FALSE; - gboolean configure = TRUE; _LOGD (LOGD_DEVICE, "slave %s state change %d (%s) -> %d (%s)", nm_device_get_iface (slave), @@ -2967,12 +3022,10 @@ slave_state_changed (NMDevice *slave, release = TRUE; } - /* Don't touch the device if its state changed externally. */ - if (nm_device_state_reason_check (reason) == NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED) - configure = FALSE; - if (release) { - nm_device_master_release_one_slave (self, slave, configure, reason); + nm_device_master_release_one_slave (self, slave, + priv->sys_iface_state == NM_DEVICE_SYS_IFACE_STATE_MANAGED, + reason); /* Bridge/bond/team interfaces are left up until manually deactivated */ if (priv->slaves == NULL && priv->state == NM_DEVICE_STATE_ACTIVATED) _LOGD (LOGD_DEVICE, "last slave removed; remaining activated"); @@ -2988,32 +3041,36 @@ slave_state_changed (NMDevice *slave, * * If @self is capable of enslaving other devices (ie it's a bridge, bond, team, * etc) then this function adds @slave to the slave list for later enslavement. + * + * Returns: %TRUE if the slave was enslaved. %FALSE means, the slave was already + * enslaved and nothing was done. */ -static void +static gboolean nm_device_master_add_slave (NMDevice *self, NMDevice *slave, gboolean configure) { NMDevicePrivate *priv; NMDevicePrivate *slave_priv; SlaveInfo *info; + gboolean changed = FALSE; - g_return_if_fail (NM_IS_DEVICE (self)); - g_return_if_fail (NM_IS_DEVICE (slave)); - g_return_if_fail (NM_DEVICE_GET_CLASS (self)->enslave_slave != NULL); + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + g_return_val_if_fail (NM_IS_DEVICE (slave), FALSE); + g_return_val_if_fail (NM_DEVICE_GET_CLASS (self)->enslave_slave != NULL, FALSE); priv = NM_DEVICE_GET_PRIVATE (self); slave_priv = NM_DEVICE_GET_PRIVATE (slave); info = find_slave_info (self, slave); - _LOGt (LOGD_CORE, "master: add one slave %p/%s%s", slave, nm_device_get_iface (slave), + _LOGT (LOGD_CORE, "master: add one slave %p/%s%s", slave, nm_device_get_iface (slave), info ? " (already registered)" : ""); if (configure) - g_return_if_fail (nm_device_get_state (slave) >= NM_DEVICE_STATE_DISCONNECTED); + g_return_val_if_fail (nm_device_get_state (slave) >= NM_DEVICE_STATE_DISCONNECTED, FALSE); if (!info) { - g_return_if_fail (!slave_priv->master); - g_return_if_fail (!slave_priv->is_enslaved); + g_return_val_if_fail (!slave_priv->master, FALSE); + g_return_val_if_fail (!slave_priv->is_enslaved, FALSE); info = g_slice_new0 (SlaveInfo); info->slave = g_object_ref (slave); @@ -3033,13 +3090,15 @@ nm_device_master_add_slave (NMDevice *self, NMDevice *slave, gboolean configure) g_warn_if_fail (!NM_FLAGS_HAS (slave_priv->unmanaged_mask, NM_UNMANAGED_IS_SLAVE)); nm_device_set_unmanaged_by_flags (slave, NM_UNMANAGED_IS_SLAVE, FALSE, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); + changed = TRUE; } else - g_return_if_fail (slave_priv->master == self); + g_return_val_if_fail (slave_priv->master == self, FALSE); nm_device_queue_recheck_assume (self); nm_device_queue_recheck_assume (slave); -} + return changed; +} /** * nm_device_master_get_slaves: @@ -3132,7 +3191,7 @@ nm_device_master_release_slaves (NMDevice *self) gboolean configure = TRUE; /* Don't release the slaves if this connection doesn't belong to NM. */ - if (nm_device_uses_generated_assumed_connection (self)) + if (nm_device_sys_iface_state_is_external (self)) return; reason = priv->state_reason; @@ -3210,6 +3269,14 @@ nm_device_slave_notify_enslave (NMDevice *self, gboolean success) _LOGI (LOGD_DEVICE, "enslaved to %s", nm_device_get_iface (priv->master)); priv->is_enslaved = TRUE; + + if ( NM_IN_SET_TYPED (NMDeviceSysIfaceState, + priv->sys_iface_state, + NM_DEVICE_SYS_IFACE_STATE_EXTERNAL, + NM_DEVICE_SYS_IFACE_STATE_ASSUME) + && nm_device_sys_iface_state_get (priv->master) == NM_DEVICE_SYS_IFACE_STATE_MANAGED) + nm_device_sys_iface_state_set (self, NM_DEVICE_SYS_IFACE_STATE_MANAGED); + _notify (self, PROP_MASTER); _notify (priv->master, PROP_SLAVES); } else if (activating) { @@ -3248,15 +3315,19 @@ nm_device_slave_notify_release (NMDevice *self, NMDeviceStateReason reason) if ( priv->state > NM_DEVICE_STATE_DISCONNECTED && priv->state <= NM_DEVICE_STATE_ACTIVATED) { - if (nm_device_state_reason_check (reason) == NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED) { + switch (nm_device_state_reason_check (reason)) { + case NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED: new_state = NM_DEVICE_STATE_FAILED; master_status = "failed"; - } else if (nm_device_state_reason_check (reason) == NM_DEVICE_STATE_REASON_USER_REQUESTED) { + break; + case NM_DEVICE_STATE_REASON_USER_REQUESTED: new_state = NM_DEVICE_STATE_DEACTIVATING; master_status = "deactivated by user request"; - } else { + break; + default: new_state = NM_DEVICE_STATE_DISCONNECTED; master_status = "deactivated"; + break; } _LOGD (LOGD_DEVICE, "Activation: connection '%s' master %s", @@ -3920,12 +3991,14 @@ recheck_available (gpointer user_data) { NMDevice *self = NM_DEVICE (user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - gboolean now_available = nm_device_is_available (self, NM_DEVICE_CHECK_DEV_AVAILABLE_NONE); + gboolean now_available; NMDeviceState state = nm_device_get_state (self); NMDeviceState new_state = NM_DEVICE_STATE_UNKNOWN; priv->recheck_available.call_id = 0; + now_available = nm_device_is_available (self, NM_DEVICE_CHECK_DEV_AVAILABLE_NONE); + if (state == NM_DEVICE_STATE_UNAVAILABLE && now_available) { new_state = NM_DEVICE_STATE_DISCONNECTED; nm_device_queue_state (self, new_state, priv->recheck_available.available_reason); @@ -4164,7 +4237,7 @@ master_ready (NMDevice *self, /* If the master didn't change, add-slave only rechecks whether to assume a connection. */ nm_device_master_add_slave (master, self, - nm_active_connection_get_assumed (active) ? FALSE : TRUE); + !nm_device_sys_iface_state_is_external_or_assume (self)); } static void @@ -4232,7 +4305,6 @@ activate_stage1_device_prepare (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; - NMActiveConnection *active = NM_ACTIVE_CONNECTION (priv->act_request); _set_ip_state (self, AF_INET, IP_NONE); _set_ip_state (self, AF_INET6, IP_NONE); @@ -4244,7 +4316,7 @@ activate_stage1_device_prepare (NMDevice *self) nm_device_state_changed (self, NM_DEVICE_STATE_PREPARE, NM_DEVICE_STATE_REASON_NONE); /* Assumed connections were already set up outside NetworkManager */ - if (!nm_active_connection_get_assumed (active)) { + if (!nm_device_sys_iface_state_is_external_or_assume (self)) { NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE; ret = NM_DEVICE_GET_CLASS (self)->act_stage1_prepare (self, &failure_reason); @@ -4336,13 +4408,12 @@ activate_stage2_device_config (NMDevice *self) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMActStageReturn ret; gboolean no_firmware = FALSE; - NMActiveConnection *active = NM_ACTIVE_CONNECTION (priv->act_request); GSList *iter; nm_device_state_changed (self, NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_REASON_NONE); /* Assumed connections were already set up outside NetworkManager */ - if (!nm_active_connection_get_assumed (active)) { + if (!nm_device_sys_iface_state_is_external_or_assume (self)) { NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE; if (!nm_device_bring_up (self, FALSE, &no_firmware)) { @@ -4370,7 +4441,8 @@ activate_stage2_device_config (NMDevice *self) if (slave_state == NM_DEVICE_STATE_IP_CONFIG) nm_device_master_enslave_slave (self, info->slave, nm_device_get_applied_connection (info->slave)); - else if ( nm_device_uses_generated_assumed_connection (self) + else if ( priv->act_request + && nm_device_sys_iface_state_is_external (self) && slave_state <= NM_DEVICE_STATE_DISCONNECTED) nm_device_queue_recheck_assume (info->slave); } @@ -4471,7 +4543,7 @@ check_ip_state (NMDevice *self, gboolean may_fail) && (priv->ip6_state == IP_FAIL || (ip6_ignore && priv->ip6_state == IP_DONE))) { /* Either both methods failed, or only one failed and the other is * disabled */ - if (nm_device_uses_assumed_connection (self)) { + if (nm_device_sys_iface_state_is_external_or_assume (self)) { /* We have assumed configuration, but couldn't redo it. No problem, * move to check state. */ _set_ip_state (self, AF_INET, IP_DONE); @@ -4663,7 +4735,7 @@ ipv4_dad_start (NMDevice *self, NMIP4Config **configs, ArpingCallback cb) || !hw_addr || !hw_addr_len || !addr_found - || nm_device_uses_assumed_connection (self)) { + || nm_device_sys_iface_state_is_external_or_assume (self)) { /* DAD not needed, signal success */ cb (self, configs, TRUE); @@ -4964,7 +5036,7 @@ ensure_con_ip4_config (NMDevice *self) nm_connection_get_setting_ip4_config (connection), nm_device_get_ip4_route_metric (self)); - if (nm_device_uses_assumed_connection (self)) { + if (nm_device_sys_iface_state_is_external_or_assume (self)) { /* For assumed connections ignore all addresses and routes. */ nm_ip4_config_reset_addresses (priv->con_ip4_config); nm_ip4_config_reset_routes (priv->con_ip4_config); @@ -4990,7 +5062,7 @@ ensure_con_ip6_config (NMDevice *self) nm_connection_get_setting_ip6_config (connection), nm_device_get_ip6_route_metric (self)); - if (nm_device_uses_assumed_connection (self)) { + if (nm_device_sys_iface_state_is_external_or_assume (self)) { /* For assumed connections ignore all addresses and routes. */ nm_ip6_config_reset_addresses (priv->con_ip6_config); nm_ip6_config_reset_routes (priv->con_ip6_config); @@ -5132,7 +5204,7 @@ ip4_config_merge_and_apply (NMDevice *self, * but if the IP method is automatic we need to update the default route to * maintain connectivity. */ - if (nm_device_uses_generated_assumed_connection (self) && !auto_method) + if (nm_device_sys_iface_state_is_external (self) && !auto_method) goto END_ADD_DEFAULT_ROUTE; /* At this point, we treat assumed and non-assumed connections alike. @@ -5208,7 +5280,7 @@ END_ADD_DEFAULT_ROUTE: routes_full_sync = commit && priv->v4_commit_first_time - && !nm_device_uses_assumed_connection (self); + && !nm_device_sys_iface_state_is_external_or_assume (self); success = nm_device_set_ip4_config (self, composite, default_route_metric, commit, routes_full_sync); g_object_unref (composite); @@ -5228,14 +5300,10 @@ dhcp4_lease_change (NMDevice *self, NMIP4Config *config) return FALSE; } - /* Notify dispatcher scripts of new DHCP4 config */ - nm_dispatcher_call (DISPATCHER_ACTION_DHCP4_CHANGE, - nm_device_get_settings_connection (self), - nm_device_get_applied_connection (self), - self, - NULL, - NULL, - NULL); + nm_dispatcher_call_device (NM_DISPATCHER_ACTION_DHCP4_CHANGE, + self, + NULL, + NULL, NULL, NULL); nm_device_remove_pending_action (self, NM_PENDING_ACTION_DHCP4, FALSE); @@ -5285,7 +5353,7 @@ dhcp4_fail (NMDevice *self, gboolean timeout) * device will transition to the ACTIVATED state without IP configuration), * retry DHCP again. */ - if (nm_device_uses_assumed_connection (self)) { + if (nm_device_sys_iface_state_is_external_or_assume (self)) { dhcp_schedule_restart (self, AF_INET, "connection is assumed"); return; } @@ -5883,7 +5951,7 @@ ip6_config_merge_and_apply (NMDevice *self, * but if the IP method is automatic we need to update the default route to * maintain connectivity. */ - if (nm_device_uses_generated_assumed_connection (self) && !auto_method) + if (nm_device_sys_iface_state_is_external (self) && !auto_method) goto END_ADD_DEFAULT_ROUTE; /* At this point, we treat assumed and non-assumed connections alike. @@ -5965,7 +6033,7 @@ END_ADD_DEFAULT_ROUTE: routes_full_sync = commit && priv->v6_commit_first_time - && !nm_device_uses_assumed_connection (self); + && !nm_device_sys_iface_state_is_external_or_assume (self); success = nm_device_set_ip6_config (self, composite, commit, routes_full_sync); g_object_unref (composite); @@ -5996,11 +6064,10 @@ dhcp6_lease_change (NMDevice *self) return FALSE; } - /* Notify dispatcher scripts of new DHCPv6 config */ - nm_dispatcher_call (DISPATCHER_ACTION_DHCP6_CHANGE, - settings_connection, - nm_device_get_applied_connection (self), - self, NULL, NULL, NULL); + nm_dispatcher_call_device (NM_DISPATCHER_ACTION_DHCP6_CHANGE, + self, + NULL, + NULL, NULL, NULL); nm_device_remove_pending_action (self, NM_PENDING_ACTION_DHCP6, FALSE); @@ -6080,7 +6147,7 @@ dhcp6_fail (NMDevice *self, gboolean timeout) * device will transition to the ACTIVATED state without IP configuration), * retry DHCP again. */ - if (nm_device_uses_assumed_connection (self)) { + if (nm_device_sys_iface_state_is_external_or_assume (self)) { dhcp_schedule_restart (self, AF_INET6, "connection is assumed"); return; } @@ -6665,7 +6732,7 @@ _commit_mtu (NMDevice *self, const NMIP4Config *config) if (ifindex <= 0) return; - if (nm_device_uses_assumed_connection (self)) { + if (nm_device_sys_iface_state_is_external_or_assume (self)) { /* for assumed connections we don't tamper with the MTU. This is * a bug and supposed to be fixed by the unmanaged/assumed rework. */ return; @@ -7332,7 +7399,7 @@ act_stage3_ip6_config_start (NMDevice *self, * IPv6LL if this is not an assumed connection, since assumed connections * will already have IPv6 set up. */ - if (!nm_device_uses_assumed_connection (self)) + if (!nm_device_sys_iface_state_is_external_or_assume (self)) set_nm_ipv6ll (self, TRUE); /* Re-enable IPv6 on the interface */ @@ -7362,7 +7429,7 @@ act_stage3_ip6_config_start (NMDevice *self, _LOGW (LOGD_IP6, "unhandled IPv6 config method '%s'; will fail", method); if ( ret != NM_ACT_STAGE_RETURN_FAILURE - && !nm_device_uses_assumed_connection (self)) { + && !nm_device_sys_iface_state_is_external_or_assume (self)) { switch (ip6_privacy) { case NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN: case NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED: @@ -7605,7 +7672,7 @@ nm_device_activate_schedule_stage3_ip_config_start (NMDevice *self) s_con = nm_connection_get_setting_connection (connection); if (!priv->fw_ready) { - if (nm_device_uses_generated_assumed_connection (self)) + if (nm_device_sys_iface_state_is_external (self)) priv->fw_ready = TRUE; else { if (!priv->fw_call) { @@ -7907,7 +7974,7 @@ activate_stage5_ip4_config_commit (NMDevice *self) /* Interface must be IFF_UP before IP config can be applied */ ip_ifindex = nm_device_get_ip_ifindex (self); - if (!nm_platform_link_is_up (NM_PLATFORM_GET, ip_ifindex) && !nm_device_uses_assumed_connection (self)) { + if (!nm_platform_link_is_up (NM_PLATFORM_GET, ip_ifindex) && !nm_device_sys_iface_state_is_external_or_assume (self)) { nm_platform_link_set_up (NM_PLATFORM_GET, ip_ifindex, NULL); if (!nm_platform_link_is_up (NM_PLATFORM_GET, ip_ifindex)) _LOGW (LOGD_DEVICE, "interface %s not up for IP configuration", nm_device_get_ip_iface (self)); @@ -7937,14 +8004,10 @@ activate_stage5_ip4_config_commit (NMDevice *self) if ( priv->dhcp4.client && nm_device_activate_ip4_state_in_conf (self) && (nm_device_get_state (self) > NM_DEVICE_STATE_IP_CONFIG)) { - /* Notify dispatcher scripts of new DHCP4 config */ - nm_dispatcher_call (DISPATCHER_ACTION_DHCP4_CHANGE, - nm_device_get_settings_connection (self), - nm_device_get_applied_connection (self), - self, - NULL, - NULL, - NULL); + nm_dispatcher_call_device (NM_DISPATCHER_ACTION_DHCP4_CHANGE, + self, + NULL, + NULL, NULL, NULL); } arp_announce (self); @@ -8060,7 +8123,7 @@ activate_stage5_ip6_config_commit (NMDevice *self) /* Interface must be IFF_UP before IP config can be applied */ ip_ifindex = nm_device_get_ip_ifindex (self); - if (!nm_platform_link_is_up (NM_PLATFORM_GET, ip_ifindex) && !nm_device_uses_assumed_connection (self)) { + if (!nm_platform_link_is_up (NM_PLATFORM_GET, ip_ifindex) && !nm_device_sys_iface_state_is_external_or_assume (self)) { nm_platform_link_set_up (NM_PLATFORM_GET, ip_ifindex, NULL); if (!nm_platform_link_is_up (NM_PLATFORM_GET, ip_ifindex)) _LOGW (LOGD_DEVICE, "interface %s not up for IP configuration", nm_device_get_ip_iface (self)); @@ -8073,13 +8136,10 @@ activate_stage5_ip6_config_commit (NMDevice *self) /* If IPv6 wasn't the first IP to complete, and DHCP was used, * then ensure dispatcher scripts get the DHCP lease information. */ - nm_dispatcher_call (DISPATCHER_ACTION_DHCP6_CHANGE, - nm_device_get_settings_connection (self), - nm_device_get_applied_connection (self), - self, - NULL, - NULL, - NULL); + nm_dispatcher_call_device (NM_DISPATCHER_ACTION_DHCP6_CHANGE, + self, + NULL, + NULL, NULL, NULL); } else { /* still waiting for first dhcp6 lease. */ return; @@ -8192,7 +8252,24 @@ act_request_set (NMDevice *self, NMActRequest *act_request) "notify::"NM_EXPORTED_OBJECT_PATH, G_CALLBACK (act_request_set_cb), self); + + switch (nm_active_connection_get_activation_type (NM_ACTIVE_CONNECTION (act_request))) { + case NM_ACTIVATION_TYPE_EXTERNAL: + break; + case NM_ACTIVATION_TYPE_ASSUME: + if (priv->sys_iface_state == NM_DEVICE_SYS_IFACE_STATE_EXTERNAL) + nm_device_sys_iface_state_set (self, NM_DEVICE_SYS_IFACE_STATE_ASSUME); + break; + case NM_ACTIVATION_TYPE_MANAGED: + if (NM_IN_SET_TYPED (NMDeviceSysIfaceState, + priv->sys_iface_state, + NM_DEVICE_SYS_IFACE_STATE_EXTERNAL, + NM_DEVICE_SYS_IFACE_STATE_ASSUME)) + nm_device_sys_iface_state_set (self, NM_DEVICE_SYS_IFACE_STATE_MANAGED); + break; + } } + _notify (self, PROP_ACTIVE_CONNECTION); } @@ -9291,7 +9368,7 @@ nm_device_set_ip4_config (NMDevice *self, /* Always commit to nm-platform to update lifetimes */ if (commit && new_config) { - gboolean assumed = nm_device_uses_assumed_connection (self); + gboolean assumed = nm_device_sys_iface_state_is_external_or_assume (self); _commit_mtu (self, new_config); /* For assumed devices we must not touch the kernel-routes, such as the device-route. @@ -9333,6 +9410,8 @@ nm_device_set_ip4_config (NMDevice *self, nm_default_route_manager_ip4_update_default_route (nm_default_route_manager_get (), self); if (has_changes) { + NMSettingsConnection *settings_connection; + _update_ip4_address (self); if (old_config != priv->ip4_config) @@ -9342,15 +9421,17 @@ nm_device_set_ip4_config (NMDevice *self, if (old_config != priv->ip4_config) nm_exported_object_clear_and_unexport (&old_config); - if (nm_device_uses_generated_assumed_connection (self)) { - NMConnection *settings_connection = NM_CONNECTION (nm_device_get_settings_connection (self)); + if ( nm_device_sys_iface_state_is_external (self) + && (settings_connection = nm_device_get_settings_connection (self)) + && nm_settings_connection_get_nm_generated (settings_connection) + && nm_active_connection_get_activation_type (NM_ACTIVE_CONNECTION (priv->act_request)) == NM_ACTIVATION_TYPE_EXTERNAL) { NMSetting *s_ip4; g_object_freeze_notify (G_OBJECT (settings_connection)); - nm_connection_remove_setting (settings_connection, NM_TYPE_SETTING_IP4_CONFIG); + nm_connection_remove_setting (NM_CONNECTION (settings_connection), NM_TYPE_SETTING_IP4_CONFIG); s_ip4 = nm_ip4_config_create_setting (priv->ip4_config); - nm_connection_add_setting (settings_connection, s_ip4); + nm_connection_add_setting (NM_CONNECTION (settings_connection), s_ip4); g_object_thaw_notify (G_OBJECT (settings_connection)); } @@ -9489,6 +9570,8 @@ nm_device_set_ip6_config (NMDevice *self, nm_default_route_manager_ip6_update_default_route (nm_default_route_manager_get (), self); if (has_changes) { + NMSettingsConnection *settings_connection; + if (old_config != priv->ip6_config) _notify (self, PROP_IP6_CONFIG); g_signal_emit (self, signals[IP6_CONFIG_CHANGED], 0, priv->ip6_config, old_config); @@ -9496,15 +9579,17 @@ nm_device_set_ip6_config (NMDevice *self, if (old_config != priv->ip6_config) nm_exported_object_clear_and_unexport (&old_config); - if (nm_device_uses_generated_assumed_connection (self)) { - NMConnection *settings_connection = NM_CONNECTION (nm_device_get_settings_connection (self)); + if ( nm_device_sys_iface_state_is_external (self) + && (settings_connection = nm_device_get_settings_connection (self)) + && nm_settings_connection_get_nm_generated (settings_connection) + && nm_active_connection_get_activation_type (NM_ACTIVE_CONNECTION (priv->act_request)) == NM_ACTIVATION_TYPE_EXTERNAL) { NMSetting *s_ip6; g_object_freeze_notify (G_OBJECT (settings_connection)); - nm_connection_remove_setting (settings_connection, NM_TYPE_SETTING_IP6_CONFIG); + nm_connection_remove_setting (NM_CONNECTION (settings_connection), NM_TYPE_SETTING_IP6_CONFIG); s_ip6 = nm_ip6_config_create_setting (priv->ip6_config); - nm_connection_add_setting (settings_connection, s_ip6); + nm_connection_add_setting (NM_CONNECTION (settings_connection), s_ip6); g_object_thaw_notify (G_OBJECT (settings_connection)); } @@ -9608,13 +9693,12 @@ ip_check_pre_up (NMDevice *self) priv->dispatcher.post_state = NM_DEVICE_STATE_SECONDARIES; priv->dispatcher.post_state_reason = NM_DEVICE_STATE_REASON_NONE; - if (!nm_dispatcher_call (DISPATCHER_ACTION_PRE_UP, - nm_device_get_settings_connection (self), - nm_device_get_applied_connection (self), - self, - dispatcher_complete_proceed_state, - self, - &priv->dispatcher.call_id)) { + if (!nm_dispatcher_call_device (NM_DISPATCHER_ACTION_PRE_UP, + self, + NULL, + dispatcher_complete_proceed_state, + self, + &priv->dispatcher.call_id)) { /* Just proceed on errors */ dispatcher_complete_proceed_state (0, self); } @@ -10976,7 +11060,7 @@ nm_device_update_firewall_zone (NMDevice *self) s_con = nm_connection_get_setting_connection (applied_connection); if ( nm_device_get_state (self) == NM_DEVICE_STATE_ACTIVATED - && !nm_device_uses_generated_assumed_connection (self)) { + && !nm_device_sys_iface_state_is_external (self)) { nm_firewall_manager_add_or_change_zone (nm_firewall_manager_get (), nm_device_get_ip_iface (self), nm_setting_connection_get_zone (s_con), @@ -11477,7 +11561,7 @@ _cleanup_generic_pre (NMDevice *self, CleanupType cleanup_type) connection = nm_device_get_applied_connection (self); if ( cleanup_type == CLEANUP_TYPE_DECONFIGURE && connection - && !nm_device_uses_generated_assumed_connection (self)) { + && !nm_device_sys_iface_state_is_external (self)) { nm_firewall_manager_remove_from_zone (nm_firewall_manager_get (), nm_device_get_ip_iface (self), NULL, @@ -11995,6 +12079,14 @@ _set_state_full (NMDevice *self, /* Cache the activation request for the dispatcher */ req = nm_g_object_ref (priv->act_request); + if ( state > NM_DEVICE_STATE_UNMANAGED + && nm_device_state_reason_check (reason) == NM_DEVICE_STATE_REASON_NOW_MANAGED + && NM_IN_SET_TYPED (NMDeviceSysIfaceState, + priv->sys_iface_state, + NM_DEVICE_SYS_IFACE_STATE_EXTERNAL, + NM_DEVICE_SYS_IFACE_STATE_ASSUME)) + nm_device_sys_iface_state_set (self, NM_DEVICE_SYS_IFACE_STATE_MANAGED); + if (state <= NM_DEVICE_STATE_UNAVAILABLE) { if (available_connections_del_all (self)) _notify (self, PROP_AVAILABLE_CONNECTIONS); @@ -12018,14 +12110,12 @@ _set_state_full (NMDevice *self, case NM_DEVICE_STATE_UNMANAGED: nm_device_set_firmware_missing (self, FALSE); if (old_state > NM_DEVICE_STATE_UNMANAGED) { - switch (nm_device_state_reason_check (reason)) { - case NM_DEVICE_STATE_REASON_REMOVED: - nm_device_cleanup (self, reason, CLEANUP_TYPE_REMOVED); - break; - case NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED: - nm_device_cleanup (self, reason, CLEANUP_TYPE_KEEP); - break; - default: + if (priv->sys_iface_state != NM_DEVICE_SYS_IFACE_STATE_MANAGED) { + nm_device_cleanup (self, reason, + priv->sys_iface_state == NM_DEVICE_SYS_IFACE_STATE_REMOVED + ? CLEANUP_TYPE_REMOVED + : CLEANUP_TYPE_KEEP); + } else { /* Clean up if the device is now unmanaged but was activated */ if (nm_device_get_act_request (self)) nm_device_cleanup (self, reason, CLEANUP_TYPE_DECONFIGURE); @@ -12040,11 +12130,11 @@ _set_state_full (NMDevice *self, case NM_DEVICE_STATE_UNAVAILABLE: if (old_state == NM_DEVICE_STATE_UNMANAGED) { save_ip6_properties (self); - if (nm_device_state_reason_check (reason) != NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED) + if (priv->sys_iface_state == NM_DEVICE_SYS_IFACE_STATE_MANAGED) ip6_managed_setup (self); } - if (nm_device_state_reason_check (reason) != NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED) { + if (priv->sys_iface_state == NM_DEVICE_SYS_IFACE_STATE_MANAGED) { if (old_state == NM_DEVICE_STATE_UNMANAGED || priv->firmware_missing) { if (!nm_device_bring_up (self, TRUE, &no_firmware) && no_firmware) _LOGW (LOGD_PLATFORM, "firmware may be missing."); @@ -12071,7 +12161,7 @@ _set_state_full (NMDevice *self, nm_device_cleanup (self, reason, CLEANUP_TYPE_DECONFIGURE); } else if (old_state < NM_DEVICE_STATE_DISCONNECTED) { - if (nm_device_state_reason_check (reason) != NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED) { + if (priv->sys_iface_state == NM_DEVICE_SYS_IFACE_STATE_MANAGED) { /* Ensure IPv6 is set up as it may not have been done when * entering the UNAVAILABLE state depending on the reason. */ @@ -12130,20 +12220,17 @@ _set_state_full (NMDevice *self, priv->ignore_carrier = nm_config_data_get_ignore_carrier (NM_CONFIG_GET_DATA, self); if (quitting) { - nm_dispatcher_call_sync (DISPATCHER_ACTION_PRE_DOWN, - nm_act_request_get_settings_connection (req), - nm_act_request_get_applied_connection (req), - self); + nm_dispatcher_call_device_sync (NM_DISPATCHER_ACTION_PRE_DOWN, + self, req); } else { priv->dispatcher.post_state = NM_DEVICE_STATE_DISCONNECTED; priv->dispatcher.post_state_reason = reason; - if (!nm_dispatcher_call (DISPATCHER_ACTION_PRE_DOWN, - nm_act_request_get_settings_connection (req), - nm_act_request_get_applied_connection (req), - self, - deactivate_dispatcher_complete, - self, - &priv->dispatcher.call_id)) { + if (!nm_dispatcher_call_device (NM_DISPATCHER_ACTION_PRE_DOWN, + self, + req, + deactivate_dispatcher_complete, + self, + &priv->dispatcher.call_id)) { /* Just proceed on errors */ deactivate_dispatcher_complete (0, self); } @@ -12170,10 +12257,10 @@ _set_state_full (NMDevice *self, case NM_DEVICE_STATE_ACTIVATED: _LOGI (LOGD_DEVICE, "Activation: successful, device activated."); nm_device_update_metered (self); - nm_dispatcher_call (DISPATCHER_ACTION_UP, - nm_act_request_get_settings_connection (req), - nm_act_request_get_applied_connection (req), - self, NULL, NULL, NULL); + nm_dispatcher_call_device (NM_DISPATCHER_ACTION_UP, + self, + req, + NULL, NULL, NULL); if (priv->proxy_config) { nm_pacrunner_manager_send (priv->pacrunner_manager, @@ -12192,7 +12279,7 @@ _set_state_full (NMDevice *self, */ _cancel_activation (self); - if (nm_device_uses_assumed_connection (self)) { + if (nm_device_sys_iface_state_is_external_or_assume (self)) { /* Avoid tearing down assumed connection, assume it's connected */ nm_device_queue_state (self, NM_DEVICE_STATE_ACTIVATED, @@ -12230,7 +12317,7 @@ _set_state_full (NMDevice *self, if ( applied_connection && priv->ifindex != priv->ip_ifindex - && !nm_device_uses_generated_assumed_connection (self)) { + && !nm_device_sys_iface_state_is_external (self)) { NMSettingConnection *s_con; const char *zone; @@ -12265,15 +12352,13 @@ _set_state_full (NMDevice *self, if ( (old_state == NM_DEVICE_STATE_ACTIVATED || old_state == NM_DEVICE_STATE_DEACTIVATING) && (state != NM_DEVICE_STATE_DEACTIVATING)) { if (quitting) { - nm_dispatcher_call_sync (DISPATCHER_ACTION_DOWN, - nm_act_request_get_settings_connection (req), - nm_act_request_get_applied_connection (req), - self); + nm_dispatcher_call_device_sync (NM_DISPATCHER_ACTION_DOWN, + self, req); } else { - nm_dispatcher_call (DISPATCHER_ACTION_DOWN, - nm_act_request_get_settings_connection (req), - nm_act_request_get_applied_connection (req), - self, NULL, NULL, NULL); + nm_dispatcher_call_device (NM_DISPATCHER_ACTION_DOWN, + self, + req, + NULL, NULL, NULL); } } @@ -13179,6 +13264,7 @@ nm_device_init (NMDevice *self) priv->unmanaged_mask = priv->unmanaged_flags; priv->available_connections = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL); priv->ip6_saved_properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free); + priv->sys_iface_state = NM_DEVICE_SYS_IFACE_STATE_EXTERNAL; priv->pacrunner_manager = g_object_ref (nm_pacrunner_manager_get ()); diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index f98978bdc0..073e1fbdf2 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -30,6 +30,13 @@ #include "nm-rfkill-manager.h" #include "NetworkManagerUtils.h" +typedef enum { + NM_DEVICE_SYS_IFACE_STATE_EXTERNAL, + NM_DEVICE_SYS_IFACE_STATE_ASSUME, + NM_DEVICE_SYS_IFACE_STATE_MANAGED, + NM_DEVICE_SYS_IFACE_STATE_REMOVED, +} NMDeviceSysIfaceState; + static inline NMDeviceStateReason nm_device_state_reason_check (NMDeviceStateReason reason) { @@ -489,8 +496,6 @@ gboolean nm_device_complete_connection (NMDevice *device, gboolean nm_device_check_connection_compatible (NMDevice *device, NMConnection *connection); gboolean nm_device_check_slave_connection_compatible (NMDevice *device, NMConnection *connection); -gboolean nm_device_uses_assumed_connection (NMDevice *device); - gboolean nm_device_unmanage_on_quit (NMDevice *self); gboolean nm_device_spec_match_list (NMDevice *device, const GSList *specs); @@ -595,6 +600,7 @@ gboolean nm_device_has_capability (NMDevice *self, NMDeviceCapabilities caps); gboolean nm_device_realize_start (NMDevice *device, const NMPlatformLink *plink, + NMUnmanFlagOp unmanaged_user_explicit, gboolean *out_compatible, GError **error); void nm_device_realize_finish (NMDevice *self, @@ -611,6 +617,13 @@ gboolean nm_device_get_autoconnect (NMDevice *device); void nm_device_set_autoconnect_intern (NMDevice *device, gboolean autoconnect); void nm_device_emit_recheck_auto_activate (NMDevice *device); +NMDeviceSysIfaceState nm_device_sys_iface_state_get (NMDevice *device); + +gboolean nm_device_sys_iface_state_is_external (NMDevice *self); +gboolean nm_device_sys_iface_state_is_external_or_assume (NMDevice *self); + +void nm_device_sys_iface_state_set (NMDevice *device, NMDeviceSysIfaceState sys_iface_state); + void nm_device_state_changed (NMDevice *device, NMDeviceState state, NMDeviceStateReason reason); diff --git a/src/devices/team/nm-device-team.c b/src/devices/team/nm-device-team.c index 5a94e76df2..6906c759d6 100644 --- a/src/devices/team/nm-device-team.c +++ b/src/devices/team/nm-device-team.c @@ -416,7 +416,7 @@ teamd_dbus_appeared (GDBusConnection *connection, success = teamd_read_config (device); if (success) nm_device_activate_schedule_stage2_device_config (device); - else if (!nm_device_uses_assumed_connection (device)) + else if (!nm_device_sys_iface_state_is_external_or_assume (device)) nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED); } } diff --git a/src/nm-act-request.c b/src/nm-act-request.c index 0396489683..e4f6492365 100644 --- a/src/nm-act-request.c +++ b/src/nm-act-request.c @@ -543,6 +543,7 @@ nm_act_request_init (NMActRequest *req) * @specific_object: the object path of the specific object (ie, WiFi access point, * etc) that will be used to activate @connection and @device * @subject: the #NMAuthSubject representing the requestor of the activation + * @activation_type: the #NMActivationType. * @device: the device/interface to configure according to @connection * * Creates a new device-based activation request. If an applied connection is @@ -555,6 +556,7 @@ nm_act_request_new (NMSettingsConnection *settings_connection, NMConnection *applied_connection, const char *specific_object, NMAuthSubject *subject, + NMActivationType activation_type, NMDevice *device) { g_return_val_if_fail (!settings_connection || NM_IS_SETTINGS_CONNECTION (settings_connection), NULL); @@ -567,6 +569,7 @@ nm_act_request_new (NMSettingsConnection *settings_connection, NM_ACTIVE_CONNECTION_INT_DEVICE, device, NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT, specific_object, NM_ACTIVE_CONNECTION_INT_SUBJECT, subject, + NM_ACTIVE_CONNECTION_INT_ACTIVATION_TYPE, (int) activation_type, NULL); } diff --git a/src/nm-act-request.h b/src/nm-act-request.h index 47247f8910..b854940442 100644 --- a/src/nm-act-request.h +++ b/src/nm-act-request.h @@ -40,6 +40,7 @@ NMActRequest *nm_act_request_new (NMSettingsConnection *settings_connec NMConnection *applied_connection, const char *specific_object, NMAuthSubject *subject, + NMActivationType activation_type, NMDevice *device); NMSettingsConnection *nm_act_request_get_settings_connection (NMActRequest *req); diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c index ab2a9b3b6b..320ba45828 100644 --- a/src/nm-active-connection.c +++ b/src/nm-active-connection.c @@ -44,20 +44,20 @@ typedef struct _NMActiveConnectionPrivate { char *pending_activation_id; - gboolean is_default; - gboolean is_default6; NMActiveConnectionState state; - gboolean state_set; - gboolean vpn; + bool is_default:1; + bool is_default6:1; + bool state_set:1; + bool vpn:1; + bool master_ready:1; + + NMActivationType activation_type:3; NMAuthSubject *subject; NMActiveConnection *master; - gboolean master_ready; NMActiveConnection *parent; - gboolean assumed; - NMAuthChain *chain; const char *wifi_shared_permission; NMActiveConnectionAuthResultFunc result_func; @@ -88,6 +88,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMActiveConnection, PROP_INT_SUBJECT, PROP_INT_MASTER, PROP_INT_MASTER_READY, + PROP_INT_ACTIVATION_TYPE, ); enum { @@ -102,8 +103,15 @@ G_DEFINE_ABSTRACT_TYPE (NMActiveConnection, nm_active_connection, NM_TYPE_EXPORT #define NM_ACTIVE_CONNECTION_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR(self, NMActiveConnection, NM_IS_ACTIVE_CONNECTION) +/*****************************************************************************/ + static void check_master_ready (NMActiveConnection *self); static void _device_cleanup (NMActiveConnection *self); +static void _settings_connection_notify_flags (NMSettingsConnection *settings_connection, + GParamSpec *param, + NMActiveConnection *self); +static void _set_activation_type (NMActiveConnection *self, + NMActivationType activation_type); /*****************************************************************************/ @@ -181,12 +189,15 @@ _set_settings_connection (NMActiveConnection *self, NMSettingsConnection *connec if (priv->settings_connection) { g_signal_handlers_disconnect_by_func (priv->settings_connection, _settings_connection_updated, self); g_signal_handlers_disconnect_by_func (priv->settings_connection, _settings_connection_removed, self); + g_signal_handlers_disconnect_by_func (priv->settings_connection, _settings_connection_notify_flags, self); g_clear_object (&priv->settings_connection); } if (connection) { priv->settings_connection = g_object_ref (connection); g_signal_connect (connection, NM_SETTINGS_CONNECTION_UPDATED_INTERNAL, (GCallback) _settings_connection_updated, self); g_signal_connect (connection, NM_SETTINGS_CONNECTION_REMOVED, (GCallback) _settings_connection_removed, self); + if (nm_active_connection_get_activation_type (self) == NM_ACTIVATION_TYPE_EXTERNAL) + g_signal_connect (connection, "notify::"NM_SETTINGS_CONNECTION_FLAGS, (GCallback) _settings_connection_notify_flags, self); } } @@ -214,6 +225,14 @@ nm_active_connection_set_state (NMActiveConnection *self, state_to_string (new_state), state_to_string (priv->state)); + if ( new_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED + && priv->activation_type == NM_ACTIVATION_TYPE_ASSUME) { + /* assuming connections mean to gracefully take over an externally + * configured device. Once activation is complete, an assumed + * activation *is* the same as a full activation. */ + _set_activation_type (self, NM_ACTIVATION_TYPE_MANAGED); + } + old_state = priv->state; priv->state = new_state; priv->state_set = TRUE; @@ -566,7 +585,7 @@ nm_active_connection_set_device (NMActiveConnection *self, NMDevice *device) g_signal_connect (device, "notify::" NM_DEVICE_METERED, G_CALLBACK (device_metered_changed), self); - if (!priv->assumed) { + if (priv->activation_type != NM_ACTIVATION_TYPE_EXTERNAL) { priv->pending_activation_id = g_strdup_printf (NM_PENDING_ACTIONPREFIX_ACTIVATION"%p", (void *)self); nm_device_add_pending_action (device, priv->pending_activation_id, TRUE); } @@ -712,24 +731,55 @@ nm_active_connection_set_master (NMActiveConnection *self, NMActiveConnection *m check_master_ready (self); } -void -nm_active_connection_set_assumed (NMActiveConnection *self, gboolean assumed) +NMActivationType +nm_active_connection_get_activation_type (NMActiveConnection *self) +{ + g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), NM_ACTIVATION_TYPE_MANAGED); + + return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->activation_type; +} + +static void +_set_activation_type (NMActiveConnection *self, + NMActivationType activation_type) { NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self); - g_return_if_fail (priv->assumed == FALSE); - priv->assumed = assumed; + if (priv->activation_type == activation_type) + return; - if (priv->pending_activation_id) { - nm_device_remove_pending_action (priv->device, priv->pending_activation_id, TRUE); - g_clear_pointer (&priv->pending_activation_id, g_free); - } + _LOGD ("update activation type from %s to %s", + nm_activation_type_to_string (priv->activation_type), + nm_activation_type_to_string (activation_type)); + priv->activation_type = activation_type; + + if ( priv->activation_type == NM_ACTIVATION_TYPE_MANAGED + && priv->device + && self == NM_ACTIVE_CONNECTION (nm_device_get_act_request (priv->device)) + && NM_IN_SET (nm_device_sys_iface_state_get (priv->device), + NM_DEVICE_SYS_IFACE_STATE_EXTERNAL, + NM_DEVICE_SYS_IFACE_STATE_ASSUME)) + nm_device_sys_iface_state_set (priv->device, NM_DEVICE_SYS_IFACE_STATE_MANAGED); } -gboolean -nm_active_connection_get_assumed (NMActiveConnection *self) +/*****************************************************************************/ + +static void +_settings_connection_notify_flags (NMSettingsConnection *settings_connection, + GParamSpec *param, + NMActiveConnection *self) { - return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->assumed; + nm_assert (NM_IS_ACTIVE_CONNECTION (self)); + nm_assert (NM_IS_SETTINGS_CONNECTION (settings_connection)); + nm_assert (nm_active_connection_get_activation_type (self) == NM_ACTIVATION_TYPE_EXTERNAL); + nm_assert (NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->settings_connection == settings_connection); + + if (nm_settings_connection_get_nm_generated (settings_connection)) + return; + + g_signal_handlers_disconnect_by_func (settings_connection, _settings_connection_notify_flags, self); + _set_activation_type (self, NM_ACTIVATION_TYPE_MANAGED); + nm_device_reapply_settings_immediately (nm_active_connection_get_device (self)); } /*****************************************************************************/ @@ -1058,6 +1108,7 @@ set_property (GObject *object, guint prop_id, const char *tmp; NMSettingsConnection *con; NMConnection *acon; + int i; switch (prop_id) { case PROP_INT_SETTINGS_CONNECTION: @@ -1082,6 +1133,15 @@ set_property (GObject *object, guint prop_id, case PROP_INT_MASTER: nm_active_connection_set_master (self, g_value_get_object (value)); break; + case PROP_INT_ACTIVATION_TYPE: + /* construct-only */ + i = g_value_get_int (value); + if (!NM_IN_SET (i, NM_ACTIVATION_TYPE_MANAGED, + NM_ACTIVATION_TYPE_ASSUME, + NM_ACTIVATION_TYPE_EXTERNAL)) + g_return_if_reached (); + priv->activation_type = (NMActivationType) i; + break; case PROP_SPECIFIC_OBJECT: tmp = g_value_get_string (value); /* NM uses "/" to mean NULL */ @@ -1117,6 +1177,7 @@ nm_active_connection_init (NMActiveConnection *self) _LOGT ("creating"); + priv->activation_type = NM_ACTIVATION_TYPE_MANAGED; priv->version_id = _version_id_new (); } @@ -1128,15 +1189,16 @@ constructed (GObject *object) G_OBJECT_CLASS (nm_active_connection_parent_class)->constructed (object); - if (!priv->applied_connection && priv->settings_connection) { - priv->applied_connection = - nm_simple_connection_new_clone ((NMConnection *) priv->settings_connection); - } + if (!priv->applied_connection && priv->settings_connection) + priv->applied_connection = nm_simple_connection_new_clone (NM_CONNECTION (priv->settings_connection)); if (priv->applied_connection) nm_connection_clear_secrets (priv->applied_connection); - _LOGD ("constructed (%s, version-id %llu)", G_OBJECT_TYPE_NAME (self), (unsigned long long) priv->version_id); + _LOGD ("constructed (%s, version-id %llu, type %s)", + G_OBJECT_TYPE_NAME (self), + (unsigned long long) priv->version_id, + nm_activation_type_to_string (priv->activation_type)); g_return_if_fail (priv->subject); } @@ -1321,6 +1383,15 @@ nm_active_connection_class_init (NMActiveConnectionClass *ac_class) FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_INT_ACTIVATION_TYPE] = + g_param_spec_int (NM_ACTIVE_CONNECTION_INT_ACTIVATION_TYPE, "", "", + NM_ACTIVATION_TYPE_MANAGED, + NM_ACTIVATION_TYPE_EXTERNAL, + NM_ACTIVATION_TYPE_MANAGED, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); signals[DEVICE_CHANGED] = diff --git a/src/nm-active-connection.h b/src/nm-active-connection.h index d87a30b540..ba231c3077 100644 --- a/src/nm-active-connection.h +++ b/src/nm-active-connection.h @@ -55,6 +55,7 @@ #define NM_ACTIVE_CONNECTION_INT_SUBJECT "int-subject" #define NM_ACTIVE_CONNECTION_INT_MASTER "int-master" #define NM_ACTIVE_CONNECTION_INT_MASTER_READY "int-master-ready" +#define NM_ACTIVE_CONNECTION_INT_ACTIVATION_TYPE "int-activation-type" /* Internal signals*/ #define NM_ACTIVE_CONNECTION_DEVICE_CHANGED "device-changed" @@ -158,10 +159,7 @@ void nm_active_connection_set_master (NMActiveConnection *self, void nm_active_connection_set_parent (NMActiveConnection *self, NMActiveConnection *parent); -void nm_active_connection_set_assumed (NMActiveConnection *self, - gboolean assumed); - -gboolean nm_active_connection_get_assumed (NMActiveConnection *self); +NMActivationType nm_active_connection_get_activation_type (NMActiveConnection *self); void nm_active_connection_clear_secrets (NMActiveConnection *self); diff --git a/src/nm-checkpoint.c b/src/nm-checkpoint.c index c6b494624a..927dc859d2 100644 --- a/src/nm-checkpoint.c +++ b/src/nm-checkpoint.c @@ -281,6 +281,7 @@ activate: NULL, device, subject, + NM_ACTIVATION_TYPE_MANAGED, &local_error)) { _LOGW ("rollback: reactivation of connection %s/%s failed: %s", nm_connection_get_id ((NMConnection *) connection), diff --git a/src/nm-connectivity.c b/src/nm-connectivity.c index a33ec680eb..ac13b2ca85 100644 --- a/src/nm-connectivity.c +++ b/src/nm-connectivity.c @@ -105,8 +105,7 @@ update_state (NMConnectivity *self, NMConnectivityState state) priv->state = state; _notify (self, PROP_STATE); - /* Notify dispatcher scripts of a connectivity state change */ - nm_dispatcher_call_connectivity (DISPATCHER_ACTION_CONNECTIVITY_CHANGE, state); + nm_dispatcher_call_connectivity (state, NULL, NULL, NULL); } } diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c index ead86d4775..adef77e296 100644 --- a/src/nm-core-utils.c +++ b/src/nm-core-utils.c @@ -4339,3 +4339,12 @@ nm_utils_format_con_diff_for_audit (GHashTable *diff) return g_string_free (str, FALSE); } + +/*****************************************************************************/ + +NM_UTILS_LOOKUP_STR_DEFINE (nm_activation_type_to_string, NMActivationType, + NM_UTILS_LOOKUP_DEFAULT_WARN ("(unknown)"), + NM_UTILS_LOOKUP_STR_ITEM (NM_ACTIVATION_TYPE_MANAGED, "managed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_ACTIVATION_TYPE_ASSUME, "assume"), + NM_UTILS_LOOKUP_STR_ITEM (NM_ACTIVATION_TYPE_EXTERNAL, "external"), +) diff --git a/src/nm-core-utils.h b/src/nm-core-utils.h index b0dbe9bf06..779ba90ab9 100644 --- a/src/nm-core-utils.h +++ b/src/nm-core-utils.h @@ -472,4 +472,10 @@ char **nm_utils_read_plugin_paths (const char *dirname, const char *prefix); char *nm_utils_format_con_diff_for_audit (GHashTable *diff); +/*****************************************************************************/ + +const char *nm_activation_type_to_string (NMActivationType activation_type); + +/*****************************************************************************/ + #endif /* __NM_CORE_UTILS_H__ */ diff --git a/src/nm-dispatcher.c b/src/nm-dispatcher.c index 6c0c4bb44d..1bb26e1c45 100644 --- a/src/nm-dispatcher.c +++ b/src/nm-dispatcher.c @@ -21,14 +21,16 @@ #include "nm-default.h" +#include "nm-dispatcher.h" + #include <string.h> #include <errno.h> -#include "nm-dispatcher.h" #include "nm-dispatcher-api.h" #include "NetworkManagerUtils.h" #include "nm-utils.h" #include "nm-connectivity.h" +#include "nm-act-request.h" #include "devices/nm-device.h" #include "nm-dhcp4-config.h" #include "nm-dhcp6-config.h" @@ -70,14 +72,14 @@ static Monitor monitors[3] = { }; static const Monitor* -_get_monitor_by_action (DispatcherAction action) +_get_monitor_by_action (NMDispatcherAction action) { switch (action) { - case DISPATCHER_ACTION_PRE_UP: - case DISPATCHER_ACTION_VPN_PRE_UP: + case NM_DISPATCHER_ACTION_PRE_UP: + case NM_DISPATCHER_ACTION_VPN_PRE_UP: return &monitors[MONITOR_INDEX_PRE_UP]; - case DISPATCHER_ACTION_PRE_DOWN: - case DISPATCHER_ACTION_VPN_PRE_DOWN: + case NM_DISPATCHER_ACTION_PRE_DOWN: + case NM_DISPATCHER_ACTION_VPN_PRE_DOWN: return &monitors[MONITOR_INDEX_PRE_DOWN]; default: return &monitors[MONITOR_INDEX_DEFAULT]; @@ -311,9 +313,9 @@ fill_vpn_props (NMProxyConfig *proxy_config, } typedef struct { - DispatcherAction action; + NMDispatcherAction action; guint request_id; - DispatcherFunc callback; + NMDispatcherFunc callback; gpointer user_data; guint idle_id; } DispatchInfo; @@ -362,7 +364,7 @@ dispatch_result_to_string (DispatchResult result) } static void -dispatcher_results_process (guint request_id, DispatcherAction action, GVariantIter *results) +dispatcher_results_process (guint request_id, NMDispatcherAction action, GVariantIter *results) { const char *script, *err; guint32 result; @@ -440,22 +442,22 @@ dispatcher_done_cb (GObject *proxy, GAsyncResult *result, gpointer user_data) } static const char *action_table[] = { - [DISPATCHER_ACTION_HOSTNAME] = NMD_ACTION_HOSTNAME, - [DISPATCHER_ACTION_PRE_UP] = NMD_ACTION_PRE_UP, - [DISPATCHER_ACTION_UP] = NMD_ACTION_UP, - [DISPATCHER_ACTION_PRE_DOWN] = NMD_ACTION_PRE_DOWN, - [DISPATCHER_ACTION_DOWN] = NMD_ACTION_DOWN, - [DISPATCHER_ACTION_VPN_PRE_UP] = NMD_ACTION_VPN_PRE_UP, - [DISPATCHER_ACTION_VPN_UP] = NMD_ACTION_VPN_UP, - [DISPATCHER_ACTION_VPN_PRE_DOWN] = NMD_ACTION_VPN_PRE_DOWN, - [DISPATCHER_ACTION_VPN_DOWN] = NMD_ACTION_VPN_DOWN, - [DISPATCHER_ACTION_DHCP4_CHANGE] = NMD_ACTION_DHCP4_CHANGE, - [DISPATCHER_ACTION_DHCP6_CHANGE] = NMD_ACTION_DHCP6_CHANGE, - [DISPATCHER_ACTION_CONNECTIVITY_CHANGE] = NMD_ACTION_CONNECTIVITY_CHANGE + [NM_DISPATCHER_ACTION_HOSTNAME] = NMD_ACTION_HOSTNAME, + [NM_DISPATCHER_ACTION_PRE_UP] = NMD_ACTION_PRE_UP, + [NM_DISPATCHER_ACTION_UP] = NMD_ACTION_UP, + [NM_DISPATCHER_ACTION_PRE_DOWN] = NMD_ACTION_PRE_DOWN, + [NM_DISPATCHER_ACTION_DOWN] = NMD_ACTION_DOWN, + [NM_DISPATCHER_ACTION_VPN_PRE_UP] = NMD_ACTION_VPN_PRE_UP, + [NM_DISPATCHER_ACTION_VPN_UP] = NMD_ACTION_VPN_UP, + [NM_DISPATCHER_ACTION_VPN_PRE_DOWN] = NMD_ACTION_VPN_PRE_DOWN, + [NM_DISPATCHER_ACTION_VPN_DOWN] = NMD_ACTION_VPN_DOWN, + [NM_DISPATCHER_ACTION_DHCP4_CHANGE] = NMD_ACTION_DHCP4_CHANGE, + [NM_DISPATCHER_ACTION_DHCP6_CHANGE] = NMD_ACTION_DHCP6_CHANGE, + [NM_DISPATCHER_ACTION_CONNECTIVITY_CHANGE] = NMD_ACTION_CONNECTIVITY_CHANGE }; static const char * -action_to_string (DispatcherAction action) +action_to_string (NMDispatcherAction action) { g_assert ((gsize) action < G_N_ELEMENTS (action_table)); return action_table[action]; @@ -474,17 +476,18 @@ dispatcher_idle_cb (gpointer user_data) } static gboolean -_dispatcher_call (DispatcherAction action, +_dispatcher_call (NMDispatcherAction action, gboolean blocking, + NMDevice *device, NMSettingsConnection *settings_connection, NMConnection *applied_connection, - NMDevice *device, + gboolean activation_type_external, NMConnectivityState connectivity_state, const char *vpn_iface, NMProxyConfig *vpn_proxy_config, NMIP4Config *vpn_ip4_config, NMIP6Config *vpn_ip6_config, - DispatcherFunc callback, + NMDispatcherFunc callback, gpointer user_data, guint *out_call_id) { @@ -517,8 +520,8 @@ _dispatcher_call (DispatcherAction action, _ensure_requests (); /* All actions except 'hostname' and 'connectivity-change' require a device */ - if ( action == DISPATCHER_ACTION_HOSTNAME - || action == DISPATCHER_ACTION_CONNECTIVITY_CHANGE) { + if ( action == NM_DISPATCHER_ACTION_HOSTNAME + || action == NM_DISPATCHER_ACTION_CONNECTIVITY_CHANGE) { _LOGD ("(%u) dispatching action '%s'%s", reqid, action_to_string (action), blocking @@ -573,7 +576,7 @@ _dispatcher_call (DispatcherAction action, NMD_CONNECTION_PROPS_FILENAME, g_variant_new_string (filename)); } - if (nm_settings_connection_get_nm_generated_assumed (settings_connection)) { + if (activation_type_external) { g_variant_builder_add (&connection_props, "{sv}", NMD_CONNECTION_PROPS_EXTERNAL, g_variant_new_boolean (TRUE)); @@ -589,8 +592,8 @@ _dispatcher_call (DispatcherAction action, g_variant_builder_init (&vpn_ip6_props, G_VARIANT_TYPE_VARDICT); /* hostname and connectivity-change actions don't send device data */ - if ( action != DISPATCHER_ACTION_HOSTNAME - && action != DISPATCHER_ACTION_CONNECTIVITY_CHANGE) { + if ( action != NM_DISPATCHER_ACTION_HOSTNAME + && action != NM_DISPATCHER_ACTION_CONNECTIVITY_CHANGE) { fill_device_props (device, &device_props, &device_proxy_props, @@ -694,41 +697,75 @@ done: } /** - * nm_dispatcher_call: - * @action: the %DispatcherAction - * @settings_connection: the #NMSettingsConnection the action applies to - * @applied_connection: the currently applied connection + * nm_dispatcher_call_hostname: + * @callback: a caller-supplied callback to execute when done + * @user_data: caller-supplied pointer passed to @callback + * @out_call_id: on success, a call identifier which can be passed to + * nm_dispatcher_call_cancel() + * + * This method always invokes the dispatcher action asynchronously. + * + * Returns: %TRUE if the action was dispatched, %FALSE on failure + */ +gboolean +nm_dispatcher_call_hostname (NMDispatcherFunc callback, + gpointer user_data, + guint *out_call_id) +{ + return _dispatcher_call (NM_DISPATCHER_ACTION_HOSTNAME, FALSE, + NULL, NULL, NULL, FALSE, + NM_CONNECTIVITY_UNKNOWN, + NULL, NULL, NULL, NULL, + callback, user_data, out_call_id); +} + +/** + * nm_dispatcher_call_device: + * @action: the %NMDispatcherAction * @device: the #NMDevice the action applies to + * @act_request: the #NMActRequest for the action. If %NULL, use the + * current request of the device. * @callback: a caller-supplied callback to execute when done * @user_data: caller-supplied pointer passed to @callback * @out_call_id: on success, a call identifier which can be passed to * nm_dispatcher_call_cancel() * - * This method always invokes the dispatcher action asynchronously. To ignore + * This method always invokes the device dispatcher action asynchronously. To ignore * the result, pass %NULL to @callback. * * Returns: %TRUE if the action was dispatched, %FALSE on failure */ gboolean -nm_dispatcher_call (DispatcherAction action, - NMSettingsConnection *settings_connection, - NMConnection *applied_connection, - NMDevice *device, - DispatcherFunc callback, - gpointer user_data, - guint *out_call_id) +nm_dispatcher_call_device (NMDispatcherAction action, + NMDevice *device, + NMActRequest *act_request, + NMDispatcherFunc callback, + gpointer user_data, + guint *out_call_id) { - return _dispatcher_call (action, FALSE, settings_connection, applied_connection, device, - NM_CONNECTIVITY_UNKNOWN, NULL, NULL, NULL, NULL, + nm_assert (NM_IS_DEVICE (device)); + if (!act_request) { + act_request = nm_device_get_act_request (device); + if (!act_request) + return FALSE; + } + nm_assert (NM_IN_SET (nm_active_connection_get_device (NM_ACTIVE_CONNECTION (act_request)), NULL, device)); + return _dispatcher_call (action, FALSE, + device, + nm_act_request_get_settings_connection (act_request), + nm_act_request_get_applied_connection (act_request), + nm_active_connection_get_activation_type (NM_ACTIVE_CONNECTION (act_request)) == NM_ACTIVATION_TYPE_EXTERNAL, + NM_CONNECTIVITY_UNKNOWN, + NULL, NULL, NULL, NULL, callback, user_data, out_call_id); } /** - * nm_dispatcher_call_sync(): - * @action: the %DispatcherAction - * @settings_connection: the #NMSettingsConnection the action applies to - * @applied_connection: the currently applied connection + * nm_dispatcher_call_device_sync(): + * @action: the %NMDispatcherAction * @device: the #NMDevice the action applies to + * @act_request: the #NMActRequest for the action. If %NULL, use the + * current request of the device. * * This method always invokes the dispatcher action synchronously and it may * take a long time to return. @@ -736,18 +773,30 @@ nm_dispatcher_call (DispatcherAction action, * Returns: %TRUE if the action was dispatched, %FALSE on failure */ gboolean -nm_dispatcher_call_sync (DispatcherAction action, - NMSettingsConnection *settings_connection, - NMConnection *applied_connection, - NMDevice *device) +nm_dispatcher_call_device_sync (NMDispatcherAction action, + NMDevice *device, + NMActRequest *act_request) { - return _dispatcher_call (action, TRUE, settings_connection, applied_connection, device, - NM_CONNECTIVITY_UNKNOWN, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + nm_assert (NM_IS_DEVICE (device)); + if (!act_request) { + act_request = nm_device_get_act_request (device); + if (!act_request) + return FALSE; + } + nm_assert (NM_IN_SET (nm_active_connection_get_device (NM_ACTIVE_CONNECTION (act_request)), NULL, device)); + return _dispatcher_call (action, TRUE, + device, + nm_act_request_get_settings_connection (act_request), + nm_act_request_get_applied_connection (act_request), + nm_active_connection_get_activation_type (NM_ACTIVE_CONNECTION (act_request)) == NM_ACTIVATION_TYPE_EXTERNAL, + NM_CONNECTIVITY_UNKNOWN, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL); } /** * nm_dispatcher_call_vpn(): - * @action: the %DispatcherAction + * @action: the %NMDispatcherAction * @settings_connection: the #NMSettingsConnection the action applies to * @applied_connection: the currently applied connection * @parent_device: the parent #NMDevice of the VPN connection @@ -766,7 +815,7 @@ nm_dispatcher_call_sync (DispatcherAction action, * Returns: %TRUE if the action was dispatched, %FALSE on failure */ gboolean -nm_dispatcher_call_vpn (DispatcherAction action, +nm_dispatcher_call_vpn (NMDispatcherAction action, NMSettingsConnection *settings_connection, NMConnection *applied_connection, NMDevice *parent_device, @@ -774,18 +823,23 @@ nm_dispatcher_call_vpn (DispatcherAction action, NMProxyConfig *vpn_proxy_config, NMIP4Config *vpn_ip4_config, NMIP6Config *vpn_ip6_config, - DispatcherFunc callback, + NMDispatcherFunc callback, gpointer user_data, guint *out_call_id) { - return _dispatcher_call (action, FALSE, settings_connection, applied_connection, - parent_device, NM_CONNECTIVITY_UNKNOWN, vpn_iface, vpn_proxy_config, - vpn_ip4_config, vpn_ip6_config, callback, user_data, out_call_id); + return _dispatcher_call (action, FALSE, + parent_device, + settings_connection, + applied_connection, + FALSE, + NM_CONNECTIVITY_UNKNOWN, + vpn_iface, vpn_proxy_config, vpn_ip4_config, vpn_ip6_config, + callback, user_data, out_call_id); } /** * nm_dispatcher_call_vpn_sync(): - * @action: the %DispatcherAction + * @action: the %NMDispatcherAction * @settings_connection: the #NMSettingsConnection the action applies to * @applied_connection: the currently applied connection * @parent_device: the parent #NMDevice of the VPN connection @@ -800,7 +854,7 @@ nm_dispatcher_call_vpn (DispatcherAction action, * Returns: %TRUE if the action was dispatched, %FALSE on failure */ gboolean -nm_dispatcher_call_vpn_sync (DispatcherAction action, +nm_dispatcher_call_vpn_sync (NMDispatcherAction action, NMSettingsConnection *settings_connection, NMConnection *applied_connection, NMDevice *parent_device, @@ -809,26 +863,39 @@ nm_dispatcher_call_vpn_sync (DispatcherAction action, NMIP4Config *vpn_ip4_config, NMIP6Config *vpn_ip6_config) { - return _dispatcher_call (action, TRUE, settings_connection, applied_connection, - parent_device, NM_CONNECTIVITY_UNKNOWN, vpn_iface, vpn_proxy_config, - vpn_ip4_config, vpn_ip6_config, NULL, NULL, NULL); + return _dispatcher_call (action, TRUE, + parent_device, + settings_connection, + applied_connection, + FALSE, + NM_CONNECTIVITY_UNKNOWN, + vpn_iface, vpn_proxy_config, vpn_ip4_config, vpn_ip6_config, + NULL, NULL, NULL); } /** * nm_dispatcher_call_connectivity(): - * @action: the %DispatcherAction * @connectivity_state: the #NMConnectivityState value + * @callback: a caller-supplied callback to execute when done + * @user_data: caller-supplied pointer passed to @callback + * @out_call_id: on success, a call identifier which can be passed to + * nm_dispatcher_call_cancel() * * This method does not block the caller. * * Returns: %TRUE if the action was dispatched, %FALSE on failure */ gboolean -nm_dispatcher_call_connectivity (DispatcherAction action, - NMConnectivityState connectivity_state) +nm_dispatcher_call_connectivity (NMConnectivityState connectivity_state, + NMDispatcherFunc callback, + gpointer user_data, + guint *out_call_id) { - return _dispatcher_call (action, FALSE, NULL, NULL, NULL, connectivity_state, - NULL, NULL, NULL, NULL, NULL, NULL, NULL); + return _dispatcher_call (NM_DISPATCHER_ACTION_CONNECTIVITY_CHANGE, FALSE, + NULL, NULL, NULL, FALSE, + connectivity_state, + NULL, NULL, NULL, NULL, + callback, user_data, out_call_id); } void diff --git a/src/nm-dispatcher.h b/src/nm-dispatcher.h index 7ea1a6b8ae..4448e8173f 100644 --- a/src/nm-dispatcher.h +++ b/src/nm-dispatcher.h @@ -19,44 +19,44 @@ * Copyright (C) 2005 - 2008 Novell, Inc. */ -#ifndef __NETWORKMANAGER_DISPATCHER_H__ -#define __NETWORKMANAGER_DISPATCHER_H__ - -#include <stdio.h> +#ifndef __NM_DISPATCHER_H__ +#define __NM_DISPATCHER_H__ #include "nm-connection.h" typedef enum { - DISPATCHER_ACTION_HOSTNAME, - DISPATCHER_ACTION_PRE_UP, - DISPATCHER_ACTION_UP, - DISPATCHER_ACTION_PRE_DOWN, - DISPATCHER_ACTION_DOWN, - DISPATCHER_ACTION_VPN_PRE_UP, - DISPATCHER_ACTION_VPN_UP, - DISPATCHER_ACTION_VPN_PRE_DOWN, - DISPATCHER_ACTION_VPN_DOWN, - DISPATCHER_ACTION_DHCP4_CHANGE, - DISPATCHER_ACTION_DHCP6_CHANGE, - DISPATCHER_ACTION_CONNECTIVITY_CHANGE -} DispatcherAction; + NM_DISPATCHER_ACTION_HOSTNAME, + NM_DISPATCHER_ACTION_PRE_UP, + NM_DISPATCHER_ACTION_UP, + NM_DISPATCHER_ACTION_PRE_DOWN, + NM_DISPATCHER_ACTION_DOWN, + NM_DISPATCHER_ACTION_VPN_PRE_UP, + NM_DISPATCHER_ACTION_VPN_UP, + NM_DISPATCHER_ACTION_VPN_PRE_DOWN, + NM_DISPATCHER_ACTION_VPN_DOWN, + NM_DISPATCHER_ACTION_DHCP4_CHANGE, + NM_DISPATCHER_ACTION_DHCP6_CHANGE, + NM_DISPATCHER_ACTION_CONNECTIVITY_CHANGE +} NMDispatcherAction; + +typedef void (*NMDispatcherFunc) (guint call_id, gpointer user_data); -typedef void (*DispatcherFunc) (guint call_id, gpointer user_data); +gboolean nm_dispatcher_call_hostname (NMDispatcherFunc callback, + gpointer user_data, + guint *out_call_id); -gboolean nm_dispatcher_call (DispatcherAction action, - NMSettingsConnection *settings_connection, - NMConnection *applied_connection, - NMDevice *device, - DispatcherFunc callback, - gpointer user_data, - guint *out_call_id); +gboolean nm_dispatcher_call_device (NMDispatcherAction action, + NMDevice *device, + NMActRequest *act_request, + NMDispatcherFunc callback, + gpointer user_data, + guint *out_call_id); -gboolean nm_dispatcher_call_sync (DispatcherAction action, - NMSettingsConnection *settings_connection, - NMConnection *applied_connection, - NMDevice *device); +gboolean nm_dispatcher_call_device_sync (NMDispatcherAction action, + NMDevice *device, + NMActRequest *act_request); -gboolean nm_dispatcher_call_vpn (DispatcherAction action, +gboolean nm_dispatcher_call_vpn (NMDispatcherAction action, NMSettingsConnection *settings_connection, NMConnection *applied_connection, NMDevice *parent_device, @@ -64,11 +64,11 @@ gboolean nm_dispatcher_call_vpn (DispatcherAction action, NMProxyConfig *vpn_proxy_config, NMIP4Config *vpn_ip4_config, NMIP6Config *vpn_ip6_config, - DispatcherFunc callback, + NMDispatcherFunc callback, gpointer user_data, guint *out_call_id); -gboolean nm_dispatcher_call_vpn_sync (DispatcherAction action, +gboolean nm_dispatcher_call_vpn_sync (NMDispatcherAction action, NMSettingsConnection *settings_connection, NMConnection *applied_connection, NMDevice *parent_device, @@ -77,11 +77,14 @@ gboolean nm_dispatcher_call_vpn_sync (DispatcherAction action, NMIP4Config *vpn_ip4_config, NMIP6Config *vpn_ip6_config); -gboolean nm_dispatcher_call_connectivity (DispatcherAction action, - NMConnectivityState state); +gboolean nm_dispatcher_call_connectivity (NMConnectivityState state, + NMDispatcherFunc callback, + gpointer user_data, + guint *out_call_id); + void nm_dispatcher_call_cancel (guint call_id); void nm_dispatcher_init (void); -#endif /* __NETWORKMANAGER_DISPATCHER_H__ */ +#endif /* __NM_DISPATCHER_H__ */ diff --git a/src/nm-manager.c b/src/nm-manager.c index b1c6c479bd..649f8464fd 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -67,6 +67,7 @@ static NMActiveConnection *_new_active_connection (NMManager *self, const char *specific_object, NMDevice *device, NMAuthSubject *subject, + NMActivationType activation_type, GError **error); static void policy_activating_device_changed (GObject *object, GParamSpec *pspec, gpointer user_data); @@ -270,20 +271,20 @@ active_connection_remove (NMManager *self, NMActiveConnection *active) 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) - && (connection = nm_active_connection_get_settings_connection (active)) - && nm_settings_connection_get_nm_generated_assumed (connection)) + if ( (connection = nm_active_connection_get_settings_connection (active)) + && nm_settings_connection_get_volatile (connection)) g_object_ref (connection); else connection = NULL; nm_exported_object_clear_and_unexport (&active); - if ( connection - && nm_settings_has_connection (priv->settings, connection)) { - _LOGD (LOGD_DEVICE, "assumed connection disconnected. Deleting generated connection '%s' (%s)", - nm_settings_connection_get_id (connection), nm_settings_connection_get_uuid (connection)); - nm_settings_connection_delete (NM_SETTINGS_CONNECTION (connection), NULL, NULL); + if (connection) { + if (nm_settings_has_connection (priv->settings, connection)) { + _LOGD (LOGD_DEVICE, "assumed connection disconnected. Deleting generated connection '%s' (%s)", + nm_settings_connection_get_id (connection), nm_settings_connection_get_uuid (connection)); + nm_settings_connection_delete (connection, NULL, NULL); + } g_object_unref (connection); } } @@ -395,46 +396,60 @@ nm_manager_get_active_connections (NMManager *manager) } static NMActiveConnection * -find_ac_for_connection (NMManager *manager, NMConnection *connection) +active_connection_find_first (NMManager *self, + NMSettingsConnection *settings_connection, + const char *uuid, + NMActiveConnectionState max_state) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); + NMManagerPrivate *priv; GSList *iter; - const char *uuid = NULL; - gboolean is_settings_connection; - is_settings_connection = NM_IS_SETTINGS_CONNECTION (connection); + g_return_val_if_fail (NM_IS_MANAGER (self), NULL); + g_return_val_if_fail (!settings_connection || NM_IS_SETTINGS_CONNECTION (settings_connection), NULL); - if (!is_settings_connection) - uuid = nm_connection_get_uuid (connection); + priv = NM_MANAGER_GET_PRIVATE (self); for (iter = priv->active_connections; iter; iter = iter->next) { NMActiveConnection *ac = iter->data; NMSettingsConnection *con; con = nm_active_connection_get_settings_connection (ac); - - /* depending on whether we have a NMSettingsConnection or a NMConnection, - * we lookup by UUID or by reference. */ - if (is_settings_connection) { - if (con != (NMSettingsConnection *) connection) - continue; - } else { - if (strcmp (uuid, nm_connection_get_uuid (NM_CONNECTION (con))) != 0) - continue; - } - if (nm_active_connection_get_state (ac) < NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) - return ac; + if (settings_connection && con != settings_connection) + continue; + if (uuid && !nm_streq0 (uuid, nm_connection_get_uuid (NM_CONNECTION (con)))) + continue; + if (nm_active_connection_get_state (ac) > max_state) + continue; + return ac; } return NULL; } +static NMActiveConnection * +active_connection_find_first_by_connection (NMManager *self, + NMConnection *connection) +{ + gboolean is_settings_connection; + + nm_assert (NM_IS_MANAGER (self)); + nm_assert (NM_IS_CONNECTION (connection)); + + is_settings_connection = NM_IS_SETTINGS_CONNECTION (connection); + /* Depending on whether connection is a settings connection, + * either lookup by object-identity of @connection, or compare the UUID */ + return active_connection_find_first (self, + is_settings_connection ? NM_SETTINGS_CONNECTION (connection) : NULL, + is_settings_connection ? NULL : nm_connection_get_uuid (connection), + NM_ACTIVE_CONNECTION_STATE_DEACTIVATING); +} + static gboolean _get_activatable_connections_filter (NMSettings *settings, NMSettingsConnection *connection, gpointer user_data) { - return !find_ac_for_connection (user_data, NM_CONNECTION (connection)); + return !active_connection_find_first (user_data, connection, NULL, NM_ACTIVE_CONNECTION_STATE_DEACTIVATING); } /* Filter out connections that are already active. @@ -800,13 +815,17 @@ find_best_device_state (NMManager *manager, gboolean *force_connectivity_check) } break; case NM_ACTIVE_CONNECTION_STATE_ACTIVATING: - if (!nm_active_connection_get_assumed (ac)) { + if (!NM_IN_SET (nm_active_connection_get_activation_type (ac), + NM_ACTIVATION_TYPE_EXTERNAL, + NM_ACTIVATION_TYPE_ASSUME)) { if (best_state != NM_STATE_CONNECTED_GLOBAL) best_state = NM_STATE_CONNECTING; } break; case NM_ACTIVE_CONNECTION_STATE_DEACTIVATING: - if (!nm_active_connection_get_assumed (ac)) { + if (!NM_IN_SET (nm_active_connection_get_activation_type (ac), + NM_ACTIVATION_TYPE_EXTERNAL, + NM_ACTIVATION_TYPE_ASSUME)) { if (best_state < NM_STATE_DISCONNECTING) best_state = NM_STATE_DISCONNECTING; } @@ -1019,8 +1038,10 @@ remove_device (NMManager *self, if (unmanage) { if (quitting) nm_device_set_unmanaged_by_quitting (device); - else + else { + nm_device_sys_iface_state_set (device, NM_DEVICE_SYS_IFACE_STATE_REMOVED); nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_PLATFORM_INIT, TRUE, NM_DEVICE_STATE_REASON_REMOVED); + } } else if (quitting && nm_config_get_configure_and_quit (priv->config)) { nm_device_spawn_iface_helper (device); } @@ -1696,9 +1717,6 @@ done: static gboolean match_connection_filter (NMConnection *connection, gpointer user_data) { - if (nm_settings_connection_get_nm_generated_assumed (NM_SETTINGS_CONNECTION (connection))) - return FALSE; - return nm_device_check_connection_compatible (NM_DEVICE (user_data), connection); } @@ -1706,22 +1724,27 @@ match_connection_filter (NMConnection *connection, gpointer user_data) * get_existing_connection: * @manager: #NMManager instance * @device: #NMDevice instance + * @assume_connection_uuid: if present, try to assume a connection with this + * UUID. If no uuid is given or no matching connection is found, we + * only do external activation. * @out_generated: (allow-none): return TRUE, if the connection was generated. * * Returns: a #NMSettingsConnection to be assumed by the device, or %NULL if * the device does not support assuming existing connections. */ static NMSettingsConnection * -get_existing_connection (NMManager *self, NMDevice *device, gboolean *out_generated) +get_existing_connection (NMManager *self, + NMDevice *device, + const char *assume_connection_uuid, + gboolean *out_generated) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - gs_free_slist GSList *connections = NULL; NMConnection *connection = NULL; - NMSettingsConnection *matched; NMSettingsConnection *added = NULL; GError *error = NULL; NMDevice *master = NULL; int ifindex = nm_device_get_ifindex (device); + NMSettingsConnection *matched; if (out_generated) *out_generated = FALSE; @@ -1765,30 +1788,29 @@ get_existing_connection (NMManager *self, NMDevice *device, gboolean *out_genera * When no configured connection matches the generated connection, we keep * the generated connection instead. */ - { - gs_free NMSettingsConnection **cons = NULL; - guint i, len; - - /* XXX: this code will go away soon. Copy the array over to a GSList - * and don't bother for now. */ - cons = nm_manager_get_activatable_connections (self, &len, FALSE); - for (i = len; i > 0; ) - connections = g_slist_prepend (connections, cons[--i]); - connections = g_slist_sort (connections, (GCompareFunc) nm_settings_connection_cmp_timestamp); - } - matched = NM_SETTINGS_CONNECTION (nm_utils_match_connection (connections, - connection, - nm_device_has_carrier (device), - nm_device_get_ip4_route_metric (device), - nm_device_get_ip6_route_metric (device), - match_connection_filter, - device)); - if (matched) { - _LOGI (LOGD_DEVICE, "(%s): found matching connection '%s'", - nm_device_get_iface (device), - nm_settings_connection_get_id (matched)); - g_object_unref (connection); - return matched; + if ( assume_connection_uuid + && (matched = nm_settings_get_connection_by_uuid (priv->settings, assume_connection_uuid)) + && !active_connection_find_first (self, matched, NULL, + NM_ACTIVE_CONNECTION_STATE_DEACTIVATING)) { + NMConnection *const connections[] = { + NM_CONNECTION (matched), + NULL, + }; + + matched = NM_SETTINGS_CONNECTION (nm_utils_match_connection (connections, + connection, + nm_device_has_carrier (device), + nm_device_get_ip4_route_metric (device), + nm_device_get_ip6_route_metric (device), + match_connection_filter, + device)); + if (matched) { + _LOGI (LOGD_DEVICE, "(%s): found matching connection '%s'", + nm_device_get_iface (device), + nm_settings_connection_get_id (matched)); + g_object_unref (connection); + return matched; + } } _LOGD (LOGD_DEVICE, "(%s): generated connection '%s'", @@ -1799,7 +1821,7 @@ get_existing_connection (NMManager *self, NMDevice *device, gboolean *out_genera if (added) { nm_settings_connection_set_flags (NM_SETTINGS_CONNECTION (added), NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED | - NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED_ASSUMED, + NM_SETTINGS_CONNECTION_FLAGS_VOLATILE, TRUE); if (out_generated) *out_generated = TRUE; @@ -1816,54 +1838,13 @@ get_existing_connection (NMManager *self, NMDevice *device, gboolean *out_genera } static gboolean -assume_connection (NMManager *self, NMDevice *device, NMSettingsConnection *connection) -{ - NMActiveConnection *active, *master_ac; - NMAuthSubject *subject; - GError *error = NULL; - - _LOGD (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_val_if_fail (nm_device_get_state (device) >= NM_DEVICE_STATE_DISCONNECTED, FALSE); - - subject = nm_auth_subject_new_internal (); - active = _new_active_connection (self, NM_CONNECTION (connection), NULL, NULL, device, subject, &error); - g_object_unref (subject); - - if (!active) { - _LOGW (LOGD_DEVICE, "assumed connection %s failed to activate: %s", - nm_connection_get_path (NM_CONNECTION (connection)), - error->message); - 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, NM_CONNECTION (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_exported_object_export (NM_EXPORTED_OBJECT (active)); - active_connection_add (self, active); - nm_device_queue_activation (device, NM_ACT_REQUEST (active)); - g_object_unref (active); - - return TRUE; -} - -static gboolean -recheck_assume_connection (NMManager *self, NMDevice *device) +recheck_assume_connection (NMManager *self, + NMDevice *device, + const char *assume_connection_uuid) { NMSettingsConnection *connection; - gboolean was_unmanaged = FALSE, success, generated = FALSE; + gboolean was_unmanaged = FALSE; + gboolean generated = FALSE; NMDeviceState state; g_return_val_if_fail (NM_IS_MANAGER (self), FALSE); @@ -1879,43 +1860,90 @@ recheck_assume_connection (NMManager *self, NMDevice *device) if (state > NM_DEVICE_STATE_DISCONNECTED) return FALSE; - connection = get_existing_connection (self, device, &generated); + if (nm_device_sys_iface_state_get (device) != NM_DEVICE_SYS_IFACE_STATE_EXTERNAL) + return FALSE; + + connection = get_existing_connection (self, device, assume_connection_uuid, &generated); if (!connection) { _LOGD (LOGD_DEVICE, "(%s): can't assume; no connection", nm_device_get_iface (device)); return FALSE; } + _LOGD (LOGD_DEVICE, "(%s): will attempt to assume connection", + nm_device_get_iface (device)); + + if (!generated) + nm_device_sys_iface_state_set (device, NM_DEVICE_SYS_IFACE_STATE_ASSUME); + + /* Move device to DISCONNECTED to activate the connection */ if (state == NM_DEVICE_STATE_UNMANAGED) { was_unmanaged = TRUE; nm_device_state_changed (device, NM_DEVICE_STATE_UNAVAILABLE, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); } + 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); + } - success = assume_connection (self, device, connection); - if (!success) { - if (was_unmanaged) { - nm_device_state_changed (device, - NM_DEVICE_STATE_UNAVAILABLE, - NM_DEVICE_STATE_REASON_CONFIG_FAILED); - } + g_return_val_if_fail (nm_device_get_state (device) >= NM_DEVICE_STATE_DISCONNECTED, FALSE); + + { + gs_unref_object NMActiveConnection *active = NULL; + gs_unref_object NMAuthSubject *subject = NULL; + NMActiveConnection *master_ac; + GError *error = NULL; + + subject = nm_auth_subject_new_internal (); + active = _new_active_connection (self, NM_CONNECTION (connection), NULL, NULL, + device, subject, + generated ? NM_ACTIVATION_TYPE_EXTERNAL : NM_ACTIVATION_TYPE_ASSUME, + &error); + + if (!active) { + _LOGW (LOGD_DEVICE, "assumed connection %s failed to activate: %s", + nm_connection_get_path (NM_CONNECTION (connection)), + error->message); + g_error_free (error); + + if (was_unmanaged) { + nm_device_state_changed (device, + NM_DEVICE_STATE_UNAVAILABLE, + NM_DEVICE_STATE_REASON_CONFIG_FAILED); + } - if (generated) { - _LOGD (LOGD_DEVICE, "(%s): connection assumption failed. Deleting generated connection", - nm_device_get_iface (device)); + if (generated) { + _LOGD (LOGD_DEVICE, "(%s): connection assumption failed. Deleting generated connection", + nm_device_get_iface (device)); - nm_settings_connection_delete (connection, NULL, NULL); + nm_settings_connection_delete (connection, NULL, NULL); + } else { + if (nm_device_sys_iface_state_get (device) == NM_DEVICE_SYS_IFACE_STATE_ASSUME) + nm_device_sys_iface_state_set (device, NM_DEVICE_SYS_IFACE_STATE_EXTERNAL); + } + return FALSE; } + + /* If the device is a slave or VLAN, find the master ActiveConnection */ + master_ac = NULL; + if (find_master (self, NM_CONNECTION (connection), device, NULL, NULL, &master_ac, NULL) && master_ac) + nm_active_connection_set_master (active, master_ac); + + nm_exported_object_export (NM_EXPORTED_OBJECT (active)); + active_connection_add (self, active); + nm_device_queue_activation (device, NM_ACT_REQUEST (active)); } - return success; + return TRUE; } static void recheck_assume_connection_cb (NMDevice *device, gpointer user_data) { - recheck_assume_connection (user_data, device); + recheck_assume_connection (user_data, device, NULL); } static void @@ -1976,7 +2004,10 @@ device_realized (NMDevice *device, } static void -_device_realize_finish (NMManager *self, NMDevice *device, const NMPlatformLink *plink) +_device_realize_finish (NMManager *self, + NMDevice *device, + const NMPlatformLink *plink, + const char *connection_uuid_to_assume) { g_return_if_fail (NM_IS_MANAGER (self)); g_return_if_fail (NM_IS_DEVICE (device)); @@ -1986,7 +2017,7 @@ _device_realize_finish (NMManager *self, NMDevice *device, const NMPlatformLink if (!nm_device_get_managed (device, FALSE)) return; - if (recheck_assume_connection (self, device)) + if (recheck_assume_connection (self, device, connection_uuid_to_assume)) return; /* if we failed to assume a connection for the managed device, but the device @@ -2132,9 +2163,13 @@ factory_device_added_cb (NMDeviceFactory *factory, g_return_if_fail (NM_IS_MANAGER (self)); - if (nm_device_realize_start (device, NULL, NULL, &error)) { + if (nm_device_realize_start (device, + NULL, + NM_UNMAN_FLAG_OP_FORGET, + NULL, + &error)) { add_device (self, device, NULL); - _device_realize_finish (self, device, NULL); + _device_realize_finish (self, device, NULL, NULL); } else { _LOGW (LOGD_DEVICE, "(%s): failed to realize device: %s", nm_device_get_iface (device), error->message); @@ -2205,9 +2240,13 @@ platform_link_added (NMManager *self, * device with the link's name. */ return; - } else if (nm_device_realize_start (candidate, plink, &compatible, &error)) { + } else if (nm_device_realize_start (candidate, + plink, + NM_UNMAN_FLAG_OP_FORGET, + &compatible, + &error)) { /* Success */ - _device_realize_finish (self, candidate, plink); + _device_realize_finish (self, candidate, plink, NULL); return; } @@ -2257,10 +2296,29 @@ platform_link_added (NMManager *self, if (device) { gs_free_error GError *error = NULL; + NMUnmanFlagOp unmanaged_user_explicit = NM_UNMAN_FLAG_OP_FORGET; + + if (dev_state) { + switch (dev_state->managed) { + case NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_MANAGED: + unmanaged_user_explicit = NM_UNMAN_FLAG_OP_SET_MANAGED; + break; + case NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_UNMANAGED: + unmanaged_user_explicit = NM_UNMAN_FLAG_OP_SET_UNMANAGED; + break; + case NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_UNKNOWN: + break; + } + } - if (nm_device_realize_start (device, plink, NULL, &error)) { + if (nm_device_realize_start (device, + plink, + unmanaged_user_explicit, + NULL, + &error)) { add_device (self, device, NULL); - _device_realize_finish (self, device, plink); + _device_realize_finish (self, device, plink, + dev_state ? dev_state->connection_uuid : NULL); } else { _LOGW (LOGD_DEVICE, "%s: failed to realize device: %s", plink->name, error->message); @@ -2408,27 +2466,21 @@ nm_manager_get_device_paths (NMManager *self) } static NMDevice * -nm_manager_get_connection_device (NMManager *self, - NMConnection *connection) -{ - NMActiveConnection *ac = find_ac_for_connection (self, connection); - if (ac == NULL) - return NULL; - - return nm_active_connection_get_device (ac); -} - -static NMDevice * nm_manager_get_best_device_for_connection (NMManager *self, NMConnection *connection, gboolean for_user_request) { const GSList *devices, *iter; - NMDevice *act_device = nm_manager_get_connection_device (self, connection); + NMActiveConnection *ac; + NMDevice *act_device; NMDeviceCheckConAvailableFlags flags; - if (act_device) - return act_device; + ac = active_connection_find_first_by_connection (self, connection); + if (ac) { + act_device = nm_active_connection_get_device (ac); + if (act_device) + return act_device; + } flags = for_user_request ? NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST : NM_DEVICE_CHECK_CON_AVAILABLE_NONE; @@ -2626,8 +2678,10 @@ find_master (NMManager *self, *out_master_connection = master_connection; if (out_master_device) *out_master_device = master_device; - if (out_master_ac && master_connection) - *out_master_ac = find_ac_for_connection (self, NM_CONNECTION (master_connection)); + if (out_master_ac && master_connection) { + *out_master_ac = active_connection_find_first (self, master_connection, NULL, + NM_ACTIVE_CONNECTION_STATE_DEACTIVATING); + } if (master_device || master_connection) return TRUE; @@ -2735,6 +2789,7 @@ ensure_master_active_connection (NMManager *self, NULL, master_device, subject, + NM_ACTIVATION_TYPE_MANAGED, error); return master_ac; } @@ -2780,6 +2835,7 @@ ensure_master_active_connection (NMManager *self, NULL, candidate, subject, + NM_ACTIVATION_TYPE_MANAGED, error); return master_ac; } @@ -2926,6 +2982,7 @@ autoconnect_slaves (NMManager *self, NULL, nm_manager_get_best_device_for_connection (self, NM_CONNECTION (slave_connection), FALSE), subject, + NM_ACTIVATION_TYPE_MANAGED, &local_err); if (local_err) { _LOGW (LOGD_CORE, "Slave connection activation failed: %s", local_err->message); @@ -3017,6 +3074,7 @@ static gboolean _internal_activate_device (NMManager *self, NMActiveConnection *active, GError **error) { NMDevice *device, *existing, *master_device = NULL; + NMActiveConnection *existing_ac; NMConnection *applied; NMSettingsConnection *connection; NMSettingsConnection *master_connection = NULL; @@ -3083,7 +3141,8 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError * return FALSE; } - parent_ac = nm_manager_activate_connection (self, parent_con, NULL, NULL, parent, subject, error); + parent_ac = nm_manager_activate_connection (self, parent_con, NULL, NULL, parent, + subject, NM_ACTIVATION_TYPE_MANAGED, error); if (!parent_ac) { g_prefix_error (error, "%s failed to activate parent: ", nm_device_get_iface (device)); return FALSE; @@ -3177,9 +3236,12 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError * autoconnect_slaves (self, connection, device, nm_active_connection_get_subject (active)); /* Disconnect the connection if connected or queued on another device */ - existing = nm_manager_get_connection_device (self, NM_CONNECTION (connection)); - if (existing) - nm_device_steal_connection (existing, connection); + existing_ac = active_connection_find_first (self, connection, NULL, NM_ACTIVE_CONNECTION_STATE_DEACTIVATING); + if (existing_ac) { + existing = nm_active_connection_get_device (existing_ac); + if (existing) + nm_device_steal_connection (existing, connection); + } /* If the device is there, we can ready it for the activation. */ if (nm_device_is_real (device)) @@ -3278,6 +3340,7 @@ _new_active_connection (NMManager *self, const char *specific_object, NMDevice *device, NMAuthSubject *subject, + NMActivationType activation_type, GError **error) { NMSettingsConnection *settings_connection = NULL; @@ -3288,7 +3351,7 @@ _new_active_connection (NMManager *self, g_return_val_if_fail (NM_IS_AUTH_SUBJECT (subject), NULL); /* Can't create new AC for already-active connection */ - existing_ac = find_ac_for_connection (self, connection); + existing_ac = active_connection_find_first_by_connection (self, connection); if (NM_IS_VPN_CONNECTION (existing_ac)) { g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_CONNECTION_ALREADY_ACTIVE, "Connection '%s' is already active", @@ -3306,6 +3369,8 @@ _new_active_connection (NMManager *self, settings_connection = (NMSettingsConnection *) connection; if (is_vpn) { + if (activation_type != NM_ACTIVATION_TYPE_MANAGED) + g_return_val_if_reached (NULL); return _new_vpn_active_connection (self, settings_connection, specific_object, @@ -3317,6 +3382,7 @@ _new_active_connection (NMManager *self, applied, specific_object, subject, + activation_type, device); } @@ -3369,6 +3435,8 @@ _internal_activation_auth_done (NMActiveConnection *active, * @specific_object: the specific object path, if any, for the activation * @device: the #NMDevice to activate @connection on * @subject: the subject which requested activation + * @activation_type: whether to assume the connection. That is, take over gracefully, + * non-destructible. * @error: return location for an error * * Begins a new internally-initiated activation of @connection on @device. @@ -3388,6 +3456,7 @@ nm_manager_activate_connection (NMManager *self, const char *specific_object, NMDevice *device, NMAuthSubject *subject, + NMActivationType activation_type, GError **error) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); @@ -3434,6 +3503,7 @@ nm_manager_activate_connection (NMManager *self, specific_object, device, subject, + activation_type, error); if (active) { priv->authorizing_connections = g_slist_prepend (priv->authorizing_connections, active); @@ -3677,6 +3747,7 @@ impl_manager_activate_connection (NMManager *self, specific_object_path, device, subject, + NM_ACTIVATION_TYPE_MANAGED, &error); if (!active) goto error; @@ -3896,6 +3967,7 @@ impl_manager_add_and_activate_connection (NMManager *self, specific_object_path, device, subject, + NM_ACTIVATION_TYPE_MANAGED, &error); if (!active) goto error; diff --git a/src/nm-manager.h b/src/nm-manager.h index a7baf30986..676fa995b6 100644 --- a/src/nm-manager.h +++ b/src/nm-manager.h @@ -115,6 +115,7 @@ NMActiveConnection *nm_manager_activate_connection (NMManager *manager, const char *specific_object, NMDevice *device, NMAuthSubject *subject, + NMActivationType activation_type, GError **error); gboolean nm_manager_deactivate_connection (NMManager *manager, diff --git a/src/nm-policy.c b/src/nm-policy.c index 44b921dc83..66c9895c8d 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -428,7 +428,7 @@ settings_set_hostname_cb (const char *hostname, } if (!ret) - nm_dispatcher_call (DISPATCHER_ACTION_HOSTNAME, NULL, NULL, NULL, NULL, NULL, NULL); + nm_dispatcher_call_hostname (NULL, NULL, NULL); } static void @@ -1023,6 +1023,7 @@ auto_activate_device (NMPolicy *self, specific_object, device, subject, + NM_ACTIVATION_TYPE_MANAGED, &error)) { _LOGI (LOGD_DEVICE, "connection '%s' auto-activation failed: (%d) %s", nm_settings_connection_get_id (best_connection), @@ -1433,6 +1434,7 @@ activate_secondary_connections (NMPolicy *self, nm_exported_object_get_path (NM_EXPORTED_OBJECT (req)), device, nm_active_connection_get_subject (NM_ACTIVE_CONNECTION (req)), + NM_ACTIVATION_TYPE_MANAGED, &error); if (ac) secondary_ac_list = g_slist_append (secondary_ac_list, g_object_ref (ac)); @@ -1846,6 +1848,7 @@ vpn_connection_retry_after_failure (NMVpnConnection *vpn, NMPolicy *self) NULL, NULL, nm_active_connection_get_subject (ac), + NM_ACTIVATION_TYPE_MANAGED, &error)) { _LOGW (LOGD_DEVICE, "VPN '%s' reconnect failed: %s", nm_settings_connection_get_id (connection), diff --git a/src/nm-types.h b/src/nm-types.h index 01d9dde9b2..32f4198ad7 100644 --- a/src/nm-types.h +++ b/src/nm-types.h @@ -55,6 +55,22 @@ typedef struct _NMSleepMonitor NMSleepMonitor; typedef struct _NMLldpListener NMLldpListener; typedef struct _NMConfigDeviceStateData NMConfigDeviceStateData; +/*****************************************************************************/ + +typedef enum { + /* Do a full activation. */ + NM_ACTIVATION_TYPE_MANAGED = 0, + + /* gracefully/seamlessly take over the device. This leaves additional + * IP addresses and does not restore missing manual addresses. */ + NM_ACTIVATION_TYPE_ASSUME = 1, + + /* external activation. This device is not managed by NM, instead + * a in-memory connection is generated and NM pretends the device + * to be active, but it doesn't do anything really. */ + NM_ACTIVATION_TYPE_EXTERNAL = 2, +} NMActivationType; + typedef enum { /* In priority order; higher number == higher priority */ diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c index bfbe051f11..d8e6a4faa1 100644 --- a/src/settings/nm-settings-connection.c +++ b/src/settings/nm-settings-connection.c @@ -498,7 +498,7 @@ set_unsaved (NMSettingsConnection *self, gboolean now_unsaved) else { flags &= ~(NM_SETTINGS_CONNECTION_FLAGS_UNSAVED | NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED | - NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED_ASSUMED); + NM_SETTINGS_CONNECTION_FLAGS_VOLATILE); } nm_settings_connection_set_flags_all (self, flags); } @@ -561,7 +561,7 @@ nm_settings_connection_replace_settings (NMSettingsConnection *self, _LOGD ("replace settings from connection %p (%s)", new_connection, nm_connection_get_id (NM_CONNECTION (self))); nm_settings_connection_set_flags (self, - NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED | NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED_ASSUMED, + NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED | NM_SETTINGS_CONNECTION_FLAGS_VOLATILE, FALSE); /* Cache the just-updated system secrets in case something calls @@ -2641,18 +2641,18 @@ nm_settings_connection_get_nm_generated (NMSettingsConnection *self) } /** - * nm_settings_connection_get_nm_generated_assumed: + * nm_settings_connection_get_volatile: * @self: an #NMSettingsConnection * - * Gets the "nm-generated-assumed" flag on @self. + * Gets the "volatile" flag on @self. * - * The connection is a generated connection especially - * generated for connection assumption. + * The connection is marked as volatile and will be removed when + * it disconnects. */ gboolean -nm_settings_connection_get_nm_generated_assumed (NMSettingsConnection *self) +nm_settings_connection_get_volatile (NMSettingsConnection *self) { - return NM_FLAGS_HAS (nm_settings_connection_get_flags (self), NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED_ASSUMED); + return NM_FLAGS_HAS (nm_settings_connection_get_flags (self), NM_SETTINGS_CONNECTION_FLAGS_VOLATILE); } gboolean diff --git a/src/settings/nm-settings-connection.h b/src/settings/nm-settings-connection.h index 7b59c5edcd..b449e2bd14 100644 --- a/src/settings/nm-settings-connection.h +++ b/src/settings/nm-settings-connection.h @@ -58,9 +58,9 @@ * @NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED: A connection is "nm-generated" if * it was generated by NetworkManger. If the connection gets modified or saved * by the user, the flag gets cleared. A nm-generated is implicitly unsaved. - * @NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED_ASSUMED: A special kind of "nm-generated" - * connection that was specifically created for connection assumption. "nm-generated-assumed" - * implies "nm-generated". + * @NM_SETTINGS_CONNECTION_FLAGS_VOLATILE: The connection will be deleted + * when it disconnects. That is for in-memory connections (unsaved), which are + * currently active but cleanup on disconnect. * @NM_SETTINGS_CONNECTION_FLAGS_ALL: special mask, for all known flags * * #NMSettingsConnection flags. @@ -70,7 +70,7 @@ typedef enum NM_SETTINGS_CONNECTION_FLAGS_NONE = 0x00, NM_SETTINGS_CONNECTION_FLAGS_UNSAVED = 0x01, NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED = 0x02, - NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED_ASSUMED = 0x04, + NM_SETTINGS_CONNECTION_FLAGS_VOLATILE = 0x04, __NM_SETTINGS_CONNECTION_FLAGS_LAST, NM_SETTINGS_CONNECTION_FLAGS_ALL = ((__NM_SETTINGS_CONNECTION_FLAGS_LAST - 1) << 1) - 1, @@ -228,7 +228,7 @@ void nm_settings_connection_set_autoconnect_blocke gboolean nm_settings_connection_can_autoconnect (NMSettingsConnection *self); gboolean nm_settings_connection_get_nm_generated (NMSettingsConnection *self); -gboolean nm_settings_connection_get_nm_generated_assumed (NMSettingsConnection *self); +gboolean nm_settings_connection_get_volatile (NMSettingsConnection *self); gboolean nm_settings_connection_get_ready (NMSettingsConnection *self); void nm_settings_connection_set_ready (NMSettingsConnection *self, diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c index cc03a2c4d9..f738b4377a 100644 --- a/src/settings/nm-settings.c +++ b/src/settings/nm-settings.c @@ -2143,7 +2143,7 @@ hostnamed_properties_changed (GDBusProxy *proxy, g_free (priv->hostname.value); priv->hostname.value = g_strdup (hostname); _notify (self, PROP_HOSTNAME); - nm_dispatcher_call (DISPATCHER_ACTION_HOSTNAME, NULL, NULL, NULL, NULL, NULL, NULL); + nm_dispatcher_call_hostname (NULL, NULL, NULL); } g_variant_unref (v_hostname); diff --git a/src/tests/test-general.c b/src/tests/test-general.c index 643c912fa2..cecce83f2c 100644 --- a/src/tests/test-general.c +++ b/src/tests/test-general.c @@ -309,6 +309,30 @@ _match_connection_new (void) return connection; } +static NMConnection * +_match_connection (GSList *connections, + NMConnection *original, + gboolean device_has_carrier, + gint64 default_v4_metric, + gint64 default_v6_metric) +{ + NMConnection **list; + guint i, len; + + len = g_slist_length (connections); + g_assert (len < 10); + + list = g_alloca ((len + 1) * sizeof (NMConnection *)); + for (i = 0; i < len; i++, connections = connections->next) { + g_assert (connections); + g_assert (connections->data); + list[i] = connections->data; + } + list[i] = NULL; + + return nm_utils_match_connection (list, original, device_has_carrier, default_v4_metric, default_v6_metric, NULL, NULL); +} + static void test_connection_match_basic (void) { @@ -320,7 +344,7 @@ test_connection_match_basic (void) copy = nm_simple_connection_new_clone (orig); connections = g_slist_append (connections, copy); - matched = nm_utils_match_connection (connections, orig, TRUE, 0, 0, NULL, NULL); + matched = _match_connection (connections, orig, TRUE, 0, 0); g_assert (matched == copy); /* Now change a material property like IPv4 method and ensure matching fails */ @@ -329,7 +353,7 @@ test_connection_match_basic (void) g_object_set (G_OBJECT (s_ip4), NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL, NULL); - matched = nm_utils_match_connection (connections, orig, TRUE, 0, 0, NULL, NULL); + matched = _match_connection (connections, orig, TRUE, 0, 0); g_assert (matched == NULL); g_slist_free (connections); @@ -365,7 +389,7 @@ test_connection_match_ip6_method (void) NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, NULL); - matched = nm_utils_match_connection (connections, orig, TRUE, 0, 0, NULL, NULL); + matched = _match_connection (connections, orig, TRUE, 0, 0); g_assert (matched == copy); g_slist_free (connections); @@ -399,7 +423,7 @@ test_connection_match_ip6_method_ignore (void) NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL); - matched = nm_utils_match_connection (connections, orig, TRUE, 0, 0, NULL, NULL); + matched = _match_connection (connections, orig, TRUE, 0, 0); g_assert (matched == copy); g_slist_free (connections); @@ -433,7 +457,7 @@ test_connection_match_ip6_method_ignore_auto (void) NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL); - matched = nm_utils_match_connection (connections, orig, TRUE, 0, 0, NULL, NULL); + matched = _match_connection (connections, orig, TRUE, 0, 0); g_assert (matched == copy); g_slist_free (connections); @@ -469,11 +493,11 @@ test_connection_match_ip4_method (void) NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, NULL); - matched = nm_utils_match_connection (connections, orig, FALSE, 0, 0, NULL, NULL); + matched = _match_connection (connections, orig, FALSE, 0, 0); g_assert (matched == copy); /* Ensure when carrier=true matching fails */ - matched = nm_utils_match_connection (connections, orig, TRUE, 0, 0, NULL, NULL); + matched = _match_connection (connections, orig, TRUE, 0, 0); g_assert (matched == NULL); g_slist_free (connections); @@ -507,7 +531,7 @@ test_connection_match_interface_name (void) NM_SETTING_CONNECTION_INTERFACE_NAME, NULL, NULL); - matched = nm_utils_match_connection (connections, orig, TRUE, 0, 0, NULL, NULL); + matched = _match_connection (connections, orig, TRUE, 0, 0); g_assert (matched == copy); g_slist_free (connections); @@ -544,7 +568,7 @@ test_connection_match_wired (void) NM_SETTING_WIRED_S390_NETTYPE, "qeth", NULL); - matched = nm_utils_match_connection (connections, orig, TRUE, 0, 0, NULL, NULL); + matched = _match_connection (connections, orig, TRUE, 0, 0); g_assert (matched == copy); g_slist_free (connections); @@ -576,7 +600,7 @@ test_connection_match_wired2 (void) * the connections match. It can happen if assuming VLAN devices. */ nm_connection_remove_setting (orig, NM_TYPE_SETTING_WIRED); - matched = nm_utils_match_connection (connections, orig, TRUE, 0, 0, NULL, NULL); + matched = _match_connection (connections, orig, TRUE, 0, 0); g_assert (matched == copy); g_slist_free (connections); @@ -601,7 +625,7 @@ test_connection_match_cloned_mac (void) NM_SETTING_WIRED_CLONED_MAC_ADDRESS, "52:54:00:ab:db:23", NULL); - matched = nm_utils_match_connection (connections, orig, TRUE, 0, 0, NULL, NULL); + matched = _match_connection (connections, orig, TRUE, 0, 0); g_assert (matched == fuzzy); exact = nm_simple_connection_new_clone (orig); @@ -612,14 +636,14 @@ test_connection_match_cloned_mac (void) NM_SETTING_WIRED_CLONED_MAC_ADDRESS, "52:54:00:ab:db:23", NULL); - matched = nm_utils_match_connection (connections, orig, TRUE, 0, 0, NULL, NULL); + matched = _match_connection (connections, orig, TRUE, 0, 0); g_assert (matched == exact); g_object_set (G_OBJECT (s_wired), NM_SETTING_WIRED_CLONED_MAC_ADDRESS, "52:54:00:ab:db:24", NULL); - matched = nm_utils_match_connection (connections, orig, TRUE, 0, 0, NULL, NULL); + matched = _match_connection (connections, orig, TRUE, 0, 0); g_assert (matched == fuzzy); g_slist_free (connections); @@ -679,7 +703,7 @@ test_connection_no_match_ip4_addr (void) nm_setting_ip_config_add_address (s_ip4, nm_addr); nm_ip_address_unref (nm_addr); - matched = nm_utils_match_connection (connections, orig, TRUE, 0, 0, NULL, NULL); + matched = _match_connection (connections, orig, TRUE, 0, 0); g_assert (matched != copy); g_slist_free (connections); @@ -725,7 +749,7 @@ test_connection_no_match_vlan (void) NM_SETTING_VLAN_FLAGS, 0, NULL); - matched = nm_utils_match_connection (connections, orig, TRUE, 0, 0, NULL, NULL); + matched = _match_connection (connections, orig, TRUE, 0, 0); g_assert (matched != copy); /* Check that the connections do not match if VLAN priorities differ */ @@ -735,7 +759,7 @@ test_connection_no_match_vlan (void) g_object_set (G_OBJECT (s_vlan_copy), NM_SETTING_VLAN_FLAGS, 0, NULL); nm_setting_vlan_add_priority_str (s_vlan_copy, NM_VLAN_INGRESS_MAP, "4:2"); - matched = nm_utils_match_connection (connections, orig, TRUE, 0, 0, NULL, NULL); + matched = _match_connection (connections, orig, TRUE, 0, 0); g_assert (matched != copy); g_slist_free (connections); @@ -775,7 +799,7 @@ test_connection_match_ip4_routes1 (void) nmtst_setting_ip_config_add_route (s_ip4, "172.25.17.0", 24, "10.0.0.3", 20); /* Try to match the connections */ - matched = nm_utils_match_connection (connections, orig, FALSE, 100, 0, NULL, NULL); + matched = _match_connection (connections, orig, FALSE, 100, 0); g_assert (matched == NULL); } @@ -812,9 +836,9 @@ test_connection_match_ip4_routes2 (void) nmtst_setting_ip_config_add_route (s_ip4, "172.25.16.0", 24, "10.0.0.2", 100); /* Try to match the connections using different default metrics */ - matched = nm_utils_match_connection (connections, orig, FALSE, 100, 0, NULL, NULL); + matched = _match_connection (connections, orig, FALSE, 100, 0); g_assert (matched == copy); - matched = nm_utils_match_connection (connections, orig, FALSE, 500, 0, NULL, NULL); + matched = _match_connection (connections, orig, FALSE, 500, 0); g_assert (matched == NULL); } @@ -849,9 +873,9 @@ test_connection_match_ip6_routes (void) nmtst_setting_ip_config_add_route (s_ip6, "2001:db8:a:b:0:0:0:0", 64, "fd01::16", 50); /* Try to match the connections */ - matched = nm_utils_match_connection (connections, orig, FALSE, 0, 100, NULL, NULL); + matched = _match_connection (connections, orig, FALSE, 0, 100); g_assert (matched == NULL); - matched = nm_utils_match_connection (connections, orig, FALSE, 0, 50, NULL, NULL); + matched = _match_connection (connections, orig, FALSE, 0, 50); g_assert (matched == copy); } diff --git a/src/vpn/nm-vpn-connection.c b/src/vpn/nm-vpn-connection.c index 2120bbe37e..912972cb90 100644 --- a/src/vpn/nm-vpn-connection.c +++ b/src/vpn/nm-vpn-connection.c @@ -535,7 +535,7 @@ _set_vpn_state (NMVpnConnection *self, */ break; case STATE_PRE_UP: - if (!nm_dispatcher_call_vpn (DISPATCHER_ACTION_VPN_PRE_UP, + if (!nm_dispatcher_call_vpn (NM_DISPATCHER_ACTION_VPN_PRE_UP, _get_settings_connection (self, FALSE), _get_applied_connection (self), parent_dev, @@ -555,7 +555,7 @@ _set_vpn_state (NMVpnConnection *self, nm_active_connection_clear_secrets (NM_ACTIVE_CONNECTION (self)); /* Let dispatcher scripts know we're up and running */ - nm_dispatcher_call_vpn (DISPATCHER_ACTION_VPN_UP, + nm_dispatcher_call_vpn (NM_DISPATCHER_ACTION_VPN_UP, _get_settings_connection (self, FALSE), _get_applied_connection (self), parent_dev, @@ -577,7 +577,7 @@ _set_vpn_state (NMVpnConnection *self, break; case STATE_DEACTIVATING: if (quitting) { - nm_dispatcher_call_vpn_sync (DISPATCHER_ACTION_VPN_PRE_DOWN, + nm_dispatcher_call_vpn_sync (NM_DISPATCHER_ACTION_VPN_PRE_DOWN, _get_settings_connection (self, FALSE), _get_applied_connection (self), parent_dev, @@ -586,7 +586,7 @@ _set_vpn_state (NMVpnConnection *self, priv->ip4_config, priv->ip6_config); } else { - if (!nm_dispatcher_call_vpn (DISPATCHER_ACTION_VPN_PRE_DOWN, + if (!nm_dispatcher_call_vpn (NM_DISPATCHER_ACTION_VPN_PRE_DOWN, _get_settings_connection (self, FALSE), _get_applied_connection (self), parent_dev, @@ -611,7 +611,7 @@ _set_vpn_state (NMVpnConnection *self, && old_vpn_state <= STATE_DEACTIVATING) { /* Let dispatcher scripts know we're about to go down */ if (quitting) { - nm_dispatcher_call_vpn_sync (DISPATCHER_ACTION_VPN_DOWN, + nm_dispatcher_call_vpn_sync (NM_DISPATCHER_ACTION_VPN_DOWN, _get_settings_connection (self, FALSE), _get_applied_connection (self), parent_dev, @@ -620,7 +620,7 @@ _set_vpn_state (NMVpnConnection *self, NULL, NULL); } else { - nm_dispatcher_call_vpn (DISPATCHER_ACTION_VPN_DOWN, + nm_dispatcher_call_vpn (NM_DISPATCHER_ACTION_VPN_DOWN, _get_settings_connection (self, FALSE), _get_applied_connection (self), parent_dev, |