From 5f5743654a9462e49e6644e787aac225b16fb3c2 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 16 Mar 2017 17:42:30 +0100 Subject: [PATCH 01/24] core: fix matching routes for assuming connections If the connection candidate contains a static route without route-metric, but overrides the default route-metric, matching would have failed: ipv4.route-metric: 200 ipv4.routes: { ip = 192.168.5.0/32 } Then, we must not compare existing routes using the device's metric, but must use the overwrite from the connection. --- src/NetworkManagerUtils.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index 20b871622e..5f40d392af 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)) From e791a9d24240a803243c023498f6dcdc8d16a15d Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 16 Mar 2017 16:15:55 +0100 Subject: [PATCH 02/24] manager: fix leaking settings connection in active_connection_remove() We must always unref @connection, not only in case of nm_settings_has_connection(). Fixes: 74ed416d845ecea6684a39701d6aea5f7ba9029e --- src/nm-manager.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/nm-manager.c b/src/nm-manager.c index b1c6c479bd..63a0820e83 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -279,11 +279,12 @@ active_connection_remove (NMManager *self, NMActiveConnection *active) 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); } } From c59532ee40419e4ed7d31f1d1edbaa6bc3c2278e Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 14 Mar 2017 15:42:36 +0100 Subject: [PATCH 03/24] shared: trigger -Wenum-conversion warning in NM_IN_SET*() macros and add NM_IN_SET*_TYPED() macros, which allow to explicitly select the type of "x". --- shared/nm-utils/nm-macros-internal.h | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 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__)) \ ); \ }) From 9e60de87f54c1832d26dc44b0e08326e63c39e2b Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 1 Mar 2017 17:26:45 +0100 Subject: [PATCH 04/24] core: minor cleanups Some minor changes that make the code more similar to what will be done later for the related bug bgo#746440. --- src/devices/nm-device.c | 27 ++++++++++++++++++--------- src/nm-active-connection.c | 13 ++++++------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index cb1cc63707..f9c492706b 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 */ @@ -1725,7 +1728,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) @@ -3005,7 +3008,7 @@ nm_device_master_add_slave (NMDevice *self, NMDevice *slave, gboolean configure) 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) @@ -3248,15 +3251,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 +3927,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); diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c index ab2a9b3b6b..a96f33b432 100644 --- a/src/nm-active-connection.c +++ b/src/nm-active-connection.c @@ -44,20 +44,19 @@ 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 assumed:1; + bool master_ready:1; NMAuthSubject *subject; NMActiveConnection *master; - gboolean master_ready; NMActiveConnection *parent; - gboolean assumed; - NMAuthChain *chain; const char *wifi_shared_permission; NMActiveConnectionAuthResultFunc result_func; From 2b72cc269378ebf46fc0686ea97e0a3a277a9332 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 8 Mar 2017 14:18:09 +0100 Subject: [PATCH 05/24] core/trivial: give names in src/nm-dispatcher.h header an "NM" prefix Stuff defined in header files should have an NM prefix, although this is a project-internal header. Rename. --- src/devices/nm-device.c | 20 +++++----- src/nm-connectivity.c | 2 +- src/nm-dispatcher.c | 78 ++++++++++++++++++------------------- src/nm-dispatcher.h | 50 ++++++++++++------------ src/nm-policy.c | 2 +- src/settings/nm-settings.c | 2 +- src/vpn/nm-vpn-connection.c | 12 +++--- 7 files changed, 82 insertions(+), 84 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index f9c492706b..8f61b8623e 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -5238,7 +5238,7 @@ dhcp4_lease_change (NMDevice *self, NMIP4Config *config) } /* Notify dispatcher scripts of new DHCP4 config */ - nm_dispatcher_call (DISPATCHER_ACTION_DHCP4_CHANGE, + nm_dispatcher_call (NM_DISPATCHER_ACTION_DHCP4_CHANGE, nm_device_get_settings_connection (self), nm_device_get_applied_connection (self), self, @@ -6006,7 +6006,7 @@ dhcp6_lease_change (NMDevice *self) } /* Notify dispatcher scripts of new DHCPv6 config */ - nm_dispatcher_call (DISPATCHER_ACTION_DHCP6_CHANGE, + nm_dispatcher_call (NM_DISPATCHER_ACTION_DHCP6_CHANGE, settings_connection, nm_device_get_applied_connection (self), self, NULL, NULL, NULL); @@ -7947,7 +7947,7 @@ activate_stage5_ip4_config_commit (NMDevice *self) && 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_dispatcher_call (NM_DISPATCHER_ACTION_DHCP4_CHANGE, nm_device_get_settings_connection (self), nm_device_get_applied_connection (self), self, @@ -8082,7 +8082,7 @@ 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_dispatcher_call (NM_DISPATCHER_ACTION_DHCP6_CHANGE, nm_device_get_settings_connection (self), nm_device_get_applied_connection (self), self, @@ -9617,7 +9617,7 @@ 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, + if (!nm_dispatcher_call (NM_DISPATCHER_ACTION_PRE_UP, nm_device_get_settings_connection (self), nm_device_get_applied_connection (self), self, @@ -12139,14 +12139,14 @@ _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_dispatcher_call_sync (NM_DISPATCHER_ACTION_PRE_DOWN, nm_act_request_get_settings_connection (req), nm_act_request_get_applied_connection (req), self); } else { priv->dispatcher.post_state = NM_DEVICE_STATE_DISCONNECTED; priv->dispatcher.post_state_reason = reason; - if (!nm_dispatcher_call (DISPATCHER_ACTION_PRE_DOWN, + if (!nm_dispatcher_call (NM_DISPATCHER_ACTION_PRE_DOWN, nm_act_request_get_settings_connection (req), nm_act_request_get_applied_connection (req), self, @@ -12179,7 +12179,7 @@ _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_dispatcher_call (NM_DISPATCHER_ACTION_UP, nm_act_request_get_settings_connection (req), nm_act_request_get_applied_connection (req), self, NULL, NULL, NULL); @@ -12274,12 +12274,12 @@ _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_dispatcher_call_sync (NM_DISPATCHER_ACTION_DOWN, nm_act_request_get_settings_connection (req), nm_act_request_get_applied_connection (req), self); } else { - nm_dispatcher_call (DISPATCHER_ACTION_DOWN, + nm_dispatcher_call (NM_DISPATCHER_ACTION_DOWN, nm_act_request_get_settings_connection (req), nm_act_request_get_applied_connection (req), self, NULL, NULL, NULL); diff --git a/src/nm-connectivity.c b/src/nm-connectivity.c index a33ec680eb..491099bf96 100644 --- a/src/nm-connectivity.c +++ b/src/nm-connectivity.c @@ -106,7 +106,7 @@ update_state (NMConnectivity *self, NMConnectivityState 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 (NM_DISPATCHER_ACTION_CONNECTIVITY_CHANGE, state); } } diff --git a/src/nm-dispatcher.c b/src/nm-dispatcher.c index 6c0c4bb44d..49a672228c 100644 --- a/src/nm-dispatcher.c +++ b/src/nm-dispatcher.c @@ -70,14 +70,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 +311,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 +362,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 +440,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,7 +474,7 @@ dispatcher_idle_cb (gpointer user_data) } static gboolean -_dispatcher_call (DispatcherAction action, +_dispatcher_call (NMDispatcherAction action, gboolean blocking, NMSettingsConnection *settings_connection, NMConnection *applied_connection, @@ -484,7 +484,7 @@ _dispatcher_call (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) { @@ -517,8 +517,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 @@ -589,8 +589,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, @@ -695,7 +695,7 @@ done: /** * nm_dispatcher_call: - * @action: the %DispatcherAction + * @action: the %NMDispatcherAction * @settings_connection: the #NMSettingsConnection the action applies to * @applied_connection: the currently applied connection * @device: the #NMDevice the action applies to @@ -710,11 +710,11 @@ done: * Returns: %TRUE if the action was dispatched, %FALSE on failure */ gboolean -nm_dispatcher_call (DispatcherAction action, +nm_dispatcher_call (NMDispatcherAction action, NMSettingsConnection *settings_connection, NMConnection *applied_connection, NMDevice *device, - DispatcherFunc callback, + NMDispatcherFunc callback, gpointer user_data, guint *out_call_id) { @@ -725,7 +725,7 @@ nm_dispatcher_call (DispatcherAction action, /** * nm_dispatcher_call_sync(): - * @action: the %DispatcherAction + * @action: the %NMDispatcherAction * @settings_connection: the #NMSettingsConnection the action applies to * @applied_connection: the currently applied connection * @device: the #NMDevice the action applies to @@ -736,7 +736,7 @@ nm_dispatcher_call (DispatcherAction action, * Returns: %TRUE if the action was dispatched, %FALSE on failure */ gboolean -nm_dispatcher_call_sync (DispatcherAction action, +nm_dispatcher_call_sync (NMDispatcherAction action, NMSettingsConnection *settings_connection, NMConnection *applied_connection, NMDevice *device) @@ -747,7 +747,7 @@ nm_dispatcher_call_sync (DispatcherAction action, /** * 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 +766,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,7 +774,7 @@ 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) { @@ -785,7 +785,7 @@ nm_dispatcher_call_vpn (DispatcherAction action, /** * 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 +800,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, @@ -816,7 +816,7 @@ nm_dispatcher_call_vpn_sync (DispatcherAction action, /** * nm_dispatcher_call_connectivity(): - * @action: the %DispatcherAction + * @action: the %NMDispatcherAction * @connectivity_state: the #NMConnectivityState value * * This method does not block the caller. @@ -824,7 +824,7 @@ nm_dispatcher_call_vpn_sync (DispatcherAction action, * Returns: %TRUE if the action was dispatched, %FALSE on failure */ gboolean -nm_dispatcher_call_connectivity (DispatcherAction action, +nm_dispatcher_call_connectivity (NMDispatcherAction action, NMConnectivityState connectivity_state) { return _dispatcher_call (action, FALSE, NULL, NULL, NULL, connectivity_state, diff --git a/src/nm-dispatcher.h b/src/nm-dispatcher.h index 7ea1a6b8ae..6b73244c3b 100644 --- a/src/nm-dispatcher.h +++ b/src/nm-dispatcher.h @@ -19,44 +19,42 @@ * Copyright (C) 2005 - 2008 Novell, Inc. */ -#ifndef __NETWORKMANAGER_DISPATCHER_H__ -#define __NETWORKMANAGER_DISPATCHER_H__ - -#include +#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 (*DispatcherFunc) (guint call_id, gpointer user_data); +typedef void (*NMDispatcherFunc) (guint call_id, gpointer user_data); -gboolean nm_dispatcher_call (DispatcherAction action, +gboolean nm_dispatcher_call (NMDispatcherAction action, NMSettingsConnection *settings_connection, NMConnection *applied_connection, NMDevice *device, - DispatcherFunc callback, + NMDispatcherFunc callback, gpointer user_data, guint *out_call_id); -gboolean nm_dispatcher_call_sync (DispatcherAction action, +gboolean nm_dispatcher_call_sync (NMDispatcherAction action, NMSettingsConnection *settings_connection, NMConnection *applied_connection, NMDevice *device); -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 +62,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 +75,11 @@ gboolean nm_dispatcher_call_vpn_sync (DispatcherAction action, NMIP4Config *vpn_ip4_config, NMIP6Config *vpn_ip6_config); -gboolean nm_dispatcher_call_connectivity (DispatcherAction action, +gboolean nm_dispatcher_call_connectivity (NMDispatcherAction action, NMConnectivityState state); 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-policy.c b/src/nm-policy.c index 44b921dc83..0592bdee83 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 (NM_DISPATCHER_ACTION_HOSTNAME, NULL, NULL, NULL, NULL, NULL, NULL); } static void diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c index cc03a2c4d9..41ed226c8f 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 (NM_DISPATCHER_ACTION_HOSTNAME, NULL, NULL, NULL, NULL, NULL, NULL); } g_variant_unref (v_hostname); 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, From d2064be787a231b23dd8dfeef20f9d324502c00a Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 8 Mar 2017 14:11:22 +0100 Subject: [PATCH 06/24] core/dispatcher: add and use nm_dispatcher_call_hostname() --- src/nm-dispatcher.c | 21 +++++++++++++++++++++ src/nm-dispatcher.h | 4 ++++ src/nm-policy.c | 2 +- src/settings/nm-settings.c | 2 +- 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/nm-dispatcher.c b/src/nm-dispatcher.c index 49a672228c..1bea957fde 100644 --- a/src/nm-dispatcher.c +++ b/src/nm-dispatcher.c @@ -693,6 +693,27 @@ done: return success; } +/** + * 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, + NM_CONNECTIVITY_UNKNOWN, NULL, NULL, NULL, NULL, + callback, user_data, out_call_id); +} + /** * nm_dispatcher_call: * @action: the %NMDispatcherAction diff --git a/src/nm-dispatcher.h b/src/nm-dispatcher.h index 6b73244c3b..111085124e 100644 --- a/src/nm-dispatcher.h +++ b/src/nm-dispatcher.h @@ -41,6 +41,10 @@ typedef enum { typedef void (*NMDispatcherFunc) (guint call_id, gpointer user_data); +gboolean nm_dispatcher_call_hostname (NMDispatcherFunc callback, + gpointer user_data, + guint *out_call_id); + gboolean nm_dispatcher_call (NMDispatcherAction action, NMSettingsConnection *settings_connection, NMConnection *applied_connection, diff --git a/src/nm-policy.c b/src/nm-policy.c index 0592bdee83..2cba2852a3 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 (NM_DISPATCHER_ACTION_HOSTNAME, NULL, NULL, NULL, NULL, NULL, NULL); + nm_dispatcher_call_hostname (NULL, NULL, NULL); } static void diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c index 41ed226c8f..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 (NM_DISPATCHER_ACTION_HOSTNAME, NULL, NULL, NULL, NULL, NULL, NULL); + nm_dispatcher_call_hostname (NULL, NULL, NULL); } g_variant_unref (v_hostname); From 8987de7cc083d7763c4cc3a357ec11a7672e19e7 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 8 Mar 2017 14:11:22 +0100 Subject: [PATCH 07/24] core/dispatcher: cleanup nm_dispatcher_call_connectivity() Remove the redundant action argument. It is clear, that nm_dispatcher_call_connectivity() is called with action NM_DISPATCHER_ACTION_CONNECTIVITY_CHANGE. On the other hand, add the async callbacks. Altough they are not used at the moment, it seems more correct that an async API has a callback and a call-id to cancel the invocation. --- src/nm-connectivity.c | 3 +-- src/nm-dispatcher.c | 16 +++++++++++----- src/nm-dispatcher.h | 7 +++++-- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/nm-connectivity.c b/src/nm-connectivity.c index 491099bf96..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 (NM_DISPATCHER_ACTION_CONNECTIVITY_CHANGE, state); + nm_dispatcher_call_connectivity (state, NULL, NULL, NULL); } } diff --git a/src/nm-dispatcher.c b/src/nm-dispatcher.c index 1bea957fde..561950cff9 100644 --- a/src/nm-dispatcher.c +++ b/src/nm-dispatcher.c @@ -837,19 +837,25 @@ nm_dispatcher_call_vpn_sync (NMDispatcherAction action, /** * nm_dispatcher_call_connectivity(): - * @action: the %NMDispatcherAction * @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 (NMDispatcherAction 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, 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 111085124e..743cf44a19 100644 --- a/src/nm-dispatcher.h +++ b/src/nm-dispatcher.h @@ -79,8 +79,11 @@ gboolean nm_dispatcher_call_vpn_sync (NMDispatcherAction action, NMIP4Config *vpn_ip4_config, NMIP6Config *vpn_ip6_config); -gboolean nm_dispatcher_call_connectivity (NMDispatcherAction 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); From 3ce6cbb4a1c674b86a7e065dd27ef1ee16c392ec Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 8 Mar 2017 14:11:22 +0100 Subject: [PATCH 08/24] core/dispatcher: pass act-request to device dispatcher calls Currently, we determine NMD_CONNECTION_PROPS_EXTERNAL based on the settings connection. That is not optimal, because whether a connection is assumed or externally managed, should be really a property of the active-connection. So, in the this will change soon and we would need yet another argument to nm_dispatcher_call(). Instead, drop the settings-connection and applied-connection arguments and fetch them from the device as needed (but allow to pass a specific act-request argument to explicitly state which active connection to use). Also, rename nm_dispatcher_call() to nm_dispatcher_call_device(), it this is not a generic dispatcher call, but it is particularly related to device events. Likewise, rename nm_dispatcher_call_sync() to nm_dispatcher_call_device_sync(). --- src/devices/nm-device.c | 100 ++++++++++++++++------------------------ src/nm-dispatcher.c | 65 +++++++++++++++++--------- src/nm-dispatcher.h | 20 ++++---- 3 files changed, 93 insertions(+), 92 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 8f61b8623e..3265d5be42 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -1535,7 +1535,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; } @@ -5237,14 +5237,10 @@ dhcp4_lease_change (NMDevice *self, NMIP4Config *config) return FALSE; } - /* Notify dispatcher scripts of new DHCP4 config */ - nm_dispatcher_call (NM_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); @@ -6005,11 +6001,10 @@ dhcp6_lease_change (NMDevice *self) return FALSE; } - /* Notify dispatcher scripts of new DHCPv6 config */ - nm_dispatcher_call (NM_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); @@ -7946,14 +7941,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 (NM_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); @@ -8082,13 +8073,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 (NM_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; @@ -9617,13 +9605,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 (NM_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); } @@ -12139,20 +12126,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 (NM_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 (NM_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); } @@ -12179,10 +12163,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 (NM_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, @@ -12274,15 +12258,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 (NM_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 (NM_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); } } diff --git a/src/nm-dispatcher.c b/src/nm-dispatcher.c index 561950cff9..0b9f45cc8e 100644 --- a/src/nm-dispatcher.c +++ b/src/nm-dispatcher.c @@ -21,14 +21,16 @@ #include "nm-default.h" +#include "nm-dispatcher.h" + #include #include -#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" @@ -715,41 +717,50 @@ nm_dispatcher_call_hostname (NMDispatcherFunc callback, } /** - * nm_dispatcher_call: + * nm_dispatcher_call_device: * @action: the %NMDispatcherAction - * @settings_connection: the #NMSettingsConnection the action applies to - * @applied_connection: the currently applied connection * @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 (NMDispatcherAction action, - NMSettingsConnection *settings_connection, - NMConnection *applied_connection, - NMDevice *device, - NMDispatcherFunc 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_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, + nm_act_request_get_settings_connection (act_request), + nm_act_request_get_applied_connection (act_request), + device, NM_CONNECTIVITY_UNKNOWN, NULL, NULL, NULL, NULL, callback, user_data, out_call_id); } /** - * nm_dispatcher_call_sync(): + * nm_dispatcher_call_device_sync(): * @action: the %NMDispatcherAction - * @settings_connection: the #NMSettingsConnection the action applies to - * @applied_connection: the currently applied connection * @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. @@ -757,13 +768,23 @@ nm_dispatcher_call (NMDispatcherAction action, * Returns: %TRUE if the action was dispatched, %FALSE on failure */ gboolean -nm_dispatcher_call_sync (NMDispatcherAction 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, + nm_act_request_get_settings_connection (act_request), + nm_act_request_get_applied_connection (act_request), + device, + NM_CONNECTIVITY_UNKNOWN, NULL, NULL, NULL, NULL, + NULL, NULL, NULL); } /** diff --git a/src/nm-dispatcher.h b/src/nm-dispatcher.h index 743cf44a19..4448e8173f 100644 --- a/src/nm-dispatcher.h +++ b/src/nm-dispatcher.h @@ -45,18 +45,16 @@ gboolean nm_dispatcher_call_hostname (NMDispatcherFunc callback, gpointer user_data, guint *out_call_id); -gboolean nm_dispatcher_call (NMDispatcherAction action, - NMSettingsConnection *settings_connection, - NMConnection *applied_connection, - NMDevice *device, - NMDispatcherFunc 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 (NMDispatcherAction 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 (NMDispatcherAction action, NMSettingsConnection *settings_connection, From d43a54c9071caac2e09c2febcbcbfa1464321b2e Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 1 Mar 2017 17:28:46 +0100 Subject: [PATCH 09/24] device: return nm_device_master_add_slave() whether a slave was added This is currently not yet used. It will be later. --- src/devices/nm-device.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 3265d5be42..5252723cfe 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -474,7 +474,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); @@ -2991,17 +2991,21 @@ 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); @@ -3012,11 +3016,11 @@ nm_device_master_add_slave (NMDevice *self, NMDevice *slave, gboolean configure) 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); @@ -3036,13 +3040,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: From 90e7c8bf5bc91a48ba03be74e12702c07a1e06ee Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 16 Feb 2017 20:10:19 +0100 Subject: [PATCH 10/24] core/trivial: rename "nm-generated-assumed" flag to "volatile" The concept of assumed-connection will change. Currently we mark connections that are generated and assumed as "nm-generated-assumed". That has several consequences, one of them being that such a settings connection gets deleted when the device disconnects. That is, such a settings connection lingers around as long as it's active, but once it deactivates it gets automatically deleted. As such, it's a more volatile concept of an in-memory connection. The concept of such automatically cleaned up connections is useful beyond generated-assumed. See the related bug rh#1401515. --- src/devices/nm-device.c | 2 +- src/nm-dispatcher.c | 2 +- src/nm-manager.c | 6 +++--- src/settings/nm-settings-connection.c | 16 ++++++++-------- src/settings/nm-settings-connection.h | 10 +++++----- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 5252723cfe..a1fb1322f8 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -1606,7 +1606,7 @@ nm_device_uses_generated_assumed_connection (NMDevice *self) && 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)) + && nm_settings_connection_get_volatile (connection)) return TRUE; } return FALSE; diff --git a/src/nm-dispatcher.c b/src/nm-dispatcher.c index 0b9f45cc8e..4fa4ce6aba 100644 --- a/src/nm-dispatcher.c +++ b/src/nm-dispatcher.c @@ -575,7 +575,7 @@ _dispatcher_call (NMDispatcherAction action, NMD_CONNECTION_PROPS_FILENAME, g_variant_new_string (filename)); } - if (nm_settings_connection_get_nm_generated_assumed (settings_connection)) { + if (nm_settings_connection_get_volatile (settings_connection)) { g_variant_builder_add (&connection_props, "{sv}", NMD_CONNECTION_PROPS_EXTERNAL, g_variant_new_boolean (TRUE)); diff --git a/src/nm-manager.c b/src/nm-manager.c index 63a0820e83..4430cb4ccf 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -272,7 +272,7 @@ active_connection_remove (NMManager *self, NMActiveConnection *active) if ( nm_active_connection_get_assumed (active) && (connection = nm_active_connection_get_settings_connection (active)) - && nm_settings_connection_get_nm_generated_assumed (connection)) + && nm_settings_connection_get_volatile (connection)) g_object_ref (connection); else connection = NULL; @@ -1697,7 +1697,7 @@ done: static gboolean match_connection_filter (NMConnection *connection, gpointer user_data) { - if (nm_settings_connection_get_nm_generated_assumed (NM_SETTINGS_CONNECTION (connection))) + if (nm_settings_connection_get_volatile (NM_SETTINGS_CONNECTION (connection))) return FALSE; return nm_device_check_connection_compatible (NM_DEVICE (user_data), connection); @@ -1800,7 +1800,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; 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, From f84b8f7afc2d5627859897deeb03c296bcdabe6c Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 26 Sep 2016 14:45:35 +0200 Subject: [PATCH 11/24] device: pass the user-explict flag to nm_device_realize_start() No change in behavior yet, because for unrealized devices the user-explict unmanaged flag is always cleared. The new option is still unused. --- src/devices/nm-device.c | 21 +++++++++++++++++---- src/devices/nm-device.h | 1 + src/nm-manager.c | 18 +++++++++++++++--- 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index a1fb1322f8..ad80c2e94d 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -501,7 +501,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); @@ -2374,6 +2376,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 * @@ -2389,6 +2393,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) { @@ -2412,7 +2417,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; } @@ -2452,7 +2457,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)) { @@ -2533,6 +2538,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 @@ -2541,7 +2547,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; @@ -2662,6 +2670,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, diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index f98978bdc0..0814ddc089 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -595,6 +595,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, diff --git a/src/nm-manager.c b/src/nm-manager.c index 4430cb4ccf..2171260240 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -2133,7 +2133,11 @@ 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); } else { @@ -2206,7 +2210,11 @@ 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); return; @@ -2259,7 +2267,11 @@ platform_link_added (NMManager *self, if (device) { gs_free_error GError *error = NULL; - if (nm_device_realize_start (device, plink, NULL, &error)) { + if (nm_device_realize_start (device, + plink, + NM_UNMAN_FLAG_OP_FORGET, + NULL, + &error)) { add_device (self, device, NULL); _device_realize_finish (self, device, plink); } else { From ae4535ba7b79fa8f9707c429cb7909193cf144fe Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 26 Sep 2016 14:51:23 +0200 Subject: [PATCH 12/24] device: set user-explicit unmanaged flag based on loaded device-state On restart, the device state may be stored in /var/run. Reuse it to set the managed flag. --- src/nm-manager.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/nm-manager.c b/src/nm-manager.c index 2171260240..f239d5f32b 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -2266,10 +2266,24 @@ 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, - NM_UNMAN_FLAG_OP_FORGET, + unmanaged_user_explicit, NULL, &error)) { add_device (self, device, NULL); From 8a31e66d2cffbedb2efa39d7e6d38d1dfe51cb61 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 7 Mar 2017 11:04:36 +0100 Subject: [PATCH 13/24] core: add activation-type property to active-connection It is still unused, but will be useful to mark a connection whether it is a full activation or assumed. --- src/nm-act-request.c | 3 +++ src/nm-act-request.h | 1 + src/nm-active-connection.c | 34 +++++++++++++++++++++++++++++++++- src/nm-active-connection.h | 3 +++ src/nm-checkpoint.c | 1 + src/nm-core-utils.c | 8 ++++++++ src/nm-core-utils.h | 6 ++++++ src/nm-manager.c | 20 ++++++++++++++++++-- src/nm-manager.h | 1 + src/nm-policy.c | 3 +++ src/nm-types.h | 11 +++++++++++ 11 files changed, 88 insertions(+), 3 deletions(-) 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 a96f33b432..95b81b1d8d 100644 --- a/src/nm-active-connection.c +++ b/src/nm-active-connection.c @@ -52,6 +52,8 @@ typedef struct _NMActiveConnectionPrivate { bool assumed:1; bool master_ready:1; + NMActivationType activation_type:3; + NMAuthSubject *subject; NMActiveConnection *master; @@ -87,6 +89,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMActiveConnection, PROP_INT_SUBJECT, PROP_INT_MASTER, PROP_INT_MASTER_READY, + PROP_INT_ACTIVATION_TYPE, ); enum { @@ -711,6 +714,14 @@ nm_active_connection_set_master (NMActiveConnection *self, NMActiveConnection *m check_master_ready (self); } +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; +} + void nm_active_connection_set_assumed (NMActiveConnection *self, gboolean assumed) { @@ -1057,6 +1068,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: @@ -1081,6 +1093,13 @@ 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)) + 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 */ @@ -1116,6 +1135,7 @@ nm_active_connection_init (NMActiveConnection *self) _LOGT ("creating"); + priv->activation_type = NM_ACTIVATION_TYPE_MANAGED; priv->version_id = _version_id_new (); } @@ -1135,7 +1155,10 @@ constructed (GObject *object) 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); } @@ -1320,6 +1343,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_ASSUME, + 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..0c2e2358d5 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" @@ -163,6 +164,8 @@ void nm_active_connection_set_assumed (NMActiveConnection *self, 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); #endif /* __NETWORKMANAGER_ACTIVE_CONNECTION_H__ */ 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-core-utils.c b/src/nm-core-utils.c index ead86d4775..25b1262193 100644 --- a/src/nm-core-utils.c +++ b/src/nm-core-utils.c @@ -4339,3 +4339,11 @@ 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"), +) 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-manager.c b/src/nm-manager.c index f239d5f32b..4218530870 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); @@ -1835,7 +1836,8 @@ assume_connection (NMManager *self, NMDevice *device, NMSettingsConnection *conn 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); + active = _new_active_connection (self, NM_CONNECTION (connection), NULL, NULL, + device, subject, NM_ACTIVATION_TYPE_MANAGED, &error); g_object_unref (subject); if (!active) { @@ -2762,6 +2764,7 @@ ensure_master_active_connection (NMManager *self, NULL, master_device, subject, + NM_ACTIVATION_TYPE_MANAGED, error); return master_ac; } @@ -2807,6 +2810,7 @@ ensure_master_active_connection (NMManager *self, NULL, candidate, subject, + NM_ACTIVATION_TYPE_MANAGED, error); return master_ac; } @@ -2953,6 +2957,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); @@ -3110,7 +3115,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; @@ -3305,6 +3311,7 @@ _new_active_connection (NMManager *self, const char *specific_object, NMDevice *device, NMAuthSubject *subject, + NMActivationType activation_type, GError **error) { NMSettingsConnection *settings_connection = NULL; @@ -3333,6 +3340,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, @@ -3344,6 +3353,7 @@ _new_active_connection (NMManager *self, applied, specific_object, subject, + activation_type, device); } @@ -3396,6 +3406,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. @@ -3415,6 +3427,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); @@ -3461,6 +3474,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); @@ -3704,6 +3718,7 @@ impl_manager_activate_connection (NMManager *self, specific_object_path, device, subject, + NM_ACTIVATION_TYPE_MANAGED, &error); if (!active) goto error; @@ -3923,6 +3938,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 2cba2852a3..66c9895c8d 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -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..cf5f4cb0a9 100644 --- a/src/nm-types.h +++ b/src/nm-types.h @@ -55,6 +55,17 @@ 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, +} NMActivationType; + typedef enum { /* In priority order; higher number == higher priority */ From 3973f8ebcd8f439eee6cb816d5bd6742e8ac5a85 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 8 Mar 2017 08:26:48 +0100 Subject: [PATCH 14/24] active-connection: use activation-type for active connection instead of assumed flag --- src/nm-active-connection.c | 19 ++----------------- src/nm-active-connection.h | 3 --- src/nm-manager.c | 3 +-- 3 files changed, 3 insertions(+), 22 deletions(-) diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c index 95b81b1d8d..60e87fc313 100644 --- a/src/nm-active-connection.c +++ b/src/nm-active-connection.c @@ -49,7 +49,6 @@ typedef struct _NMActiveConnectionPrivate { bool is_default6:1; bool state_set:1; bool vpn:1; - bool assumed:1; bool master_ready:1; NMActivationType activation_type:3; @@ -568,7 +567,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_MANAGED) { 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); } @@ -722,24 +721,10 @@ nm_active_connection_get_activation_type (NMActiveConnection *self) return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->activation_type; } -void -nm_active_connection_set_assumed (NMActiveConnection *self, gboolean assumed) -{ - NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self); - - g_return_if_fail (priv->assumed == FALSE); - priv->assumed = assumed; - - 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); - } -} - gboolean nm_active_connection_get_assumed (NMActiveConnection *self) { - return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->assumed; + return nm_active_connection_get_activation_type (self) == NM_ACTIVATION_TYPE_ASSUME; } /*****************************************************************************/ diff --git a/src/nm-active-connection.h b/src/nm-active-connection.h index 0c2e2358d5..d99a959e90 100644 --- a/src/nm-active-connection.h +++ b/src/nm-active-connection.h @@ -159,9 +159,6 @@ 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); diff --git a/src/nm-manager.c b/src/nm-manager.c index 4218530870..1995ccce6a 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -1837,7 +1837,7 @@ assume_connection (NMManager *self, NMDevice *device, NMSettingsConnection *conn subject = nm_auth_subject_new_internal (); active = _new_active_connection (self, NM_CONNECTION (connection), NULL, NULL, - device, subject, NM_ACTIVATION_TYPE_MANAGED, &error); + device, subject, NM_ACTIVATION_TYPE_ASSUME, &error); g_object_unref (subject); if (!active) { @@ -1853,7 +1853,6 @@ assume_connection (NMManager *self, NMDevice *device, NMSettingsConnection *conn 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)); From fa015f2aab960bc4cf2da79a85b99d2cdb36e7bd Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 8 Mar 2017 08:32:17 +0100 Subject: [PATCH 15/24] core/trivial: rename activation-type related checks for device and active-connection nm_device_uses_assumed_connection() basically called nm_active_connection_get_assumed() on the device. Rename those functions to be closer to the activation-type flags. The concepts of "assume", "external", and "assume_or_external" will make sense with the following commits. --- src/devices/nm-device-vlan.c | 2 +- src/devices/nm-device.c | 64 +++++++++++++++---------------- src/devices/nm-device.h | 2 +- src/devices/team/nm-device-team.c | 2 +- src/nm-active-connection.c | 2 +- src/nm-active-connection.h | 2 +- src/nm-manager.c | 6 +-- 7 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c index 54d0440960..4bee5497c2 100644 --- a/src/devices/nm-device-vlan.c +++ b/src/devices/nm-device-vlan.c @@ -96,7 +96,7 @@ parent_hwaddr_maybe_changed (NMDevice *parent, NMSettingIPConfig *s_ip6; /* Never touch assumed devices */ - if (nm_device_uses_assumed_connection ((NMDevice *) self)) + if (nm_device_has_activation_type_assume_or_external ((NMDevice *) self)) return; connection = nm_device_get_applied_connection ((NMDevice *) self); diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index ad80c2e94d..83027588b6 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -1599,13 +1599,13 @@ nm_device_get_physical_port_id (NMDevice *self) /*****************************************************************************/ static gboolean -nm_device_uses_generated_assumed_connection (NMDevice *self) +nm_device_has_activation_type_external (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))) { + && nm_active_connection_has_activation_type_assume_or_external (NM_ACTIVE_CONNECTION (priv->act_request))) { connection = nm_act_request_get_settings_connection (priv->act_request); if ( connection && nm_settings_connection_get_volatile (connection)) @@ -1615,12 +1615,12 @@ nm_device_uses_generated_assumed_connection (NMDevice *self) } gboolean -nm_device_uses_assumed_connection (NMDevice *self) +nm_device_has_activation_type_assume_or_external (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); if ( priv->act_request - && nm_active_connection_get_assumed (NM_ACTIVE_CONNECTION (priv->act_request))) + && nm_active_connection_has_activation_type_assume_or_external (NM_ACTIVE_CONNECTION (priv->act_request))) return TRUE; return FALSE; } @@ -3154,7 +3154,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_has_activation_type_external (self)) return; reason = priv->state_reason; @@ -4192,7 +4192,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_active_connection_has_activation_type_assume_or_external (active) ? FALSE : TRUE); } static void @@ -4272,7 +4272,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_active_connection_has_activation_type_assume_or_external (active)) { NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE; ret = NM_DEVICE_GET_CLASS (self)->act_stage1_prepare (self, &failure_reason); @@ -4370,7 +4370,7 @@ activate_stage2_device_config (NMDevice *self) 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_active_connection_has_activation_type_assume_or_external (active)) { NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE; if (!nm_device_bring_up (self, FALSE, &no_firmware)) { @@ -4398,7 +4398,7 @@ 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 ( nm_device_has_activation_type_external (self) && slave_state <= NM_DEVICE_STATE_DISCONNECTED) nm_device_queue_recheck_assume (info->slave); } @@ -4499,7 +4499,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_has_activation_type_assume_or_external (self)) { /* We have assumed configuration, but couldn't redo it. No problem, * move to check state. */ _set_ip_state (self, AF_INET, IP_DONE); @@ -4691,7 +4691,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_has_activation_type_assume_or_external (self)) { /* DAD not needed, signal success */ cb (self, configs, TRUE); @@ -4992,7 +4992,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_has_activation_type_assume_or_external (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); @@ -5018,7 +5018,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_has_activation_type_assume_or_external (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); @@ -5160,7 +5160,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_has_activation_type_external (self) && !auto_method) goto END_ADD_DEFAULT_ROUTE; /* At this point, we treat assumed and non-assumed connections alike. @@ -5236,7 +5236,7 @@ END_ADD_DEFAULT_ROUTE: routes_full_sync = commit && priv->v4_commit_first_time - && !nm_device_uses_assumed_connection (self); + && !nm_device_has_activation_type_assume_or_external (self); success = nm_device_set_ip4_config (self, composite, default_route_metric, commit, routes_full_sync); g_object_unref (composite); @@ -5309,7 +5309,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_has_activation_type_assume_or_external (self)) { dhcp_schedule_restart (self, AF_INET, "connection is assumed"); return; } @@ -5907,7 +5907,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_has_activation_type_external (self) && !auto_method) goto END_ADD_DEFAULT_ROUTE; /* At this point, we treat assumed and non-assumed connections alike. @@ -5989,7 +5989,7 @@ END_ADD_DEFAULT_ROUTE: routes_full_sync = commit && priv->v6_commit_first_time - && !nm_device_uses_assumed_connection (self); + && !nm_device_has_activation_type_assume_or_external (self); success = nm_device_set_ip6_config (self, composite, commit, routes_full_sync); g_object_unref (composite); @@ -6103,7 +6103,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_has_activation_type_assume_or_external (self)) { dhcp_schedule_restart (self, AF_INET6, "connection is assumed"); return; } @@ -6688,7 +6688,7 @@ _commit_mtu (NMDevice *self, const NMIP4Config *config) if (ifindex <= 0) return; - if (nm_device_uses_assumed_connection (self)) { + if (nm_device_has_activation_type_assume_or_external (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; @@ -7355,7 +7355,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_has_activation_type_assume_or_external (self)) set_nm_ipv6ll (self, TRUE); /* Re-enable IPv6 on the interface */ @@ -7385,7 +7385,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_has_activation_type_assume_or_external (self)) { switch (ip6_privacy) { case NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN: case NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED: @@ -7628,7 +7628,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_has_activation_type_external (self)) priv->fw_ready = TRUE; else { if (!priv->fw_call) { @@ -7930,7 +7930,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_has_activation_type_assume_or_external (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)); @@ -8079,7 +8079,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_has_activation_type_assume_or_external (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)); @@ -9307,7 +9307,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_has_activation_type_assume_or_external (self); _commit_mtu (self, new_config); /* For assumed devices we must not touch the kernel-routes, such as the device-route. @@ -9358,7 +9358,7 @@ 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)) { + if (nm_device_has_activation_type_external (self)) { NMConnection *settings_connection = NM_CONNECTION (nm_device_get_settings_connection (self)); NMSetting *s_ip4; @@ -9512,7 +9512,7 @@ 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)) { + if (nm_device_has_activation_type_external (self)) { NMConnection *settings_connection = NM_CONNECTION (nm_device_get_settings_connection (self)); NMSetting *s_ip6; @@ -10991,7 +10991,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_has_activation_type_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), @@ -11492,7 +11492,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_has_activation_type_external (self)) { nm_firewall_manager_remove_from_zone (nm_firewall_manager_get (), nm_device_get_ip_iface (self), NULL, @@ -12204,7 +12204,7 @@ _set_state_full (NMDevice *self, */ _cancel_activation (self); - if (nm_device_uses_assumed_connection (self)) { + if (nm_device_has_activation_type_assume_or_external (self)) { /* Avoid tearing down assumed connection, assume it's connected */ nm_device_queue_state (self, NM_DEVICE_STATE_ACTIVATED, @@ -12242,7 +12242,7 @@ _set_state_full (NMDevice *self, if ( applied_connection && priv->ifindex != priv->ip_ifindex - && !nm_device_uses_generated_assumed_connection (self)) { + && !nm_device_has_activation_type_external (self)) { NMSettingConnection *s_con; const char *zone; diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index 0814ddc089..2aca285eac 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -489,7 +489,7 @@ 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_has_activation_type_assume_or_external (NMDevice *device); gboolean nm_device_unmanage_on_quit (NMDevice *self); diff --git a/src/devices/team/nm-device-team.c b/src/devices/team/nm-device-team.c index 5a94e76df2..d7cbd3660e 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_has_activation_type_assume_or_external (device)) nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED); } } diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c index 60e87fc313..78dd95a937 100644 --- a/src/nm-active-connection.c +++ b/src/nm-active-connection.c @@ -722,7 +722,7 @@ nm_active_connection_get_activation_type (NMActiveConnection *self) } gboolean -nm_active_connection_get_assumed (NMActiveConnection *self) +nm_active_connection_has_activation_type_assume_or_external (NMActiveConnection *self) { return nm_active_connection_get_activation_type (self) == NM_ACTIVATION_TYPE_ASSUME; } diff --git a/src/nm-active-connection.h b/src/nm-active-connection.h index d99a959e90..15f69733da 100644 --- a/src/nm-active-connection.h +++ b/src/nm-active-connection.h @@ -159,7 +159,7 @@ void nm_active_connection_set_master (NMActiveConnection *self, void nm_active_connection_set_parent (NMActiveConnection *self, NMActiveConnection *parent); -gboolean nm_active_connection_get_assumed (NMActiveConnection *self); +gboolean nm_active_connection_has_activation_type_assume_or_external (NMActiveConnection *self); NMActivationType nm_active_connection_get_activation_type (NMActiveConnection *self); diff --git a/src/nm-manager.c b/src/nm-manager.c index 1995ccce6a..831b04820a 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -271,7 +271,7 @@ 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) + if ( nm_active_connection_has_activation_type_assume_or_external (active) && (connection = nm_active_connection_get_settings_connection (active)) && nm_settings_connection_get_volatile (connection)) g_object_ref (connection); @@ -802,13 +802,13 @@ 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_active_connection_has_activation_type_assume_or_external (ac)) { 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_active_connection_has_activation_type_assume_or_external (ac)) { if (best_state < NM_STATE_DISCONNECTING) best_state = NM_STATE_DISCONNECTING; } From bed2fa1bec3af102c60a3871d0f86a546b7c2a0c Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 8 Mar 2017 12:22:01 +0100 Subject: [PATCH 16/24] core: track external activations types in the active-connection We need a distinction between external activations and assuming connections. The former shall have the meaning of devices that are *not* managed by NetworkManager, the latter are configurations that are gracefully taken over after restart (but fully managed). Express that in the activation-type of the active connection. Also, no longer use the settings NM_SETTINGS_CONNECTION_FLAGS_VOLATILE flag to determine whether an assumed connection is "external". These concepts are entirely orthogonal (although in pratice, external activations are in-memory and flagged as volatile, but the inverse is not necessarily true). Also change match_connection_filter() to consider all connections. Later, we only call nm_utils_match_connection() for the connection we want to assume -- which will be a regular settings connection, not a generated one. --- src/devices/nm-device.c | 20 ++++++---------- src/nm-active-connection.c | 14 +++++++---- src/nm-core-utils.c | 5 ++-- src/nm-dispatcher.c | 49 ++++++++++++++++++++++++++------------ src/nm-manager.c | 14 ++++++----- src/nm-types.h | 5 ++++ 6 files changed, 67 insertions(+), 40 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 83027588b6..efa365c77a 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -1602,16 +1602,10 @@ static gboolean nm_device_has_activation_type_external (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMSettingsConnection *connection; - if ( priv->act_request - && nm_active_connection_has_activation_type_assume_or_external (NM_ACTIVE_CONNECTION (priv->act_request))) { - connection = nm_act_request_get_settings_connection (priv->act_request); - if ( connection - && nm_settings_connection_get_volatile (connection)) - return TRUE; - } - return FALSE; + return priv->act_request + && NM_IN_SET (nm_active_connection_get_activation_type (NM_ACTIVE_CONNECTION (priv->act_request)), + NM_ACTIVATION_TYPE_EXTERNAL); } gboolean @@ -1619,10 +1613,10 @@ nm_device_has_activation_type_assume_or_external (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - if ( priv->act_request - && nm_active_connection_has_activation_type_assume_or_external (NM_ACTIVE_CONNECTION (priv->act_request))) - return TRUE; - return FALSE; + return priv->act_request + && NM_IN_SET (nm_active_connection_get_activation_type (NM_ACTIVE_CONNECTION (priv->act_request)), + NM_ACTIVATION_TYPE_ASSUME, + NM_ACTIVATION_TYPE_EXTERNAL); } static SlaveInfo * diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c index 78dd95a937..c4cd6c85cd 100644 --- a/src/nm-active-connection.c +++ b/src/nm-active-connection.c @@ -51,6 +51,8 @@ typedef struct _NMActiveConnectionPrivate { bool vpn:1; bool master_ready:1; + /* TODO: when the user updates a connection with an extern activation + * type, the activation type must be updated to FULL. */ NMActivationType activation_type:3; NMAuthSubject *subject; @@ -567,7 +569,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->activation_type == NM_ACTIVATION_TYPE_MANAGED) { + 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); } @@ -724,7 +726,9 @@ nm_active_connection_get_activation_type (NMActiveConnection *self) gboolean nm_active_connection_has_activation_type_assume_or_external (NMActiveConnection *self) { - return nm_active_connection_get_activation_type (self) == NM_ACTIVATION_TYPE_ASSUME; + return NM_IN_SET (nm_active_connection_get_activation_type (self), + NM_ACTIVATION_TYPE_ASSUME, + NM_ACTIVATION_TYPE_EXTERNAL); } /*****************************************************************************/ @@ -1081,7 +1085,9 @@ set_property (GObject *object, guint prop_id, 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)) + 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; @@ -1331,7 +1337,7 @@ nm_active_connection_class_init (NMActiveConnectionClass *ac_class) obj_properties[PROP_INT_ACTIVATION_TYPE] = g_param_spec_int (NM_ACTIVE_CONNECTION_INT_ACTIVATION_TYPE, "", "", NM_ACTIVATION_TYPE_MANAGED, - NM_ACTIVATION_TYPE_ASSUME, + NM_ACTIVATION_TYPE_EXTERNAL, NM_ACTIVATION_TYPE_MANAGED, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c index 25b1262193..adef77e296 100644 --- a/src/nm-core-utils.c +++ b/src/nm-core-utils.c @@ -4344,6 +4344,7 @@ nm_utils_format_con_diff_for_audit (GHashTable *diff) 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_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-dispatcher.c b/src/nm-dispatcher.c index 4fa4ce6aba..1bb26e1c45 100644 --- a/src/nm-dispatcher.c +++ b/src/nm-dispatcher.c @@ -478,9 +478,10 @@ dispatcher_idle_cb (gpointer user_data) static gboolean _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, @@ -575,7 +576,7 @@ _dispatcher_call (NMDispatcherAction action, NMD_CONNECTION_PROPS_FILENAME, g_variant_new_string (filename)); } - if (nm_settings_connection_get_volatile (settings_connection)) { + if (activation_type_external) { g_variant_builder_add (&connection_props, "{sv}", NMD_CONNECTION_PROPS_EXTERNAL, g_variant_new_boolean (TRUE)); @@ -711,8 +712,10 @@ nm_dispatcher_call_hostname (NMDispatcherFunc callback, gpointer user_data, guint *out_call_id) { - return _dispatcher_call (NM_DISPATCHER_ACTION_HOSTNAME, FALSE, NULL, NULL, NULL, - NM_CONNECTIVITY_UNKNOWN, NULL, NULL, NULL, NULL, + 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); } @@ -748,10 +751,12 @@ nm_dispatcher_call_device (NMDispatcherAction action, } 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), - device, - NM_CONNECTIVITY_UNKNOWN, NULL, NULL, NULL, NULL, + 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); } @@ -780,10 +785,12 @@ nm_dispatcher_call_device_sync (NMDispatcherAction action, } 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), - device, - NM_CONNECTIVITY_UNKNOWN, NULL, NULL, NULL, NULL, + 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); } @@ -820,9 +827,14 @@ nm_dispatcher_call_vpn (NMDispatcherAction action, 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); } /** @@ -851,9 +863,14 @@ nm_dispatcher_call_vpn_sync (NMDispatcherAction 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); } /** @@ -874,7 +891,9 @@ nm_dispatcher_call_connectivity (NMConnectivityState connectivity_state, gpointer user_data, guint *out_call_id) { - return _dispatcher_call (NM_DISPATCHER_ACTION_CONNECTIVITY_CHANGE, FALSE, NULL, NULL, NULL, connectivity_state, + 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); } diff --git a/src/nm-manager.c b/src/nm-manager.c index 831b04820a..e273bff8c9 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -1698,9 +1698,6 @@ done: static gboolean match_connection_filter (NMConnection *connection, gpointer user_data) { - if (nm_settings_connection_get_volatile (NM_SETTINGS_CONNECTION (connection))) - return FALSE; - return nm_device_check_connection_compatible (NM_DEVICE (user_data), connection); } @@ -1818,7 +1815,10 @@ get_existing_connection (NMManager *self, NMDevice *device, gboolean *out_genera } static gboolean -assume_connection (NMManager *self, NMDevice *device, NMSettingsConnection *connection) +assume_connection (NMManager *self, + NMDevice *device, + NMSettingsConnection *connection, + gboolean generated) { NMActiveConnection *active, *master_ac; NMAuthSubject *subject; @@ -1837,7 +1837,9 @@ assume_connection (NMManager *self, NMDevice *device, NMSettingsConnection *conn subject = nm_auth_subject_new_internal (); active = _new_active_connection (self, NM_CONNECTION (connection), NULL, NULL, - device, subject, NM_ACTIVATION_TYPE_ASSUME, &error); + device, subject, + generated ? NM_ACTIVATION_TYPE_EXTERNAL : NM_ACTIVATION_TYPE_ASSUME, + &error); g_object_unref (subject); if (!active) { @@ -1895,7 +1897,7 @@ recheck_assume_connection (NMManager *self, NMDevice *device) NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); } - success = assume_connection (self, device, connection); + success = assume_connection (self, device, connection, generated); if (!success) { if (was_unmanaged) { nm_device_state_changed (device, diff --git a/src/nm-types.h b/src/nm-types.h index cf5f4cb0a9..32f4198ad7 100644 --- a/src/nm-types.h +++ b/src/nm-types.h @@ -64,6 +64,11 @@ typedef enum { /* 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 { From b32746cec365f3b71d450b1d528c609408298dae Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 8 Mar 2017 08:45:11 +0100 Subject: [PATCH 17/24] core: only assume connections that were managed in a previous run of NetworkManager Before, we would have the concept of assumed connections, which is used for (1) externally configured device that NetworkManager should not touch and (2) connections that NetworkManager should gracefully take over after a restart (seamlessly, non-destructively). The behavior was unclear and mixed. It wasn't clear whether the device is in no-touch mode (1) or gracefully take-over (2). Previous commits already introduce separate activation types EXTERNAL (1) and ASSUME (2). Also, previously, we would for both (1) and (2) try to find a matching connection and use it. That doesn't make sense for either. In the external case (1), we should not pretend that an existing connection is active. Let's always create a new in-memory connection for these cases. Note that this means, external devices now will always generate a connection, instead of pretending an existing one is active. For the assume case (2), we shall not use nm_utils_match_connection() to guess which connection might be active. It can only the one that was active on a previous run of NetworkManager. So, use the information from the state file and try to activate it. If that fails, it is not an assume activation type. Note, that this means we now most of the time don't do ASSUME anymore. Most of the time we do EXTERNAL activation That is because the state information is only available after restart of NetworkManager. --- src/nm-manager.c | 74 ++++++++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 30 deletions(-) diff --git a/src/nm-manager.c b/src/nm-manager.c index e273bff8c9..2531dafe4d 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -1705,18 +1705,22 @@ 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; @@ -1764,30 +1768,34 @@ get_existing_connection (NMManager *self, NMDevice *device, gboolean *out_genera * When no configured connection matches the generated connection, we keep * the generated connection instead. */ - { + if (assume_connection_uuid) { + gs_free_slist GSList *connections = NULL; gs_free NMSettingsConnection **cons = NULL; + NMSettingsConnection *matched; 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]); + for (i = 0; i < len; i++) { + if (nm_streq0 (assume_connection_uuid, nm_connection_get_uuid (NM_CONNECTION (cons[i])))) { + connections = g_slist_append (NULL, cons[i]); + break; + } + } 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; + 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'", @@ -1864,7 +1872,9 @@ assume_connection (NMManager *self, } 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; @@ -1883,7 +1893,7 @@ recheck_assume_connection (NMManager *self, NMDevice *device) if (state > NM_DEVICE_STATE_DISCONNECTED) return FALSE; - connection = get_existing_connection (self, device, &generated); + 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)); @@ -1919,7 +1929,7 @@ recheck_assume_connection (NMManager *self, NMDevice *device) 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 @@ -1980,7 +1990,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)); @@ -1990,7 +2003,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 @@ -2142,7 +2155,7 @@ factory_device_added_cb (NMDeviceFactory *factory, 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); @@ -2219,7 +2232,7 @@ platform_link_added (NMManager *self, &compatible, &error)) { /* Success */ - _device_realize_finish (self, candidate, plink); + _device_realize_finish (self, candidate, plink, NULL); return; } @@ -2290,7 +2303,8 @@ platform_link_added (NMManager *self, 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); From bde67825918669bc7a6eb31669ea806a960a3ac4 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 8 Mar 2017 15:58:59 +0100 Subject: [PATCH 18/24] core: upgrade EXTERNAL activation type when user saves connection An EXTERNAL activation type comes with a nm-generated, volatile, in-memory connection. When the user actively modifies that connection, we shall mark the active connection as fully managed. --- src/nm-active-connection.c | 51 +++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c index c4cd6c85cd..29c7334950 100644 --- a/src/nm-active-connection.c +++ b/src/nm-active-connection.c @@ -51,8 +51,6 @@ typedef struct _NMActiveConnectionPrivate { bool vpn:1; bool master_ready:1; - /* TODO: when the user updates a connection with an extern activation - * type, the activation type must be updated to FULL. */ NMActivationType activation_type:3; NMAuthSubject *subject; @@ -105,8 +103,13 @@ 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); /*****************************************************************************/ @@ -184,12 +187,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); } } @@ -723,6 +729,21 @@ nm_active_connection_get_activation_type (NMActiveConnection *self) 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); + + if (priv->activation_type == activation_type) + return; + + _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; +} + gboolean nm_active_connection_has_activation_type_assume_or_external (NMActiveConnection *self) { @@ -733,6 +754,26 @@ nm_active_connection_has_activation_type_assume_or_external (NMActiveConnection /*****************************************************************************/ +static void +_settings_connection_notify_flags (NMSettingsConnection *settings_connection, + GParamSpec *param, + NMActiveConnection *self) +{ + 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)); +} + +/*****************************************************************************/ + static void unwatch_parent (NMActiveConnection *self, gboolean unref); static void @@ -1138,10 +1179,8 @@ 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); From 7a5e0c7fd77ecf158a668ccf979378a7ac58438f Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 8 Mar 2017 16:06:21 +0100 Subject: [PATCH 19/24] core: once activated an assumed connection make it NM_ACTIVATION_TYPE_MANAGED --- src/nm-active-connection.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c index 29c7334950..1cdef98cef 100644 --- a/src/nm-active-connection.c +++ b/src/nm-active-connection.c @@ -110,6 +110,8 @@ 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); /*****************************************************************************/ @@ -223,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; From b152c0a19fb6661114a0ffcbf24d8fd143d048f5 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 9 Mar 2017 16:58:37 +0100 Subject: [PATCH 20/24] manager: merge/inline assume_connection() in recheck_assume_connection() There is only one caller of assume_connection(). The tasks there are not clearly separate and it is clearer just to have one large recheck_assume_connection() function which proceeds step by step, instead of breaking it into separate parts and move them apart in the source code. The latter implies that -- unless we forward-declare assume_connection() -- the order of definition with assume_connection,recheck_assume_connection is contrary the flow of the code. Having a separate function in this case is not a simplification so merge it. --- src/nm-manager.c | 122 ++++++++++++++++++++++------------------------- 1 file changed, 56 insertions(+), 66 deletions(-) diff --git a/src/nm-manager.c b/src/nm-manager.c index 2531dafe4d..1520849f35 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -1822,62 +1822,14 @@ get_existing_connection (NMManager *self, return added ? added : NULL; } -static gboolean -assume_connection (NMManager *self, - NMDevice *device, - NMSettingsConnection *connection, - gboolean generated) -{ - 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, - generated ? NM_ACTIVATION_TYPE_EXTERNAL : NM_ACTIVATION_TYPE_ASSUME, - &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_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, 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); @@ -1900,30 +1852,68 @@ recheck_assume_connection (NMManager *self, return FALSE; } + _LOGD (LOGD_DEVICE, "(%s): will attempt to assume connection", + nm_device_get_iface (device)); + + /* 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); } - - success = assume_connection (self, device, connection, generated); - if (!success) { - 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)); - - nm_settings_connection_delete (connection, NULL, NULL); - } + 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); } - return success; + 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)); + + nm_settings_connection_delete (connection, NULL, NULL); + } + 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 TRUE; } static void From 02f6bfeae26a58adc9257247c0ac31d0e741dac7 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 13 Mar 2017 14:01:47 +0100 Subject: [PATCH 21/24] manager: cleanup find_ac_for_connection() in "nm-manager.c" - rename find_ac_for_connection() to active_connection_find_first_by_connection(). This function has the unexpected(?) behavior to either search by the @connection using pointer identity, or by looking up the UUID (depending on whether @connection is a NMSettingsConnection). - Split out a active_connection_find_first() part. The name "find-first" makes it clear that we walk the list until a matching active-connection is found. That's why I added the max_state argument. Otherwise, it would have to be called "find-first-non-disconnected". - drop nm_manager_get_connection_device(). It only had two callers. It also used the ambiguity of the @connection argument, but only one of the two callers cared about that. Meaning, _internal_activate_device() now explicitly does a lookup by the NMSettingsConnection. --- src/nm-manager.c | 94 +++++++++++++++++++++++++++--------------------- 1 file changed, 54 insertions(+), 40 deletions(-) diff --git a/src/nm-manager.c b/src/nm-manager.c index 1520849f35..c76ffc2a82 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -397,46 +397,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. @@ -2441,28 +2455,22 @@ nm_manager_get_device_paths (NMManager *self) return (const char **) g_ptr_array_free (paths, FALSE); } -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; @@ -2660,8 +2668,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; @@ -3054,6 +3064,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; @@ -3215,9 +3226,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)) @@ -3327,7 +3341,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", From 72de503d3918506b17caba3265c593f433037d85 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 13 Mar 2017 14:48:06 +0100 Subject: [PATCH 22/24] manager: simplify searching assumed connection Now we only search for a candiate with matching UUID. No need to first lookup all activatable connections, just find the candidate by UUID and see if it is activatable. --- src/NetworkManagerUtils.c | 10 +++--- src/NetworkManagerUtils.h | 2 +- src/nm-manager.c | 22 ++++++------- src/tests/test-general.c | 66 ++++++++++++++++++++++++++------------- 4 files changed, 61 insertions(+), 39 deletions(-) diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index 5f40d392af..fbca3b82f3 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -715,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, @@ -724,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/nm-manager.c b/src/nm-manager.c index c76ffc2a82..c7e79c092a 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -1739,6 +1739,7 @@ get_existing_connection (NMManager *self, GError *error = NULL; NMDevice *master = NULL; int ifindex = nm_device_get_ifindex (device); + NMSettingsConnection *matched; if (out_generated) *out_generated = FALSE; @@ -1782,20 +1783,15 @@ get_existing_connection (NMManager *self, * When no configured connection matches the generated connection, we keep * the generated connection instead. */ - if (assume_connection_uuid) { - gs_free_slist GSList *connections = NULL; - gs_free NMSettingsConnection **cons = NULL; - NMSettingsConnection *matched; - guint i, len; + 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, + }; - cons = nm_manager_get_activatable_connections (self, &len, FALSE); - for (i = 0; i < len; i++) { - if (nm_streq0 (assume_connection_uuid, nm_connection_get_uuid (NM_CONNECTION (cons[i])))) { - connections = g_slist_append (NULL, cons[i]); - break; - } - } - 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), 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); } From 9395f163f46d925b1de51f591e1f27f94cab2d67 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 16 Mar 2017 16:14:23 +0100 Subject: [PATCH 23/24] manager: always cleanup volatile settings-connection on active-connection removal This is not only relevant if the active connection is assumed/external. --- src/nm-manager.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/nm-manager.c b/src/nm-manager.c index c7e79c092a..0cd534f15f 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -271,8 +271,7 @@ 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_has_activation_type_assume_or_external (active) - && (connection = nm_active_connection_get_settings_connection (active)) + if ( (connection = nm_active_connection_get_settings_connection (active)) && nm_settings_connection_get_volatile (connection)) g_object_ref (connection); else From 850c977953e4de3c8bbee64a3d2e8726c971761c Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 13 Mar 2017 15:34:14 +0100 Subject: [PATCH 24/24] device: track system interface state in NMDevice When deciding whether to touch a device we sometimes look at whether the active connection is external/assumed. In many cases however, there is no active connection around (e.g. while moving the device from state unmanaged to disconnected before assuming). So in most cases we instead look at the device-state-reason to decide whether to touch the interface (see nm_device_state_reason_check()). Often it's desirable to have no state and passing data as function arguments. However, the state reason has to be passed along several hops (e.g. a queued state change). Or a change to a master/slave can affect the slave/master, where we pass on the state reason. Or an intermediate event might invalidate a previous state reason. Passing the state whether to touch a device or not as a state-reason is cumbersome and limited. Instead, the device should be aware of whats going on. Add a sys-iface-state with: - SYS_IFACE_STATE_EXTERNAL: meaning, NM should not touch it - SYS_IFACE_STATE_ASSUME: meaning, NM is gracefully taking over - SYS_IFACE_STATE_MANAGED: meaning, the device is managed by NM - SYS_IFACE_STATE_REMOVED: the device no longer exists This replaces most checks of nm_device_state_reason_check() and nm_active_connection_get_activation_type() by instead looking at the sys-iface-state of the device. This patch probably has still issues, but the previous behavior was not very clear either. We will need to identify those issues in future tests and tweak the behavior. At least, now there is one flag that describes how to behave. --- src/devices/nm-device-vlan.c | 5 +- src/devices/nm-device.c | 230 ++++++++++++++++++++---------- src/devices/nm-device.h | 16 ++- src/devices/team/nm-device-team.c | 2 +- src/nm-active-connection.c | 14 +- src/nm-active-connection.h | 2 - src/nm-manager.c | 21 ++- 7 files changed, 199 insertions(+), 91 deletions(-) diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c index 4bee5497c2..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_has_activation_type_assume_or_external ((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 efa365c77a..802900f5bc 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -308,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; @@ -611,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) { @@ -1598,27 +1663,6 @@ nm_device_get_physical_port_id (NMDevice *self) /*****************************************************************************/ -static gboolean -nm_device_has_activation_type_external (NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - - return priv->act_request - && NM_IN_SET (nm_active_connection_get_activation_type (NM_ACTIVE_CONNECTION (priv->act_request)), - NM_ACTIVATION_TYPE_EXTERNAL); -} - -gboolean -nm_device_has_activation_type_assume_or_external (NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - - return priv->act_request - && NM_IN_SET (nm_active_connection_get_activation_type (NM_ACTIVE_CONNECTION (priv->act_request)), - NM_ACTIVATION_TYPE_ASSUME, - NM_ACTIVATION_TYPE_EXTERNAL); -} - static SlaveInfo * find_slave_info (NMDevice *self, NMDevice *slave) { @@ -2581,6 +2625,8 @@ realize_start_setup (NMDevice *self, _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); @@ -2954,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), @@ -2977,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"); @@ -3148,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_has_activation_type_external (self)) + if (nm_device_sys_iface_state_is_external (self)) return; reason = priv->state_reason; @@ -3226,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) { @@ -4186,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_has_activation_type_assume_or_external (active) ? FALSE : TRUE); + !nm_device_sys_iface_state_is_external_or_assume (self)); } static void @@ -4254,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); @@ -4266,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_has_activation_type_assume_or_external (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); @@ -4358,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_has_activation_type_assume_or_external (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)) { @@ -4392,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_has_activation_type_external (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); } @@ -4493,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_has_activation_type_assume_or_external (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); @@ -4685,7 +4735,7 @@ ipv4_dad_start (NMDevice *self, NMIP4Config **configs, ArpingCallback cb) || !hw_addr || !hw_addr_len || !addr_found - || nm_device_has_activation_type_assume_or_external (self)) { + || nm_device_sys_iface_state_is_external_or_assume (self)) { /* DAD not needed, signal success */ cb (self, configs, TRUE); @@ -4986,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_has_activation_type_assume_or_external (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); @@ -5012,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_has_activation_type_assume_or_external (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); @@ -5154,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_has_activation_type_external (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. @@ -5230,7 +5280,7 @@ END_ADD_DEFAULT_ROUTE: routes_full_sync = commit && priv->v4_commit_first_time - && !nm_device_has_activation_type_assume_or_external (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); @@ -5303,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_has_activation_type_assume_or_external (self)) { + if (nm_device_sys_iface_state_is_external_or_assume (self)) { dhcp_schedule_restart (self, AF_INET, "connection is assumed"); return; } @@ -5901,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_has_activation_type_external (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. @@ -5983,7 +6033,7 @@ END_ADD_DEFAULT_ROUTE: routes_full_sync = commit && priv->v6_commit_first_time - && !nm_device_has_activation_type_assume_or_external (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); @@ -6097,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_has_activation_type_assume_or_external (self)) { + if (nm_device_sys_iface_state_is_external_or_assume (self)) { dhcp_schedule_restart (self, AF_INET6, "connection is assumed"); return; } @@ -6682,7 +6732,7 @@ _commit_mtu (NMDevice *self, const NMIP4Config *config) if (ifindex <= 0) return; - if (nm_device_has_activation_type_assume_or_external (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; @@ -7349,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_has_activation_type_assume_or_external (self)) + if (!nm_device_sys_iface_state_is_external_or_assume (self)) set_nm_ipv6ll (self, TRUE); /* Re-enable IPv6 on the interface */ @@ -7379,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_has_activation_type_assume_or_external (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: @@ -7622,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_has_activation_type_external (self)) + if (nm_device_sys_iface_state_is_external (self)) priv->fw_ready = TRUE; else { if (!priv->fw_call) { @@ -7924,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_has_activation_type_assume_or_external (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,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_has_activation_type_assume_or_external (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)); @@ -8202,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); } @@ -9301,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_has_activation_type_assume_or_external (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. @@ -9343,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) @@ -9352,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_has_activation_type_external (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)); } @@ -9499,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); @@ -9506,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_has_activation_type_external (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)); } @@ -10985,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_has_activation_type_external (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), @@ -11486,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_has_activation_type_external (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, @@ -12004,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); @@ -12027,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); @@ -12049,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."); @@ -12080,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. */ @@ -12198,7 +12279,7 @@ _set_state_full (NMDevice *self, */ _cancel_activation (self); - if (nm_device_has_activation_type_assume_or_external (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, @@ -12236,7 +12317,7 @@ _set_state_full (NMDevice *self, if ( applied_connection && priv->ifindex != priv->ip_ifindex - && !nm_device_has_activation_type_external (self)) { + && !nm_device_sys_iface_state_is_external (self)) { NMSettingConnection *s_con; const char *zone; @@ -13183,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 2aca285eac..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_has_activation_type_assume_or_external (NMDevice *device); - gboolean nm_device_unmanage_on_quit (NMDevice *self); gboolean nm_device_spec_match_list (NMDevice *device, const GSList *specs); @@ -612,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 d7cbd3660e..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_has_activation_type_assume_or_external (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-active-connection.c b/src/nm-active-connection.c index 1cdef98cef..320ba45828 100644 --- a/src/nm-active-connection.c +++ b/src/nm-active-connection.c @@ -752,14 +752,14 @@ _set_activation_type (NMActiveConnection *self, nm_activation_type_to_string (priv->activation_type), nm_activation_type_to_string (activation_type)); priv->activation_type = activation_type; -} -gboolean -nm_active_connection_has_activation_type_assume_or_external (NMActiveConnection *self) -{ - return NM_IN_SET (nm_active_connection_get_activation_type (self), - NM_ACTIVATION_TYPE_ASSUME, - NM_ACTIVATION_TYPE_EXTERNAL); + 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); } /*****************************************************************************/ diff --git a/src/nm-active-connection.h b/src/nm-active-connection.h index 15f69733da..ba231c3077 100644 --- a/src/nm-active-connection.h +++ b/src/nm-active-connection.h @@ -159,8 +159,6 @@ void nm_active_connection_set_master (NMActiveConnection *self, void nm_active_connection_set_parent (NMActiveConnection *self, NMActiveConnection *parent); -gboolean nm_active_connection_has_activation_type_assume_or_external (NMActiveConnection *self); - NMActivationType nm_active_connection_get_activation_type (NMActiveConnection *self); void nm_active_connection_clear_secrets (NMActiveConnection *self); diff --git a/src/nm-manager.c b/src/nm-manager.c index 0cd534f15f..649f8464fd 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -815,13 +815,17 @@ find_best_device_state (NMManager *manager, gboolean *force_connectivity_check) } break; case NM_ACTIVE_CONNECTION_STATE_ACTIVATING: - if (!nm_active_connection_has_activation_type_assume_or_external (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_has_activation_type_assume_or_external (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; } @@ -1034,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); } @@ -1854,6 +1860,9 @@ recheck_assume_connection (NMManager *self, if (state > NM_DEVICE_STATE_DISCONNECTED) return FALSE; + 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", @@ -1864,6 +1873,9 @@ recheck_assume_connection (NMManager *self, _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; @@ -1908,6 +1920,9 @@ recheck_assume_connection (NMManager *self, nm_device_get_iface (device)); 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; }