diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/devices/nm-device-ppp.c | 9 | ||||
| -rw-r--r-- | src/devices/nm-device.c | 154 | ||||
| -rw-r--r-- | src/devices/ovs/nm-device-ovs-interface.c | 2 | ||||
| -rw-r--r-- | src/devices/ovs/nm-device-ovs-port.c | 47 | ||||
| -rw-r--r-- | src/devices/ovs/nm-ovsdb.c | 32 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-listener.c | 2 | ||||
| -rw-r--r-- | src/dns/nm-dns-manager.c | 10 | ||||
| -rw-r--r-- | src/nm-active-connection.c | 33 | ||||
| -rw-r--r-- | src/nm-active-connection.h | 4 | ||||
| -rw-r--r-- | src/nm-manager.c | 142 | ||||
| -rw-r--r-- | src/nm-policy.c | 10 | ||||
| -rw-r--r-- | src/platform/nm-linux-platform.c | 9 | ||||
| -rw-r--r-- | src/platform/nmp-netns.c | 6 | ||||
| -rw-r--r-- | src/platform/tests/test-common.c | 37 | ||||
| -rw-r--r-- | src/platform/tests/test-link.c | 17 | ||||
| -rw-r--r-- | src/platform/tests/test-route.c | 44 | ||||
| -rw-r--r-- | src/ppp/nm-ppp-manager.c | 12 | ||||
| -rw-r--r-- | src/ppp/nm-pppd-plugin.c | 19 | ||||
| -rw-r--r-- | src/settings/nm-settings-connection.c | 14 | ||||
| -rw-r--r-- | src/settings/nm-settings.c | 25 | ||||
| -rw-r--r-- | src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 2 | ||||
| -rw-r--r-- | src/settings/plugins/keyfile/nms-keyfile-plugin.c | 2 |
22 files changed, 378 insertions, 254 deletions
diff --git a/src/devices/nm-device-ppp.c b/src/devices/nm-device-ppp.c index 8b3968d5..639ec44a 100644 --- a/src/devices/nm-device-ppp.c +++ b/src/devices/nm-device-ppp.c @@ -207,6 +207,14 @@ act_stage3_ip4_config_start (NMDevice *device, return NM_ACT_STAGE_RETURN_POSTPONE; } +static NMActStageReturn +act_stage3_ip6_config_start (NMDevice *self, + NMIP6Config **out_config, + NMDeviceStateReason *out_failure_reason) +{ + return NM_ACT_STAGE_RETURN_IP_FAIL; +} + static gboolean create_and_realize (NMDevice *device, NMConnection *connection, @@ -273,6 +281,7 @@ nm_device_ppp_class_init (NMDevicePppClass *klass) parent_class->act_stage2_config = act_stage2_config; parent_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start; + parent_class->act_stage3_ip6_config_start = act_stage3_ip6_config_start; parent_class->check_connection_compatible = check_connection_compatible; parent_class->create_and_realize = create_and_realize; parent_class->deactivate = deactivate; diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 6f9289ee..b8828d14 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -3940,21 +3940,24 @@ get_ip_config_may_fail (NMDevice *self, int addr_family) /* * check_ip_state * - * Transition the device from IP_CONFIG to the next state according to the - * outcome of IPv4 and IPv6 configuration. @may_fail indicates that we are - * called just after the initial configuration and thus IPv4/IPv6 are allowed to - * fail if the ipvx.may-fail properties say so, because the IP methods couldn't - * even be started. + * When @full_state_update is TRUE, transition the device from IP_CONFIG to the + * next state according to the outcome of IPv4 and IPv6 configuration. @may_fail + * indicates that we are called just after the initial configuration and thus + * IPv4/IPv6 are allowed to fail if the ipvx.may-fail properties say so, because + * the IP methods couldn't even be started. + * If @full_state_update is FALSE, just check if the connection should be failed + * due to the state of both ip families and the ipvx.may-fail settings. */ static void -check_ip_state (NMDevice *self, gboolean may_fail) +check_ip_state (NMDevice *self, gboolean may_fail, gboolean full_state_update) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); gboolean ip4_disabled = FALSE, ip6_ignore = FALSE; NMSettingIPConfig *s_ip4, *s_ip6; NMDeviceState state; - if (nm_device_get_state (self) != NM_DEVICE_STATE_IP_CONFIG) + if ( full_state_update + && nm_device_get_state (self) != NM_DEVICE_STATE_IP_CONFIG) return; /* Don't progress into IP_CHECK or SECONDARIES if we're waiting for the @@ -4001,9 +4004,12 @@ check_ip_state (NMDevice *self, gboolean may_fail) state = NM_DEVICE_STATE_FAILED; } - nm_device_state_changed (self, - state, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + if ( full_state_update + || state == NM_DEVICE_STATE_FAILED) { + nm_device_state_changed (self, + state, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + } return; } @@ -4016,7 +4022,8 @@ check_ip_state (NMDevice *self, gboolean may_fail) /* If at least a method has completed, proceed with activation */ if ( (priv->ip4_state == IP_DONE && !ip4_disabled) || (priv->ip6_state == IP_DONE && !ip6_ignore)) { - nm_device_state_changed (self, NM_DEVICE_STATE_IP_CHECK, NM_DEVICE_STATE_REASON_NONE); + if (full_state_update) + nm_device_state_changed (self, NM_DEVICE_STATE_IP_CHECK, NM_DEVICE_STATE_REASON_NONE); return; } } @@ -4058,7 +4065,7 @@ nm_device_slave_notify_enslave (NMDevice *self, gboolean success) if (activating) { if (success) - check_ip_state (self, FALSE); + check_ip_state (self, FALSE, TRUE); else nm_device_queue_state (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_UNKNOWN); } else @@ -5434,7 +5441,7 @@ nm_device_ip_method_failed (NMDevice *self, _set_ip_state (self, addr_family, IP_FAIL); if (get_ip_config_may_fail (self, addr_family)) - check_ip_state (self, FALSE); + check_ip_state (self, FALSE, (nm_device_get_state (self) == NM_DEVICE_STATE_IP_CONFIG)); else nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); } @@ -6059,15 +6066,23 @@ dhcp4_fail (NMDevice *self, gboolean timeout) && (timeout || (priv->ip4_state == IP_CONF)) && !priv->dhcp4.was_active) nm_device_activate_schedule_ip4_config_timeout (self); - else if (priv->ip4_state == IP_DONE || priv->dhcp4.was_active) { + else if ( priv->dhcp4.num_tries_left < DHCP_NUM_TRIES_MAX + || priv->ip4_state == IP_DONE + || priv->dhcp4.was_active) { /* Don't fail immediately when the lease expires but try to * restart DHCP for a predefined number of times. */ if (priv->dhcp4.num_tries_left) { priv->dhcp4.num_tries_left--; dhcp_schedule_restart (self, AF_INET, "lease expired"); - } else + } else { nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); + /* We failed the ipv4 method but schedule again the retries if the ipv6 method is + * configured, keeping the connection up. + */ + if (nm_device_get_state (self) != NM_DEVICE_STATE_FAILED) + dhcp_schedule_restart (self, AF_INET, "renewal failed"); + } } else g_warn_if_reached (); } @@ -6109,6 +6124,12 @@ dhcp4_state_changed (NMDhcpClient *client, break; } + /* After some failures, we have been able to renew the lease: + * update the ip state + */ + if (priv->ip4_state == IP_FAIL) + _set_ip_state (self, AF_INET, IP_CONF); + g_free (priv->dhcp4.pac_url); priv->dhcp4.pac_url = g_strdup (g_hash_table_lookup (options, "wpad")); nm_device_set_proxy_config (self, priv->dhcp4.pac_url); @@ -6778,13 +6799,15 @@ static void dhcp6_fail (NMDevice *self, gboolean timeout) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + gboolean is_dhcp_managed; _LOGD (LOGD_DHCP6, "DHCPv6 failed: timeout %d, num tries left %u", timeout, priv->dhcp6.num_tries_left); + is_dhcp_managed = (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_MANAGED); dhcp6_cleanup (self, CLEANUP_TYPE_DECONFIGURE, FALSE); - if (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_MANAGED) { + if (is_dhcp_managed || priv->dhcp6.num_tries_left < DHCP_NUM_TRIES_MAX) { /* Don't fail if there are static addresses configured on * the device, instead retry after some time. */ @@ -6799,15 +6822,23 @@ dhcp6_fail (NMDevice *self, gboolean timeout) && (timeout || (priv->ip6_state == IP_CONF)) && !priv->dhcp6.was_active) nm_device_activate_schedule_ip6_config_timeout (self); - else if (priv->ip6_state == IP_DONE || priv->dhcp6.was_active) { + else if ( priv->dhcp6.num_tries_left < DHCP_NUM_TRIES_MAX + || priv->ip6_state == IP_DONE + || priv->dhcp6.was_active) { /* Don't fail immediately when the lease expires but try to * restart DHCP for a predefined number of times. */ if (priv->dhcp6.num_tries_left) { priv->dhcp6.num_tries_left--; dhcp_schedule_restart (self, AF_INET6, "lease expired"); - } else + } else { nm_device_ip_method_failed (self, AF_INET6, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); + /* We failed the ipv6 method but schedule again the retries if the ipv4 method is + * configured, keeping the connection up. + */ + if (nm_device_get_state (self) != NM_DEVICE_STATE_FAILED) + dhcp_schedule_restart (self, AF_INET6, "renewal failed"); + } } else g_warn_if_reached (); } else { @@ -6874,6 +6905,12 @@ dhcp6_state_changed (NMDhcpClient *client, } } + /* After long time we have been able to renew the lease: + * update the ip state + */ + if (priv->ip6_state == IP_FAIL) + _set_ip_state (self, AF_INET6, IP_CONF); + priv->dhcp6.num_tries_left = DHCP_NUM_TRIES_MAX; if (priv->ip6_state == IP_CONF) { @@ -7506,7 +7543,7 @@ _commit_mtu (NMDevice *self, const NMIP4Config *config) gboolean anticipated_failure = FALSE; if (!priv->mtu_initial && !priv->ip6_mtu_initial) { - /* before touching any of the MTU paramters, record the + /* before touching any of the MTU parameters, record the * original setting to restore on deactivation. */ priv->mtu_initial = mtu_plat; priv->ip6_mtu_initial = _IP6_MTU_SYS (); @@ -8163,7 +8200,7 @@ nm_device_activate_stage3_ip4_start (NMDevice *self) if (nm_device_sys_iface_state_is_external (self)) { _set_ip_state (self, AF_INET, IP_DONE); - check_ip_state (self, FALSE); + check_ip_state (self, FALSE, TRUE); return TRUE; } @@ -8176,7 +8213,7 @@ nm_device_activate_stage3_ip4_start (NMDevice *self) g_object_unref (ip4_config); } else if (ret == NM_ACT_STAGE_RETURN_IP_DONE) { _set_ip_state (self, AF_INET, IP_DONE); - check_ip_state (self, FALSE); + check_ip_state (self, FALSE, TRUE); } else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, failure_reason); return FALSE; @@ -8210,7 +8247,7 @@ nm_device_activate_stage3_ip6_start (NMDevice *self) if (nm_device_sys_iface_state_is_external (self)) { _set_ip_state (self, AF_INET6, IP_DONE); - check_ip_state (self, FALSE); + check_ip_state (self, FALSE, TRUE); return TRUE; } @@ -8227,7 +8264,7 @@ nm_device_activate_stage3_ip6_start (NMDevice *self) nm_device_activate_schedule_ip6_config_result (self); } else if (ret == NM_ACT_STAGE_RETURN_IP_DONE) { _set_ip_state (self, AF_INET6, IP_DONE); - check_ip_state (self, FALSE); + check_ip_state (self, FALSE, TRUE); } else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, failure_reason); return FALSE; @@ -8277,7 +8314,7 @@ activate_stage3_ip_config_start (NMDevice *self) /* Proxy */ nm_device_set_proxy_config (self, NULL); - check_ip_state (self, TRUE); + check_ip_state (self, TRUE, TRUE); } static void @@ -8416,7 +8453,7 @@ activate_stage4_ip4_config_timeout (NMDevice *self) _set_ip_state (self, AF_INET, IP_FAIL); - check_ip_state (self, FALSE); + check_ip_state (self, FALSE, TRUE); } /* @@ -8472,7 +8509,7 @@ activate_stage4_ip6_config_timeout (NMDevice *self) _set_ip_state (self, AF_INET6, IP_FAIL); - check_ip_state (self, FALSE); + check_ip_state (self, FALSE, TRUE); } /* @@ -8720,7 +8757,7 @@ activate_stage5_ip4_config_result (NMDevice *self) /* Enter the IP_CHECK state if this is the first method to complete */ _set_ip_state (self, AF_INET, IP_DONE); - check_ip_state (self, FALSE); + check_ip_state (self, FALSE, TRUE); } void @@ -8875,7 +8912,7 @@ activate_stage5_ip6_config_commit (NMDevice *self) _LOGD (LOGD_DEVICE | LOGD_IP6, "IPv6 DAD: awaiting termination"); } else { _set_ip_state (self, AF_INET6, IP_DONE); - check_ip_state (self, FALSE); + check_ip_state (self, FALSE, TRUE); } } } else { @@ -9879,10 +9916,12 @@ static void _clear_queued_act_request (NMDevicePrivate *priv) { if (priv->queued_act_request) { - nm_active_connection_set_state ((NMActiveConnection *) priv->queued_act_request, - NM_ACTIVE_CONNECTION_STATE_DEACTIVATED, - NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED); - g_clear_object (&priv->queued_act_request); + gs_unref_object NMActRequest *ac = NULL; + + ac = g_steal_pointer (&priv->queued_act_request); + nm_active_connection_set_state_fail ((NMActiveConnection *) ac, + NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED, + NULL); } } @@ -9959,26 +9998,34 @@ impl_device_delete (NMDevice *self, GDBusMethodInvocation *context) NULL); } -static gboolean +static void _device_activate (NMDevice *self, NMActRequest *req) { - NMDevicePrivate *priv; NMConnection *connection; - g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); - g_return_val_if_fail (NM_IS_ACT_REQUEST (req), FALSE); - g_return_val_if_fail (nm_device_get_managed (self, FALSE), FALSE); + g_return_if_fail (NM_IS_DEVICE (self)); + g_return_if_fail (NM_IS_ACT_REQUEST (req)); + nm_assert (nm_device_is_real (self)); /* Ensure the activation request is still valid; the master may have * already failed in which case activation of this device should not proceed. */ if (nm_active_connection_get_state (NM_ACTIVE_CONNECTION (req)) >= NM_ACTIVE_CONNECTION_STATE_DEACTIVATING) - return FALSE; + return; - priv = NM_DEVICE_GET_PRIVATE (self); + if (!nm_device_get_managed (self, FALSE)) { + /* It's unclear why the device would be unmanaged at this point. + * Just to be sure, handle it and error out. */ + _LOGE (LOGD_DEVICE, "Activation: failed activating connection '%s' because device is still unmanaged", + nm_active_connection_get_settings_connection_id ((NMActiveConnection *) req)); + nm_active_connection_set_state_fail ((NMActiveConnection *) req, + NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN, + NULL); + return; + } connection = nm_act_request_get_applied_connection (req); - g_assert (connection); + nm_assert (connection); _LOGI (LOGD_DEVICE, "Activation: starting connection '%s' (%s)", nm_connection_get_id (connection), @@ -9989,14 +10036,12 @@ _device_activate (NMDevice *self, NMActRequest *req) act_request_set (self, req); nm_device_activate_schedule_stage1_device_prepare (self); - return TRUE; } static void _carrier_wait_check_queued_act_request (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMActRequest *queued_req; if ( !priv->queued_act_request || !priv->queued_act_request_is_waiting_for_carrier) @@ -10007,11 +10052,11 @@ _carrier_wait_check_queued_act_request (NMDevice *self) _LOGD (LOGD_DEVICE, "Cancel queued activation request as we have no carrier after timeout"); _clear_queued_act_request (priv); } else { + gs_unref_object NMActRequest *queued_req = NULL; + _LOGD (LOGD_DEVICE, "Activate queued activation request as we now have carrier"); - queued_req = priv->queued_act_request; - priv->queued_act_request = NULL; + queued_req = g_steal_pointer (&priv->queued_act_request); _device_activate (self, queued_req); - g_object_unref (queued_req); } } @@ -10071,10 +10116,11 @@ nm_device_steal_connection (NMDevice *self, NMSettingsConnection *connection) if ( priv->act_request && connection == nm_active_connection_get_settings_connection (NM_ACTIVE_CONNECTION (priv->act_request)) - && priv->state < NM_DEVICE_STATE_DEACTIVATING) + && priv->state < NM_DEVICE_STATE_DEACTIVATING) { nm_device_state_changed (self, NM_DEVICE_STATE_DEACTIVATING, NM_DEVICE_STATE_REASON_NEW_ACTIVATION); + } } void @@ -10085,10 +10131,10 @@ nm_device_queue_activation (NMDevice *self, NMActRequest *req) must_queue = _carrier_wait_check_act_request_must_queue (self, req); - if (!priv->act_request && !must_queue && nm_device_is_real (self)) { - /* Just activate immediately */ - if (!_device_activate (self, req)) - g_assert_not_reached (); + if ( !priv->act_request + && !must_queue + && nm_device_is_real (self)) { + _device_activate (self, req); return; } @@ -11369,7 +11415,7 @@ queued_ip6_config_change (gpointer user_data) _LOGD (LOGD_DEVICE | LOGD_IP6, "IPv6 DAD terminated"); g_clear_object (&priv->dad6_ip6_config); _set_ip_state (self, AF_INET6, IP_DONE); - check_ip_state (self, FALSE); + check_ip_state (self, FALSE, TRUE); if (priv->rt6_temporary_not_available) nm_device_activate_schedule_ip6_config_result (self); } @@ -13199,12 +13245,10 @@ _set_state_full (NMDevice *self, case NM_DEVICE_STATE_DISCONNECTED: if ( priv->queued_act_request && !priv->queued_act_request_is_waiting_for_carrier) { - NMActRequest *queued_req; + gs_unref_object NMActRequest *queued_req = NULL; - queued_req = priv->queued_act_request; - priv->queued_act_request = NULL; + queued_req = g_steal_pointer (&priv->queued_act_request); _device_activate (self, queued_req); - g_object_unref (queued_req); } break; case NM_DEVICE_STATE_ACTIVATED: diff --git a/src/devices/ovs/nm-device-ovs-interface.c b/src/devices/ovs/nm-device-ovs-interface.c index e746a3fd..ce32c2dd 100644 --- a/src/devices/ovs/nm-device-ovs-interface.c +++ b/src/devices/ovs/nm-device-ovs-interface.c @@ -50,7 +50,7 @@ struct _NMDeviceOvsInterfaceClass { G_DEFINE_TYPE (NMDeviceOvsInterface, nm_device_ovs_interface, NM_TYPE_DEVICE) -#define NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMDeviceOvsInterface, NM_IS_DEVICE_OVS_INTERFACE) +#define NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMDeviceOvsInterface, NM_IS_DEVICE_OVS_INTERFACE, NMDevice) /*****************************************************************************/ diff --git a/src/devices/ovs/nm-device-ovs-port.c b/src/devices/ovs/nm-device-ovs-port.c index 83199f2d..cb0915af 100644 --- a/src/devices/ovs/nm-device-ovs-port.c +++ b/src/devices/ovs/nm-device-ovs-port.c @@ -114,12 +114,13 @@ add_iface_cb (GError *error, gpointer user_data) { NMDevice *slave = user_data; - if (error) { - nm_log_warn (LOGD_DEVICE, "device %s could not be added to a ovs port: %s", + if ( error + && !g_error_matches (error, NM_UTILS_ERROR, NM_UTILS_ERROR_CANCELLED_DISPOSING)) { + nm_log_warn (LOGD_DEVICE, "device %s could not be added to a ovs port: %s", nm_device_get_iface (slave), error->message); - nm_device_state_changed (slave, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_OVSDB_FAILED); + nm_device_state_changed (slave, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_OVSDB_FAILED); } g_object_unref (slave); @@ -128,23 +129,22 @@ add_iface_cb (GError *error, gpointer user_data) static gboolean enslave_slave (NMDevice *device, NMDevice *slave, NMConnection *connection, gboolean configure) { - NMActiveConnection *ac_port = NULL; - NMActiveConnection *ac_bridge = NULL; + NMActiveConnection *ac_port = NULL; + NMActiveConnection *ac_bridge = NULL; if (!configure) return TRUE; + ac_port = NM_ACTIVE_CONNECTION (nm_device_get_act_request (device)); + ac_bridge = nm_active_connection_get_master (ac_port); + if (!ac_bridge) + ac_bridge = ac_port; - ac_port = NM_ACTIVE_CONNECTION (nm_device_get_act_request (device)); - ac_bridge = nm_active_connection_get_master (ac_port); - if (!ac_bridge) - ac_bridge = ac_port; - - nm_ovsdb_add_interface (nm_ovsdb_get (), - nm_active_connection_get_applied_connection (ac_bridge), - nm_device_get_applied_connection (device), - nm_device_get_applied_connection (slave), - add_iface_cb, g_object_ref (slave)); + nm_ovsdb_add_interface (nm_ovsdb_get (), + nm_active_connection_get_applied_connection (ac_bridge), + nm_device_get_applied_connection (device), + nm_device_get_applied_connection (slave), + add_iface_cb, g_object_ref (slave)); return TRUE; } @@ -154,12 +154,13 @@ del_iface_cb (GError *error, gpointer user_data) { NMDevice *slave = user_data; - if (error) { - nm_log_warn (LOGD_DEVICE, "device %s could not be removed from a ovs port: %s", + if ( error + && !g_error_matches (error, NM_UTILS_ERROR, NM_UTILS_ERROR_CANCELLED_DISPOSING)) { + nm_log_warn (LOGD_DEVICE, "device %s could not be removed from a ovs port: %s", nm_device_get_iface (slave), error->message); - nm_device_state_changed (slave, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_OVSDB_FAILED); + nm_device_state_changed (slave, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_OVSDB_FAILED); } g_object_unref (slave); @@ -169,7 +170,7 @@ static void release_slave (NMDevice *device, NMDevice *slave, gboolean configure) { nm_ovsdb_del_interface (nm_ovsdb_get (), nm_device_get_iface (slave), - del_iface_cb, g_object_ref (slave)); + del_iface_cb, g_object_ref (slave)); } /*****************************************************************************/ diff --git a/src/devices/ovs/nm-ovsdb.c b/src/devices/ovs/nm-ovsdb.c index b44668c0..92fcfa01 100644 --- a/src/devices/ovs/nm-ovsdb.c +++ b/src/devices/ovs/nm-ovsdb.c @@ -119,7 +119,7 @@ NM_DEFINE_SINGLETON_GETTER (NMOvsdb, nm_ovsdb_get, NM_TYPE_OVSDB); /*****************************************************************************/ static void ovsdb_try_connect (NMOvsdb *self); -static void ovsdb_disconnect (NMOvsdb *self); +static void ovsdb_disconnect (NMOvsdb *self, gboolean is_disposing); static void ovsdb_read (NMOvsdb *self); static void ovsdb_write (NMOvsdb *self); static void ovsdb_next_command (NMOvsdb *self); @@ -1103,7 +1103,7 @@ ovsdb_got_msg (NMOvsdb *self, json_t *msg) "result", &result, "error", &error) == -1) { _LOGW ("couldn't grok the message: %s", json_error.text); - ovsdb_disconnect (self); + ovsdb_disconnect (self, FALSE); return; } @@ -1114,7 +1114,7 @@ ovsdb_got_msg (NMOvsdb *self, json_t *msg) /* It's a method call! */ if (!params) { _LOGW ("a method call with no params: '%s'", method); - ovsdb_disconnect (self); + ovsdb_disconnect (self, FALSE); return; } @@ -1134,13 +1134,13 @@ ovsdb_got_msg (NMOvsdb *self, json_t *msg) /* This is a response to a method call. */ if (!priv->calls->len) { _LOGE ("there are no queued calls expecting response %" G_GUINT64_FORMAT, id); - ovsdb_disconnect (self); + ovsdb_disconnect (self, FALSE); return; } call = &g_array_index (priv->calls, OvsdbMethodCall, 0); if (call->id != id) { _LOGE ("expected a response to call %" G_GUINT64_FORMAT ", not %" G_GUINT64_FORMAT, call->id, id); - ovsdb_disconnect (self); + ovsdb_disconnect (self, FALSE); return; } /* Cool, we found a corresponsing call. Finish it. */ @@ -1219,7 +1219,7 @@ ovsdb_read_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) if (size == -1) { _LOGW ("short read from ovsdb: %s", error->message); g_clear_error (&error); - ovsdb_disconnect (self); + ovsdb_disconnect (self, FALSE); return; } @@ -1267,7 +1267,7 @@ ovsdb_write_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) if (size == -1) { _LOGW ("short write to ovsdb: %s", error->message); g_clear_error (&error); - ovsdb_disconnect (self); + ovsdb_disconnect (self, FALSE); return; } @@ -1310,21 +1310,19 @@ ovsdb_write (NMOvsdb *self) * puts us back in sync. */ static void -ovsdb_disconnect (NMOvsdb *self) +ovsdb_disconnect (NMOvsdb *self, gboolean is_disposing) { NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE (self); OvsdbMethodCall *call; OvsdbMethodCallback callback; gpointer user_data; - GError *error; + gs_free_error GError *error = NULL; _LOGD ("disconnecting from ovsdb"); + nm_utils_error_set_cancelled (&error, is_disposing, "NMOvsdb"); while (priv->calls->len) { - error = NULL; call = &g_array_index (priv->calls, OvsdbMethodCall, priv->calls->len - 1); - g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_CANCELLED, "Cancelled"); - callback = call->callback; user_data = call->user_data; g_array_remove_index (priv->calls, priv->calls->len - 1); @@ -1343,12 +1341,10 @@ static void _monitor_bridges_cb (NMOvsdb *self, json_t *result, GError *error, gpointer user_data) { if (error) { - if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + if (!nm_utils_error_is_cancelled (error, TRUE)) { _LOGI ("%s", error->message); - ovsdb_disconnect (self); + ovsdb_disconnect (self, FALSE); } - - g_clear_error (&error); return; } @@ -1371,7 +1367,7 @@ _client_connect_cb (GObject *source_object, GAsyncResult *res, gpointer user_dat if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) _LOGI ("%s", error->message); - ovsdb_disconnect (self); + ovsdb_disconnect (self, FALSE); g_clear_error (&error); return; } @@ -1555,7 +1551,7 @@ dispose (GObject *object) NMOvsdb *self = NM_OVSDB (object); NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE (self); - ovsdb_disconnect (self); + ovsdb_disconnect (self, TRUE); g_string_free (priv->input, TRUE); priv->input = NULL; diff --git a/src/dhcp/nm-dhcp-listener.c b/src/dhcp/nm-dhcp-listener.c index a0449816..1cce5a1c 100644 --- a/src/dhcp/nm-dhcp-listener.c +++ b/src/dhcp/nm-dhcp-listener.c @@ -145,7 +145,7 @@ _method_call_handle (NMDhcpListener *self, gs_free char *iface = NULL; gs_free char *pid_str = NULL; gs_free char *reason = NULL; - gs_unref_variant GVariant *options; + gs_unref_variant GVariant *options = NULL; int pid; gboolean handled = FALSE; diff --git a/src/dns/nm-dns-manager.c b/src/dns/nm-dns-manager.c index 973abc1c..dc545470 100644 --- a/src/dns/nm-dns-manager.c +++ b/src/dns/nm-dns-manager.c @@ -1448,11 +1448,13 @@ nm_dns_manager_stop (NMDnsManager *self) _LOGT ("stopping..."); /* If we're quitting, leave a valid resolv.conf in place, not one - * pointing to 127.0.0.1 if any plugins were active. Thus update - * DNS after disposing of all plugins. But if we haven't done any - * DNS updates yet, there's no reason to touch resolv.conf on shutdown. + * pointing to 127.0.0.1 if dnsmasq was active. But if we haven't + * done any DNS updates yet, there's no reason to touch resolv.conf + * on shutdown. */ - if (priv->dns_touched) { + if ( priv->dns_touched + && priv->plugin + && NM_IS_DNS_DNSMASQ (priv->plugin)) { if (!update_dns (self, TRUE, &error)) { _LOGW ("could not commit DNS changes on shutdown: %s", error->message); g_clear_error (&error); diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c index 2286a74b..65f57565 100644 --- a/src/nm-active-connection.c +++ b/src/nm-active-connection.c @@ -292,6 +292,36 @@ nm_active_connection_set_state (NMActiveConnection *self, } } +void +nm_active_connection_set_state_fail (NMActiveConnection *self, + NMActiveConnectionStateReason reason, + const char *error_desc) +{ + NMActiveConnectionState s; + + g_return_if_fail (NM_IS_ACTIVE_CONNECTION (self)); + + if (error_desc) { + _LOGD ("Failed to activate '%s': %s", + nm_active_connection_get_settings_connection_id (self), + error_desc); + } + + s = nm_active_connection_get_state (self); + if ( s >= NM_ACTIVE_CONNECTION_STATE_ACTIVATING + && s < NM_ACTIVE_CONNECTION_STATE_DEACTIVATING) { + nm_active_connection_set_state (self, + NM_ACTIVE_CONNECTION_STATE_DEACTIVATING, + reason); + s = nm_active_connection_get_state (self); + } + if (s < NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) { + nm_active_connection_set_state (self, + NM_ACTIVE_CONNECTION_STATE_DEACTIVATED, + reason); + } +} + NMActivationStateFlags nm_active_connection_get_state_flags (NMActiveConnection *self) { @@ -1236,6 +1266,7 @@ set_property (GObject *object, guint prop_id, nm_active_connection_set_device (self, g_value_get_object (value)); break; case PROP_INT_SUBJECT: + /* construct-only */ priv->subject = g_value_dup_object (value); break; case PROP_INT_MASTER: @@ -1251,6 +1282,7 @@ set_property (GObject *object, guint prop_id, _set_activation_type (self, (NMActivationType) i); break; case PROP_SPECIFIC_OBJECT: + /* construct-only */ tmp = g_value_get_string (value); /* NM uses "/" to mean NULL */ if (g_strcmp0 (tmp, "/") != 0) @@ -1263,6 +1295,7 @@ set_property (GObject *object, guint prop_id, priv->is_default6 = g_value_get_boolean (value); break; case PROP_VPN: + /* construct-only */ priv->vpn = g_value_get_boolean (value); break; case PROP_MASTER: diff --git a/src/nm-active-connection.h b/src/nm-active-connection.h index 5ede2b04..3015b5c5 100644 --- a/src/nm-active-connection.h +++ b/src/nm-active-connection.h @@ -148,6 +148,10 @@ void nm_active_connection_set_state (NMActiveConnection *self, NMActiveConnectionState state, NMActiveConnectionStateReason reason); +void nm_active_connection_set_state_fail (NMActiveConnection *active, + NMActiveConnectionStateReason reason, + const char *error_desc); + NMActivationStateFlags nm_active_connection_get_state_flags (NMActiveConnection *self); void nm_active_connection_set_state_flags_full (NMActiveConnection *self, diff --git a/src/nm-manager.c b/src/nm-manager.c index 001fae55..8391dbf2 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -685,7 +685,8 @@ active_connection_default_changed (NMActiveConnection *active, * Begins to track and manage @active. Increases the refcount of @active. */ static void -active_connection_add (NMManager *self, NMActiveConnection *active) +active_connection_add (NMManager *self, + NMActiveConnection *active) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); @@ -708,11 +709,12 @@ active_connection_add (NMManager *self, NMActiveConnection *active) G_CALLBACK (active_connection_default_changed), self); + if (!nm_exported_object_is_exported (NM_EXPORTED_OBJECT (active))) + nm_exported_object_export (NM_EXPORTED_OBJECT (active)); + g_signal_emit (self, signals[ACTIVE_CONNECTION_ADDED], 0, active); - /* Only notify D-Bus if the active connection is actually exported */ - if (nm_exported_object_is_exported (NM_EXPORTED_OBJECT (active))) - _notify (self, PROP_ACTIVE_CONNECTIONS); + _notify (self, PROP_ACTIVE_CONNECTIONS); } const CList * @@ -2345,7 +2347,6 @@ recheck_assume_connection (NMManager *self, 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)); } @@ -3523,18 +3524,18 @@ autoconnect_slaves (NMManager *self, static gboolean _internal_activate_vpn (NMManager *self, NMActiveConnection *active, GError **error) { - gboolean success; - - g_assert (NM_IS_VPN_CONNECTION (active)); + nm_assert (NM_IS_VPN_CONNECTION (active)); nm_exported_object_export (NM_EXPORTED_OBJECT (active)); - success = nm_vpn_manager_activate_connection (NM_MANAGER_GET_PRIVATE (self)->vpn_manager, - NM_VPN_CONNECTION (active), - error); - if (!success) + if (!nm_vpn_manager_activate_connection (NM_MANAGER_GET_PRIVATE (self)->vpn_manager, + NM_VPN_CONNECTION (active), + error)) { nm_exported_object_unexport (NM_EXPORTED_OBJECT (active)); + return FALSE; + } - return success; + active_connection_add (self, active); + return TRUE; } /* Traverse the device to disconnected state. This means that the device is ready @@ -3563,8 +3564,8 @@ unmanaged_to_disconnected (NMDevice *device) NM_DEVICE_STATE_REASON_USER_REQUESTED); } - if ( nm_device_is_available (device, NM_DEVICE_CHECK_DEV_AVAILABLE_FOR_USER_REQUEST) - && (nm_device_get_state (device) == NM_DEVICE_STATE_UNAVAILABLE)) { + if ( nm_device_get_state (device) == NM_DEVICE_STATE_UNAVAILABLE + && nm_device_is_available (device, NM_DEVICE_CHECK_DEV_AVAILABLE_FOR_USER_REQUEST)) { nm_device_state_changed (device, NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_USER_REQUESTED); @@ -3581,32 +3582,36 @@ active_connection_parent_active (NMActiveConnection *active, { NMDevice *device = nm_active_connection_get_device (active); GError *error = NULL; + NMSettingsConnection *connection; + NMDevice *parent; g_signal_handlers_disconnect_by_func (active, (GCallback) active_connection_parent_active, self); - if (parent_ac) { - NMSettingsConnection *connection = nm_active_connection_get_settings_connection (active); - NMDevice *parent = nm_active_connection_get_device (parent_ac); - - if (nm_device_create_and_realize (device, (NMConnection *) connection, parent, &error)) { - /* We can now proceed to disconnected state so that activation proceeds. */ - unmanaged_to_disconnected (device); - } else { - _LOGW (LOGD_CORE, "Could not realize device '%s': %s", - nm_device_get_iface (device), error->message); - nm_active_connection_set_state (active, - NM_ACTIVE_CONNECTION_STATE_DEACTIVATED, - NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REALIZE_FAILED); - } - } else { + if (!parent_ac) { _LOGW (LOGD_CORE, "The parent connection device '%s' depended on disappeared.", nm_device_get_iface (device)); - nm_active_connection_set_state (active, - NM_ACTIVE_CONNECTION_STATE_DEACTIVATED, - NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REMOVED); + nm_active_connection_set_state_fail (active, + NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REMOVED, + "parent device disappeared"); + return; + } + + connection = nm_active_connection_get_settings_connection (active); + parent = nm_active_connection_get_device (parent_ac); + + if (!nm_device_create_and_realize (device, (NMConnection *) connection, parent, &error)) { + _LOGW (LOGD_CORE, "Could not realize device '%s': %s", + nm_device_get_iface (device), error->message); + nm_active_connection_set_state_fail (active, + NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REALIZE_FAILED, + "failure to realize device"); + return; } + + /* We can now proceed to disconnected state so that activation proceeds. */ + unmanaged_to_disconnected (device); } static gboolean @@ -3783,11 +3788,22 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError * } /* If the device is there, we can ready it for the activation. */ - if (nm_device_is_real (device)) + if (nm_device_is_real (device)) { unmanaged_to_disconnected (device); + if (!nm_device_get_managed (device, FALSE)) { + /* Unexpectedly, the device is still unmanaged. That can happen for example, + * if the device is forcibly unmanaged due to NM_UNMANAGED_USER_SETTINGS. */ + g_set_error_literal (error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_DEPENDENCY_FAILED, + "Activation failed because the device is unmanaged"); + return FALSE; + } + } + /* Export the new ActiveConnection to clients and start it on the device */ - nm_exported_object_export (NM_EXPORTED_OBJECT (active)); + active_connection_add (self, active); nm_device_queue_activation (device, NM_ACT_REQUEST (active)); return TRUE; } @@ -3822,7 +3838,6 @@ _internal_activate_generic (NMManager *self, NMActiveConnection *active, GError * is exported, make sure the manager's activating-connection property * is up-to-date. */ - active_connection_add (self, active); policy_activating_device_changed (G_OBJECT (priv->policy), NULL, self); } @@ -3929,25 +3944,6 @@ _new_active_connection (NMManager *self, } static void -_internal_activation_failed (NMManager *self, - NMActiveConnection *active, - const char *error_desc) -{ - _LOGD (LOGD_CORE, "Failed to activate '%s': %s", - nm_active_connection_get_settings_connection_id (active), - error_desc); - - if (nm_active_connection_get_state (active) <= NM_ACTIVE_CONNECTION_STATE_ACTIVATED) { - nm_active_connection_set_state (active, - NM_ACTIVE_CONNECTION_STATE_DEACTIVATING, - NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN); - nm_active_connection_set_state (active, - NM_ACTIVE_CONNECTION_STATE_DEACTIVATED, - NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN); - } -} - -static void _internal_activation_auth_done (NMActiveConnection *active, gboolean success, const char *error_desc, @@ -3992,7 +3988,9 @@ _internal_activation_auth_done (NMActiveConnection *active, } nm_assert (error_desc || error); - _internal_activation_failed (self, active, error_desc ? error_desc : error->message); + nm_active_connection_set_state_fail (active, + NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN, + error_desc ?: error->message); } /** @@ -4211,6 +4209,7 @@ _activation_auth_done (NMActiveConnection *active, GError *error = NULL; NMAuthSubject *subject; NMSettingsConnection *connection; + _nm_unused gs_unref_object NMActiveConnection *active_free = active; subject = nm_active_connection_get_subject (active); connection = nm_active_connection_get_settings_connection (active); @@ -4225,7 +4224,6 @@ _activation_auth_done (NMActiveConnection *active, nm_exported_object_get_path (NM_EXPORTED_OBJECT (active)))); nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ACTIVATE, connection, TRUE, NULL, subject, NULL); - g_object_unref (active); return; } } else { @@ -4234,12 +4232,12 @@ _activation_auth_done (NMActiveConnection *active, error_desc); } - g_assert (error); nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ACTIVATE, connection, FALSE, NULL, subject, error->message); - _internal_activation_failed (self, active, error->message); + nm_active_connection_set_state_fail (active, + NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN, + error->message); - g_object_unref (active); g_dbus_method_invocation_take_error (context, error); } @@ -4251,8 +4249,8 @@ impl_manager_activate_connection (NMManager *self, const char *specific_object_path) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMActiveConnection *active = NULL; - NMAuthSubject *subject = NULL; + gs_unref_object NMActiveConnection *active = NULL; + gs_unref_object NMAuthSubject *subject = NULL; NMSettingsConnection *connection = NULL; NMDevice *device = NULL; gboolean is_vpn = FALSE; @@ -4319,8 +4317,14 @@ impl_manager_activate_connection (NMManager *self, if (!active) goto error; - nm_active_connection_authorize (active, NULL, _activation_auth_done, self, context); - g_clear_object (&subject); + /* FIXME: nm_active_connection_authorize() is not cancellable, + * and we pass on the only reference to @active. This construct + * is unsuitable for a coordinated shutdown. */ + nm_active_connection_authorize (g_steal_pointer (&active), + NULL, + _activation_auth_done, + self, + context); return; error: @@ -4328,10 +4332,6 @@ error: nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ACTIVATE, connection, FALSE, NULL, subject, error->message); } - g_clear_object (&active); - g_clear_object (&subject); - - g_assert (error); g_dbus_method_invocation_take_error (context, error); } @@ -4385,8 +4385,10 @@ activation_add_done (NMSettings *settings, error = local; } - g_assert (error); - _internal_activation_failed (self, active, error->message); + nm_assert (error); + nm_active_connection_set_state_fail (active, + NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN, + error->message); if (new_connection) nm_settings_connection_delete (new_connection, NULL); g_dbus_method_invocation_return_gerror (context, error); diff --git a/src/nm-policy.c b/src/nm-policy.c index 4d0ef91a..b73e04cb 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -1758,10 +1758,16 @@ device_state_changed (NMDevice *device, * been consulted, and it may be able to provide the secrets. * * We detect this by using a version-id of the agent-manager, which increments - * whenever new agents register. */ + * whenever new agents register. Note that the agent-manager's version-id is + * never zero and strictly increasing. + * + * A connection's version-id of zero means that the connection never tried to request secrets. + * That can happen when nm_settings_connection_get_secrets() fails early without actually + * consulting any agents. + */ con_v = nm_settings_connection_get_last_secret_agent_version_id (connection); if ( con_v == 0 - || con_v != nm_agent_manager_get_agent_version_id (priv->agent_mgr)) + || con_v == nm_agent_manager_get_agent_version_id (priv->agent_mgr)) block_no_secrets = TRUE; } diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index fe270e88..e5961c7e 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -4437,10 +4437,13 @@ event_valid_msg (NMPlatform *platform, struct nl_msg *msg, gboolean handle_event nm_auto_nmpobj const NMPObject *obj_replace = NULL; gboolean resync_required = FALSE; gboolean only_dirty = FALSE; + gboolean is_ipv6; - if (NM_FLAGS_HAS (obj->ip_route.r_rtm_flags, RTM_F_CLONED)) { - /* a cloned route might be a response for RTM_GETROUTE. Check, whether it is. */ - nm_assert (!nmp_object_is_alive (obj)); + /* IPv4 routes that are a response to RTM_GETROUTE must have + * the cloned flag while IPv6 routes don't have to. */ + is_ipv6 = NMP_OBJECT_GET_TYPE (obj) == NMP_OBJECT_TYPE_IP6_ROUTE; + if (is_ipv6 || NM_FLAGS_HAS (obj->ip_route.r_rtm_flags, RTM_F_CLONED)) { + nm_assert (is_ipv6 || !nmp_object_is_alive (obj)); priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); if (NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)) { guint i; diff --git a/src/platform/nmp-netns.c b/src/platform/nmp-netns.c index bc305f01..d8561aef 100644 --- a/src/platform/nmp-netns.c +++ b/src/platform/nmp-netns.c @@ -475,6 +475,7 @@ nmp_netns_new (void) NMPNetns *self; int errsv; GError *error = NULL; + unsigned long mountflags = 0; _stack_ensure_init (); @@ -503,7 +504,10 @@ nmp_netns_new (void) goto err_out; } - if (mount ("sysfs", "/sys", "sysfs", 0, NULL) != 0) { + if (access ("/sys", W_OK) == -1) + mountflags = MS_RDONLY; + + if (mount ("sysfs", "/sys", "sysfs", mountflags, NULL) != 0) { errsv = errno; _LOGE (NULL, "failed mount /sys: %s", g_strerror (errsv)); goto err_out; diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c index 9a12f8f9..d56e681e 100644 --- a/src/platform/tests/test-common.c +++ b/src/platform/tests/test-common.c @@ -1931,47 +1931,12 @@ main (int argc, char **argv) g_error ("unshare(CLONE_NEWNET|CLONE_NEWNS) failed with %s (%d)", strerror (errsv), errsv); } - /* Below we need a read-only /sys (to signal that we're in an environment - * we don't have udev and writable /sys/devices so that we still are able - * to test device classes that modify the device attributes (such as bridges). - * - * We use two sysfs instances to achieve this, binding the /device subtree - * of the writeable one to the read-only one. - * - * We abuse a /sys/kernel/debug for our temporary writable sysfs mount, - * just because it's guarranteed to exist and mounts are allowed there even - * after the sysfs mount point hardening [linux 0cbee99269]. It's just in - * our mount namespace, we release it quickly and don't need debugfs anyway... - * An alrernative would be to create a temporary directory, but that seems - * like an overkill. */ - - /* Make the mounts below /sys private to our namespace. Other mounts - * wouldn't be permitted for good reasons. */ + /* We need a read-only /sys so that the platform knows there's no udev. */ mount (NULL, "/sys", "sysfs", MS_SLAVE, NULL); - - /* Mount the read-only sysfs. */ if (mount ("sys", "/sys", "sysfs", MS_RDONLY, NULL) != 0) { errsv = errno; g_error ("mount(\"/sys\") failed with %s (%d)", strerror (errsv), errsv); } - - /* Create the writable /sys/devices tree. */ - if (mount ("sys", "/sys/kernel/debug", "sysfs", 0, NULL) != 0) { - errsv = errno; - g_error ("mount(\"/sys/devices/k\") failed with %s (%d)", strerror (errsv), errsv); - } - - /* Bind mound the writable device tree to the read-only sysfs. */ - if (mount ("/sys/kernel/debug/devices", "/sys/devices", "sysfs", MS_BIND, NULL) != 0) { - errsv = errno; - g_error ("mount(\"/sys\") failed with %s (%d)", strerror (errsv), errsv); - } - - /* Release the temporary mount now that we bound the /devices subtree. */ - if (umount ("/sys/kernel/debug") != 0) { - errsv = errno; - g_error ("umount(\"/sys/kernel/debug\") failed with %s (%d)", strerror (errsv), errsv); - } } nmtstp_setup_platform (); diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index d3a10bd6..ef78cc24 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -1949,6 +1949,17 @@ _test_netns_check_skip (void) return FALSE; } +static gboolean +_check_sysctl_skip (void) +{ + if (access ("/proc/sys/net/ipv4/ip_forward", W_OK) == -1) { + g_test_skip ("Can not write sysctls"); + return TRUE; + } + + return FALSE; +} + /*****************************************************************************/ #define _sysctl_assert_eq(plat, path, value) \ @@ -1973,6 +1984,9 @@ test_netns_general (gpointer fixture, gconstpointer test_data) if (_test_netns_check_skip ()) return; + if (_check_sysctl_skip ()) + return; + platform_1 = nm_linux_platform_new (TRUE, TRUE); platform_2 = _test_netns_create_platform (); @@ -2168,6 +2182,9 @@ test_netns_push (gpointer fixture, gconstpointer test_data) if (_test_netns_check_skip ()) return; + if (_check_sysctl_skip ()) + return; + pl[0].platform = platform_0 = nm_linux_platform_new (TRUE, TRUE); pl[1].platform = platform_1 = _test_netns_create_platform (); pl[2].platform = platform_2 = _test_netns_create_platform (); diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c index fe97db07..13648f16 100644 --- a/src/platform/tests/test-route.c +++ b/src/platform/tests/test-route.c @@ -424,7 +424,7 @@ test_ip6_route (void) /*****************************************************************************/ static void -test_ip_route_get (void) +test_ip4_route_get (void) { int ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); in_addr_t a; @@ -586,6 +586,45 @@ test_ip4_route_options (gconstpointer test_data) } static void +test_ip6_route_get (void) +{ + int ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); + const struct in6_addr *a; + NMPlatformError result; + nm_auto_nmpobj NMPObject *route = NULL; + const NMPlatformIP6Route *r; + + nmtstp_run_command_check ("ip -6 route add fd01:abcd::/64 via fe80::99 dev %s", DEVICE_NAME); + + NMTST_WAIT_ASSERT (100, { + nmtstp_wait_for_signal (NM_PLATFORM_GET, 10); + if (nmtstp_ip6_route_get (NM_PLATFORM_GET, ifindex, nmtst_inet6_from_string ("fd01:abcd::"), 64, 0, NULL, 0)) + break; + }); + + a = nmtst_inet6_from_string ("fd01:abcd::42"); + result = nm_platform_ip_route_get (NM_PLATFORM_GET, + AF_INET6, + a, + nmtst_get_rand_int () % 2 ? 0 : ifindex, + &route); + + g_assert (result == NM_PLATFORM_ERROR_SUCCESS); + g_assert (NMP_OBJECT_GET_TYPE (route) == NMP_OBJECT_TYPE_IP6_ROUTE); + g_assert (!NMP_OBJECT_IS_STACKINIT (route)); + g_assert (route->parent._ref_count == 1); + r = NMP_OBJECT_CAST_IP6_ROUTE (route); + g_assert (r->ifindex == ifindex); + nmtst_assert_ip6_address (&r->network, "fd01:abcd::42"); + g_assert_cmpint (r->plen, ==, 128); + nmtst_assert_ip6_address (&r->gateway, "fe80::99"); + + nmtstp_run_command_check ("ip -6 route flush dev %s", DEVICE_NAME); + + nmtstp_wait_for_signal (NM_PLATFORM_GET, 50); +} + +static void test_ip6_route_options (gconstpointer test_data) { const int TEST_IDX = GPOINTER_TO_INT (test_data); @@ -860,7 +899,8 @@ _nmtstp_setup_tests (void) if (nmtstp_is_root_test ()) { add_test_func_data ("/route/ip/1", test_ip, GINT_TO_POINTER (1)); - add_test_func ("/route/ip_route_get", test_ip_route_get); + add_test_func ("/route/ip4_route_get", test_ip4_route_get); + add_test_func ("/route/ip6_route_get", test_ip6_route_get); add_test_func ("/route/ip4_zero_gateway", test_ip4_zero_gateway); } } diff --git a/src/ppp/nm-ppp-manager.c b/src/ppp/nm-ppp-manager.c index 7dd6a9b9..743f80a2 100644 --- a/src/ppp/nm-ppp-manager.c +++ b/src/ppp/nm-ppp-manager.c @@ -139,11 +139,11 @@ static void _ppp_kill (NMPPPManager *manager); /*****************************************************************************/ static void -_ppp_manager_set_route_paramters (NMPPPManager *self, - guint32 ip4_route_table, - guint32 ip4_route_metric, - guint32 ip6_route_table, - guint32 ip6_route_metric) +_ppp_manager_set_route_parameters (NMPPPManager *self, + guint32 ip4_route_table, + guint32 ip4_route_metric, + guint32 ip6_route_table, + guint32 ip6_route_metric) { NMPPPManagerPrivate *priv; @@ -1359,7 +1359,7 @@ nm_ppp_manager_class_init (NMPPPManagerClass *manager_class) NMPPPOps ppp_ops = { .create = _ppp_manager_new, - .set_route_parameters = _ppp_manager_set_route_paramters, + .set_route_parameters = _ppp_manager_set_route_parameters, .start = _ppp_manager_start, .stop_async = _ppp_manager_stop_async, .stop_finish = _ppp_manager_stop_finish, diff --git a/src/ppp/nm-pppd-plugin.c b/src/ppp/nm-pppd-plugin.c index 9c47c339..0ac8f907 100644 --- a/src/ppp/nm-pppd-plugin.c +++ b/src/ppp/nm-pppd-plugin.c @@ -281,7 +281,6 @@ get_credentials (char *username, char *password) { const char *my_username = NULL; const char *my_password = NULL; - size_t len; GVariant *ret; GError *err = NULL; @@ -313,21 +312,11 @@ get_credentials (char *username, char *password) g_variant_get (ret, "(&s&s)", &my_username, &my_password); - if (my_username) { - len = strlen (my_username) + 1; - len = len < MAXNAMELEN ? len : MAXNAMELEN; + if (my_username) + g_strlcpy (username, my_username, MAXNAMELEN); - strncpy (username, my_username, len); - username[len - 1] = '\0'; - } - - if (my_password) { - len = strlen (my_password) + 1; - len = len < MAXSECRETLEN ? len : MAXSECRETLEN; - - strncpy (password, my_password, len); - password[len - 1] = '\0'; - } + if (my_password) + g_strlcpy (password, my_password, MAXSECRETLEN); g_variant_unref (ret); diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c index 37a0b3a6..58626372 100644 --- a/src/settings/nm-settings-connection.c +++ b/src/settings/nm-settings-connection.c @@ -608,6 +608,7 @@ nm_settings_connection_update (NMSettingsConnection *self, gboolean replaced = FALSE; gs_free char *logmsg_change = NULL; GError *local = NULL; + gs_unref_variant GVariant *con_agent_secrets = NULL; g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION (self), FALSE); @@ -658,9 +659,20 @@ nm_settings_connection_update (NMSettingsConnection *self, && !nm_connection_compare (NM_CONNECTION (self), replace_connection, NM_SETTING_COMPARE_FLAG_EXACT)) { + gs_unref_object NMConnection *simple = NULL; + if (log_diff_name) nm_utils_log_connection_diff (replace_connection, NM_CONNECTION (self), LOGL_DEBUG, LOGD_CORE, log_diff_name, "++ "); + /* Make a copy of agent-owned secrets because they won't be present in + * the connection returned by plugins, as plugins return only what was + * reread from the file. */ + simple = nm_simple_connection_new_clone (NM_CONNECTION (self)); + nm_connection_clear_secrets_with_flags (simple, + secrets_filter_cb, + GUINT_TO_POINTER (NM_SETTING_SECRET_FLAG_AGENT_OWNED)); + con_agent_secrets = nm_connection_to_dbus (simple, NM_CONNECTION_SERIALIZE_ONLY_SECRETS); + nm_connection_replace_settings_from_connection (NM_CONNECTION (self), replace_connection); replaced = TRUE; @@ -688,6 +700,8 @@ nm_settings_connection_update (NMSettingsConnection *self, g_variant_unref (dict); } } + if (con_agent_secrets) + (void) nm_connection_update_secrets (NM_CONNECTION (self), NULL, con_agent_secrets, NULL); } nm_settings_connection_recheck_visibility (self); diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c index 51b7bea7..8e3fc582 100644 --- a/src/settings/nm-settings.c +++ b/src/settings/nm-settings.c @@ -1337,7 +1337,7 @@ impl_settings_add_connection_helper (NMSettings *self, GVariant *settings, gboolean save_to_disk) { - NMConnection *connection; + gs_unref_object NMConnection *connection = NULL; GError *error = NULL; connection = _nm_simple_connection_new_from_dbus (settings, @@ -1345,23 +1345,18 @@ impl_settings_add_connection_helper (NMSettings *self, | NM_SETTING_PARSE_FLAGS_NORMALIZE, &error); - if (connection) { - if (!nm_connection_verify_secrets (connection, &error)) - goto failure; - - nm_settings_add_connection_dbus (self, - connection, - save_to_disk, - context, - impl_settings_add_connection_add_cb, - NULL); - g_object_unref (connection); + if ( !connection + || !nm_connection_verify_secrets (connection, &error)) { + g_dbus_method_invocation_take_error (context, error); return; } -failure: - g_assert (error); - g_dbus_method_invocation_take_error (context, error); + nm_settings_add_connection_dbus (self, + connection, + save_to_disk, + context, + impl_settings_add_connection_add_cb, + NULL); } static void diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c index bdd3ee0a..c91cd253 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -558,7 +558,7 @@ enum { PARSE_LINE_ATTR_ROUTE_VIA, PARSE_LINE_ATTR_ROUTE_METRIC, - /* iproute2 paramters that are well known and that we silently ignore. */ + /* iproute2 parameters that are well known and that we silently ignore. */ PARSE_LINE_ATTR_ROUTE_DEV, }; diff --git a/src/settings/plugins/keyfile/nms-keyfile-plugin.c b/src/settings/plugins/keyfile/nms-keyfile-plugin.c index cb5f2c9f..e6299d1e 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-plugin.c +++ b/src/settings/plugins/keyfile/nms-keyfile-plugin.c @@ -143,7 +143,7 @@ find_by_path (NMSKeyfilePlugin *self, const char *path) * an existing connection with the same UUID. * If %TRUE and @connection, allow updating only if the reload would modify * @connection (without changing its UUID) or if we would create a new connection. - * In other words, if this paramter is %TRUE, we only allow creating a + * In other words, if this parameter is %TRUE, we only allow creating a * new connection (with an unseen UUID) or updating the passed in @connection * (whereas the UUID cannot change). * Note, that this allows for @connection to be replaced by a new connection. |