diff options
Diffstat (limited to 'src/devices')
41 files changed, 3071 insertions, 1741 deletions
diff --git a/src/devices/adsl/nm-atm-manager.c b/src/devices/adsl/nm-atm-manager.c index b04e9fe7..32c4c386 100644 --- a/src/devices/adsl/nm-atm-manager.c +++ b/src/devices/adsl/nm-atm-manager.c @@ -21,13 +21,14 @@ #include "nm-default.h" #include <string.h> -#include <gudev/gudev.h> #include <gmodule.h> +#include <libudev.h> #include "nm-setting-adsl.h" #include "nm-device-adsl.h" #include "devices/nm-device-factory.h" #include "platform/nm-platform.h" +#include "nm-utils/nm-udev-utils.h" /*****************************************************************************/ @@ -39,7 +40,7 @@ #define NM_ATM_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_ATM_MANAGER, NMAtmManagerClass)) typedef struct { - GUdevClient *client; + NMUdevClient *udev_client; GSList *devices; } NMAtmManagerPrivate; @@ -73,35 +74,34 @@ nm_device_factory_create (GError **error) /*****************************************************************************/ static gboolean -dev_get_attrs (GUdevDevice *udev_device, +dev_get_attrs (struct udev_device *udev_device, const char **out_path, char **out_driver) { - GUdevDevice *parent = NULL; + struct udev_device *parent = NULL; const char *driver, *path; g_return_val_if_fail (udev_device != NULL, FALSE); g_return_val_if_fail (out_path != NULL, FALSE); g_return_val_if_fail (out_driver != NULL, FALSE); - path = g_udev_device_get_sysfs_path (udev_device); + path = udev_device_get_syspath (udev_device); if (!path) { nm_log_warn (LOGD_PLATFORM, "couldn't determine device path; ignoring..."); return FALSE; } - driver = g_udev_device_get_driver (udev_device); + driver = udev_device_get_driver (udev_device); if (!driver) { /* Try the parent */ - parent = g_udev_device_get_parent (udev_device); + parent = udev_device_get_parent (udev_device); if (parent) - driver = g_udev_device_get_driver (parent); + driver = udev_device_get_driver (parent); } *out_path = path; *out_driver = g_strdup (driver); - g_clear_object (&parent); return TRUE; } @@ -115,7 +115,7 @@ device_destroyed (gpointer user_data, GObject *dead) } static void -adsl_add (NMAtmManager *self, GUdevDevice *udev_device) +adsl_add (NMAtmManager *self, struct udev_device *udev_device) { NMAtmManagerPrivate *priv = NM_ATM_MANAGER_GET_PRIVATE (self); const char *ifname, *sysfs_path = NULL; @@ -126,7 +126,7 @@ adsl_add (NMAtmManager *self, GUdevDevice *udev_device) g_return_if_fail (udev_device != NULL); - ifname = g_udev_device_get_name (udev_device); + ifname = udev_device_get_sysname (udev_device); if (!ifname) { nm_log_warn (LOGD_PLATFORM, "failed to get device's interface name"); return; @@ -165,10 +165,10 @@ adsl_add (NMAtmManager *self, GUdevDevice *udev_device) } static void -adsl_remove (NMAtmManager *self, GUdevDevice *udev_device) +adsl_remove (NMAtmManager *self, struct udev_device *udev_device) { NMAtmManagerPrivate *priv = NM_ATM_MANAGER_GET_PRIVATE (self); - const char *iface = g_udev_device_get_name (udev_device); + const char *iface = udev_device_get_sysname (udev_device); GSList *iter; nm_log_dbg (LOGD_PLATFORM, "(%s): removing ATM device", iface); @@ -194,42 +194,49 @@ start (NMDeviceFactory *factory) { NMAtmManager *self = NM_ATM_MANAGER (factory); NMAtmManagerPrivate *priv = NM_ATM_MANAGER_GET_PRIVATE (self); - GUdevEnumerator *enumerator; - GList *devices, *iter; - - enumerator = g_udev_enumerator_new (priv->client); - g_udev_enumerator_add_match_subsystem (enumerator, "atm"); - g_udev_enumerator_add_match_is_initialized (enumerator); - devices = g_udev_enumerator_execute (enumerator); - for (iter = devices; iter; iter = g_list_next (iter)) { - adsl_add (self, G_UDEV_DEVICE (iter->data)); - g_object_unref (G_UDEV_DEVICE (iter->data)); + struct udev_enumerate *enumerate; + struct udev_list_entry *devices; + + enumerate = nm_udev_client_enumerate_new (priv->udev_client); + udev_enumerate_add_match_is_initialized (enumerate); + udev_enumerate_scan_devices (enumerate); + devices = udev_enumerate_get_list_entry (enumerate); + for (; devices; devices = udev_list_entry_get_next (devices)) { + struct udev_device *udevice; + + udevice = udev_device_new_from_syspath (udev_enumerate_get_udev (enumerate), + udev_list_entry_get_name (devices)); + if (udevice) { + adsl_add (self, udevice); + udev_device_unref (udevice); + } } - g_list_free (devices); - g_object_unref (enumerator); + udev_enumerate_unref (enumerate); } static void -handle_uevent (GUdevClient *client, - const char *action, - GUdevDevice *device, +handle_uevent (NMUdevClient *client, + struct udev_device *device, gpointer user_data) { NMAtmManager *self = NM_ATM_MANAGER (user_data); const char *subsys; const char *ifindex; guint64 seqnum; + const char *action; + + action = udev_device_get_action (device); g_return_if_fail (action != NULL); /* A bit paranoid */ - subsys = g_udev_device_get_subsystem (device); + subsys = udev_device_get_subsystem (device); g_return_if_fail (!g_strcmp0 (subsys, "atm")); - ifindex = g_udev_device_get_property (device, "IFINDEX"); - seqnum = g_udev_device_get_seqnum (device); + ifindex = udev_device_get_property_value (device, "IFINDEX"); + seqnum = udev_device_get_seqnum (device); nm_log_dbg (LOGD_PLATFORM, "UDEV event: action '%s' subsys '%s' device '%s' (%s); seqnum=%" G_GUINT64_FORMAT, - action, subsys, g_udev_device_get_name (device), ifindex ? ifindex : "unknown", seqnum); + action, subsys, udev_device_get_sysname (device), ifindex ? ifindex : "unknown", seqnum); if (!strcmp (action, "add")) adsl_add (self, device); @@ -243,10 +250,9 @@ static void nm_atm_manager_init (NMAtmManager *self) { NMAtmManagerPrivate *priv = NM_ATM_MANAGER_GET_PRIVATE (self); - const char *subsys[] = { "atm", NULL }; - priv->client = g_udev_client_new (subsys); - g_signal_connect (priv->client, "uevent", G_CALLBACK (handle_uevent), self); + priv->udev_client = nm_udev_client_new ((const char *[]) {"atm", NULL }, + handle_uevent, self); } static void @@ -256,15 +262,12 @@ dispose (GObject *object) NMAtmManagerPrivate *priv = NM_ATM_MANAGER_GET_PRIVATE (self); GSList *iter; - if (priv->client) { - g_signal_handlers_disconnect_by_func (priv->client, handle_uevent, self); - g_clear_object (&priv->client); - } - for (iter = priv->devices; iter; iter = iter->next) g_object_weak_unref (G_OBJECT (iter->data), device_destroyed, self); g_clear_pointer (&priv->devices, g_slist_free); + priv->udev_client = nm_udev_client_unref (priv->udev_client); + G_OBJECT_CLASS (nm_atm_manager_parent_class)->dispose (object); } diff --git a/src/devices/adsl/nm-device-adsl.c b/src/devices/adsl/nm-device-adsl.c index 53841a7f..fe622bdf 100644 --- a/src/devices/adsl/nm-device-adsl.c +++ b/src/devices/adsl/nm-device-adsl.c @@ -129,7 +129,7 @@ complete_connection (NMDevice *device, if (s_adsl && !nm_setting_verify (NM_SETTING (s_adsl), NULL, error)) return FALSE; - nm_utils_complete_generic (NM_PLATFORM_GET, + nm_utils_complete_generic (nm_device_get_platform (device), connection, NM_SETTING_ADSL_SETTING_NAME, existing_connections, @@ -273,14 +273,14 @@ pppoe_vcc_config (NMDeviceAdsl *self) return FALSE; /* Watch for the 'nas' interface going away */ - g_signal_connect (NM_PLATFORM_GET, NM_PLATFORM_SIGNAL_LINK_CHANGED, + g_signal_connect (nm_device_get_platform (device), NM_PLATFORM_SIGNAL_LINK_CHANGED, G_CALLBACK (link_changed_cb), self); _LOGD (LOGD_ADSL, "ATM setup successful"); /* otherwise we're good for stage3 */ - nm_platform_link_set_up (NM_PLATFORM_GET, priv->nas_ifindex, NULL); + nm_platform_link_set_up (nm_device_get_platform (device), priv->nas_ifindex, NULL); return TRUE; } @@ -306,7 +306,7 @@ nas_update_cb (gpointer user_data) } g_warn_if_fail (priv->nas_ifindex < 0); - priv->nas_ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, priv->nas_ifname); + priv->nas_ifindex = nm_platform_link_get_ifindex (nm_device_get_platform (device), priv->nas_ifname); if (priv->nas_ifindex < 0) { /* Keep waiting for it to appear */ return G_SOURCE_CONTINUE; @@ -329,12 +329,12 @@ nas_update_cb (gpointer user_data) static NMActStageReturn br2684_create_iface (NMDeviceAdsl *self, NMSettingAdsl *s_adsl, - NMDeviceStateReason *out_reason) + NMDeviceStateReason *out_failure_reason) { NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self); struct atm_newif_br2684 ni; - int err, fd, errsv; - NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; + nm_auto_close int fd = -1; + int err, errsv; guint num = 0; g_return_val_if_fail (s_adsl != NULL, FALSE); @@ -348,7 +348,7 @@ br2684_create_iface (NMDeviceAdsl *self, if (fd < 0) { errsv = errno; _LOGE (LOGD_ADSL, "failed to open ATM control socket (%d)", errsv); - *out_reason = NM_DEVICE_STATE_REASON_BR2684_FAILED; + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_BR2684_FAILED); return NM_ACT_STAGE_RETURN_FAILURE; } @@ -374,39 +374,36 @@ br2684_create_iface (NMDeviceAdsl *self, priv->nas_update_count = 0; priv->nas_update_id = g_timeout_add (100, nas_update_cb, self); - ret = NM_ACT_STAGE_RETURN_POSTPONE; - break; - } else if (errno != EEXIST) { + return NM_ACT_STAGE_RETURN_POSTPONE; + } + if (errno != EEXIST) { errsv = errno; _LOGW (LOGD_ADSL, "failed to create br2684 interface (%d)", errsv); - *out_reason = NM_DEVICE_STATE_REASON_BR2684_FAILED; break; } } - close (fd); - return ret; + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_BR2684_FAILED); + return NM_ACT_STAGE_RETURN_FAILURE; } static NMActStageReturn -act_stage2_config (NMDevice *device, NMDeviceStateReason *out_reason) +act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMDeviceAdsl *self = NM_DEVICE_ADSL (device); NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; NMSettingAdsl *s_adsl; const char *protocol; - g_assert (out_reason); - s_adsl = nm_connection_get_setting_adsl (nm_device_get_applied_connection (device)); - g_assert (s_adsl); + g_return_val_if_fail (s_adsl, NM_ACT_STAGE_RETURN_FAILURE); protocol = nm_setting_adsl_get_protocol (s_adsl); _LOGD (LOGD_ADSL, "using ADSL protocol '%s'", protocol); if (g_strcmp0 (protocol, NM_SETTING_ADSL_PROTOCOL_PPPOE) == 0) { /* PPPoE needs RFC2684 bridging before we can do PPP over it */ - ret = br2684_create_iface (self, s_adsl, out_reason); + ret = br2684_create_iface (self, s_adsl, out_failure_reason); } else if (g_strcmp0 (protocol, NM_SETTING_ADSL_PROTOCOL_PPPOA) == 0) { /* PPPoA doesn't need anything special */ ret = NM_ACT_STAGE_RETURN_SUCCESS; @@ -451,20 +448,19 @@ ppp_ip4_config (NMPPPManager *ppp_manager, static NMActStageReturn act_stage3_ip4_config_start (NMDevice *device, NMIP4Config **out_config, - NMDeviceStateReason *reason) + NMDeviceStateReason *out_failure_reason) { NMDeviceAdsl *self = NM_DEVICE_ADSL (device); NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self); NMSettingAdsl *s_adsl; NMActRequest *req; GError *err = NULL; - NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; const char *ppp_iface; req = nm_device_get_act_request (device); - g_assert (req); + g_return_val_if_fail (req, NM_ACT_STAGE_RETURN_FAILURE); s_adsl = (NMSettingAdsl *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_ADSL); - g_assert (s_adsl); + g_return_val_if_fail (s_adsl, NM_ACT_STAGE_RETURN_FAILURE); /* PPPoE uses the NAS interface, not the ATM interface */ if (g_strcmp0 (nm_setting_adsl_get_protocol (s_adsl), NM_SETTING_ADSL_PROTOCOL_PPPOE) == 0) { @@ -478,27 +474,26 @@ act_stage3_ip4_config_start (NMDevice *device, } priv->ppp_manager = nm_ppp_manager_create (ppp_iface, &err); - if ( priv->ppp_manager - && nm_ppp_manager_start (priv->ppp_manager, req, - nm_setting_adsl_get_username (s_adsl), - 30, 0, &err)) { - g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_STATE_CHANGED, - G_CALLBACK (ppp_state_changed), - self); - g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_IP4_CONFIG, - G_CALLBACK (ppp_ip4_config), - self); - ret = NM_ACT_STAGE_RETURN_POSTPONE; - } else { + if ( !priv->ppp_manager + || !nm_ppp_manager_start (priv->ppp_manager, req, + nm_setting_adsl_get_username (s_adsl), + 30, 0, &err)) { _LOGW (LOGD_ADSL, "PPP failed to start: %s", err->message); g_error_free (err); g_clear_object (&priv->ppp_manager); - *reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED; + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_PPP_START_FAILED); + return NM_ACT_STAGE_RETURN_FAILURE; } - return ret; + g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_STATE_CHANGED, + G_CALLBACK (ppp_state_changed), + self); + g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_IP4_CONFIG, + G_CALLBACK (ppp_ip4_config), + self); + return NM_ACT_STAGE_RETURN_POSTPONE; } static void @@ -513,7 +508,7 @@ adsl_cleanup (NMDeviceAdsl *self) g_clear_object (&priv->ppp_manager); } - g_signal_handlers_disconnect_by_func (NM_PLATFORM_GET, G_CALLBACK (link_changed_cb), self); + g_signal_handlers_disconnect_by_func (nm_device_get_platform (NM_DEVICE (self)), G_CALLBACK (link_changed_cb), self); if (priv->brfd >= 0) { close (priv->brfd); @@ -547,7 +542,7 @@ carrier_update_cb (gpointer user_data) path = g_strdup_printf ("/sys/class/atm/%s/carrier", NM_ASSERT_VALID_PATH_COMPONENT (nm_device_get_iface (NM_DEVICE (self)))); - carrier = (int) nm_platform_sysctl_get_int_checked (NM_PLATFORM_GET, NMP_SYSCTL_PATHID_ABSOLUTE (path), 10, 0, 1, -1); + carrier = (int) nm_platform_sysctl_get_int_checked (nm_device_get_platform (NM_DEVICE (self)), NMP_SYSCTL_PATHID_ABSOLUTE (path), 10, 0, 1, -1); g_free (path); if (carrier != -1) diff --git a/src/devices/bluetooth/nm-bluez-device.c b/src/devices/bluetooth/nm-bluez-device.c index 92b2c918..ebfa0d64 100644 --- a/src/devices/bluetooth/nm-bluez-device.c +++ b/src/devices/bluetooth/nm-bluez-device.c @@ -183,7 +183,8 @@ pan_connection_check_create (NMBluezDevice *self) NMConnection *connection; NMConnection *added; NMSetting *setting; - char *uuid, *id; + char *id; + char uuid[37]; GError *error = NULL; NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); @@ -205,7 +206,7 @@ pan_connection_check_create (NMBluezDevice *self) connection = nm_simple_connection_new (); /* Setting: Connection */ - uuid = nm_utils_uuid_generate (); + nm_utils_uuid_generate_buf (uuid); id = g_strdup_printf (_("%s Network"), priv->name); setting = nm_setting_connection_new (); g_object_set (setting, @@ -266,7 +267,6 @@ pan_connection_check_create (NMBluezDevice *self) g_object_unref (connection); g_free (id); - g_free (uuid); } static gboolean diff --git a/src/devices/bluetooth/nm-bluez-manager.c b/src/devices/bluetooth/nm-bluez-manager.c index 58fa9b01..2f0afa16 100644 --- a/src/devices/bluetooth/nm-bluez-manager.c +++ b/src/devices/bluetooth/nm-bluez-manager.c @@ -134,10 +134,7 @@ cleanup_checking (NMBluezManager *self, gboolean do_unwatch_name) { NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - if (priv->async_cancellable) { - g_cancellable_cancel (priv->async_cancellable); - g_clear_object (&priv->async_cancellable); - } + nm_clear_g_cancellable (&priv->async_cancellable); g_clear_object (&priv->introspect_proxy); diff --git a/src/devices/bluetooth/nm-bt-error.c b/src/devices/bluetooth/nm-bt-error.c index 18391187..66c65b6d 100644 --- a/src/devices/bluetooth/nm-bt-error.c +++ b/src/devices/bluetooth/nm-bt-error.c @@ -22,13 +22,5 @@ #include "nm-bt-error.h" -GQuark -nm_bt_error_quark (void) -{ - static GQuark quark = 0; - if (!quark) - quark = g_quark_from_static_string ("nm-bt-error"); - return quark; -} - +NM_CACHED_QUARK_FCN ("nm-bt-error", nm_bt_error_quark) diff --git a/src/devices/bluetooth/nm-device-bt.c b/src/devices/bluetooth/nm-device-bt.c index 31b9bbf9..4ee71489 100644 --- a/src/devices/bluetooth/nm-device-bt.c +++ b/src/devices/bluetooth/nm-device-bt.c @@ -99,7 +99,7 @@ G_DEFINE_TYPE (NMDeviceBt, nm_device_bt, NM_TYPE_DEVICE) /*****************************************************************************/ -static gboolean modem_stage1 (NMDeviceBt *self, NMModem *modem, NMDeviceStateReason *reason); +static gboolean modem_stage1 (NMDeviceBt *self, NMModem *modem, NMDeviceStateReason *out_failure_reason); /*****************************************************************************/ @@ -328,7 +328,7 @@ complete_connection (NMDevice *device, return FALSE; } - nm_utils_complete_generic (NM_PLATFORM_GET, + nm_utils_complete_generic (nm_device_get_platform (device), connection, NM_SETTING_BLUETOOTH_SETTING_NAME, existing_connections, @@ -362,18 +362,24 @@ complete_connection (NMDevice *device, static void ppp_stats (NMModem *modem, - guint32 in_bytes, - guint32 out_bytes, + guint i_in_bytes, + guint i_out_bytes, gpointer user_data) { - g_signal_emit (NM_DEVICE_BT (user_data), signals[PPP_STATS], 0, in_bytes, out_bytes); + guint32 in_bytes = i_in_bytes; + guint32 out_bytes = i_out_bytes; + + g_signal_emit (NM_DEVICE_BT (user_data), signals[PPP_STATS], 0, (guint) in_bytes, (guint) out_bytes); } static void -ppp_failed (NMModem *modem, NMDeviceStateReason reason, gpointer user_data) +ppp_failed (NMModem *modem, + guint i_reason, + gpointer user_data) { NMDevice *device = NM_DEVICE (user_data); NMDeviceBt *self = NM_DEVICE_BT (user_data); + NMDeviceStateReason reason = i_reason; switch (nm_device_get_state (device)) { case NM_DEVICE_STATE_PREPARE: @@ -430,28 +436,30 @@ modem_auth_result (NMModem *modem, GError *error, gpointer user_data) { NMDevice *device = NM_DEVICE (user_data); NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE ((NMDeviceBt *) device); - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; if (error) { nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NO_SECRETS); } else { + NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE; + /* Otherwise, on success for GSM/CDMA secrets we need to schedule modem stage1 again */ g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH); - if (!modem_stage1 (NM_DEVICE_BT (device), priv->modem, &reason)) - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason); + if (!modem_stage1 (NM_DEVICE_BT (device), priv->modem, &failure_reason)) + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, failure_reason); } } static void modem_prepare_result (NMModem *modem, gboolean success, - NMDeviceStateReason reason, + guint i_reason, gpointer user_data) { NMDeviceBt *self = NM_DEVICE_BT (user_data); NMDevice *device = NM_DEVICE (self); + NMDeviceStateReason reason = i_reason; NMDeviceState state; state = nm_device_get_state (device); @@ -460,12 +468,12 @@ modem_prepare_result (NMModem *modem, if (success) { NMActRequest *req; NMActStageReturn ret; - NMDeviceStateReason stage2_reason = NM_DEVICE_STATE_REASON_NONE; + NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE; req = nm_device_get_act_request (device); - g_assert (req); + g_return_if_fail (req); - ret = nm_modem_act_stage2_config (modem, req, &stage2_reason); + ret = nm_modem_act_stage2_config (modem, req, &failure_reason); switch (ret) { case NM_ACT_STAGE_RETURN_POSTPONE: break; @@ -474,17 +482,17 @@ modem_prepare_result (NMModem *modem, break; case NM_ACT_STAGE_RETURN_FAILURE: default: - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, stage2_reason); + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, failure_reason); break; } } else { - if (reason == NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT) { + if (nm_device_state_reason_check (reason) == NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT) { /* If the connect failed because the SIM PIN was wrong don't allow * the device to be auto-activated anymore, which would risk locking * the SIM if the incorrect PIN continues to be used. */ - nm_device_set_autoconnect (device, FALSE); _LOGI (LOGD_MB, "disabling autoconnect due to failed SIM PIN"); + nm_device_set_autoconnect_intern (device, FALSE); } nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason); @@ -500,7 +508,7 @@ device_state_changed (NMDevice *device, NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE ((NMDeviceBt *) device); if (priv->modem) - nm_modem_device_state_changed (priv->modem, new_state, old_state, reason); + nm_modem_device_state_changed (priv->modem, new_state, old_state); /* Need to recheck available connections whenever MM appears or disappears, * since the device could be both DUN and NAP capable and thus may not @@ -541,17 +549,15 @@ data_port_changed_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data) } static gboolean -modem_stage1 (NMDeviceBt *self, NMModem *modem, NMDeviceStateReason *reason) +modem_stage1 (NMDeviceBt *self, NMModem *modem, NMDeviceStateReason *out_failure_reason) { NMActRequest *req; NMActStageReturn ret; - g_return_val_if_fail (reason != NULL, FALSE); - req = nm_device_get_act_request (NM_DEVICE (self)); - g_assert (req); + g_return_val_if_fail (req, FALSE); - ret = nm_modem_act_stage1_prepare (modem, req, reason); + ret = nm_modem_act_stage1_prepare (modem, req, out_failure_reason); switch (ret) { case NM_ACT_STAGE_RETURN_POSTPONE: case NM_ACT_STAGE_RETURN_SUCCESS: @@ -639,7 +645,7 @@ component_added (NMDevice *device, GObject *component) const gchar *modem_control_port; char *base; NMDeviceState state; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; + NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE; if (!NM_IS_MODEM (component)) return FALSE; @@ -694,8 +700,8 @@ component_added (NMDevice *device, GObject *component) g_signal_connect (modem, "notify::" NM_MODEM_DATA_PORT, G_CALLBACK (data_port_changed_cb), self); /* Kick off the modem connection */ - if (!modem_stage1 (self, modem, &reason)) - nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, reason); + if (!modem_stage1 (self, modem, &failure_reason)) + nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, failure_reason); return TRUE; } @@ -836,14 +842,15 @@ bt_connect_timeout (gpointer user_data) } static NMActStageReturn -act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) +act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMDeviceBt *self = NM_DEVICE_BT (device); NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); NMConnection *connection; connection = nm_device_get_applied_connection (device); - g_assert (connection); + g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); + priv->bt_type = get_connection_bt_type (connection); if (priv->bt_type == NM_BT_CAPABILITY_NONE) { // FIXME: set a reason code @@ -851,7 +858,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) } if (priv->bt_type == NM_BT_CAPABILITY_DUN && !priv->mm_running) { - *reason = NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE; + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE); return NM_ACT_STAGE_RETURN_FAILURE; } @@ -862,8 +869,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) priv->bt_type & (NM_BT_CAPABILITY_DUN | NM_BT_CAPABILITY_NAP), bluez_connect_cb, g_object_ref (device)); - if (priv->timeout_id) - g_source_remove (priv->timeout_id); + nm_clear_g_source (&priv->timeout_id); priv->timeout_id = g_timeout_add_seconds (30, bt_connect_timeout, device); return NM_ACT_STAGE_RETURN_POSTPONE; @@ -872,38 +878,34 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) static NMActStageReturn act_stage3_ip4_config_start (NMDevice *device, NMIP4Config **out_config, - NMDeviceStateReason *reason) + NMDeviceStateReason *out_failure_reason) { NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE ((NMDeviceBt *) device); - NMActStageReturn ret; if (priv->bt_type == NM_BT_CAPABILITY_DUN) { - ret = nm_modem_stage3_ip4_config_start (priv->modem, - device, - NM_DEVICE_CLASS (nm_device_bt_parent_class), - reason); - } else - ret = NM_DEVICE_CLASS (nm_device_bt_parent_class)->act_stage3_ip4_config_start (device, out_config, reason); + return nm_modem_stage3_ip4_config_start (priv->modem, + device, + NM_DEVICE_CLASS (nm_device_bt_parent_class), + out_failure_reason); + } - return ret; + return NM_DEVICE_CLASS (nm_device_bt_parent_class)->act_stage3_ip4_config_start (device, out_config, out_failure_reason); } static NMActStageReturn act_stage3_ip6_config_start (NMDevice *device, NMIP6Config **out_config, - NMDeviceStateReason *reason) + NMDeviceStateReason *out_failure_reason) { NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE ((NMDeviceBt *) device); - NMActStageReturn ret; if (priv->bt_type == NM_BT_CAPABILITY_DUN) { - ret = nm_modem_stage3_ip6_config_start (priv->modem, - nm_device_get_act_request (device), - reason); - } else - ret = NM_DEVICE_CLASS (nm_device_bt_parent_class)->act_stage3_ip6_config_start (device, out_config, reason); + return nm_modem_stage3_ip6_config_start (priv->modem, + nm_device_get_act_request (device), + out_failure_reason); + } - return ret; + return NM_DEVICE_CLASS (nm_device_bt_parent_class)->act_stage3_ip6_config_start (device, out_config, out_failure_reason); } static void @@ -923,8 +925,7 @@ deactivate (NMDevice *device) */ nm_modem_device_state_changed (priv->modem, NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_ACTIVATED, - NM_DEVICE_STATE_REASON_USER_REQUESTED); + NM_DEVICE_STATE_ACTIVATED); modem_cleanup (NM_DEVICE_BT (device)); } } @@ -1028,15 +1029,15 @@ set_property (GObject *object, guint prop_id, switch (prop_id) { case PROP_BT_NAME: - /* Construct only */ + /* construct-only */ priv->name = g_value_dup_string (value); break; case PROP_BT_CAPABILITIES: - /* Construct only */ + /* construct-only */ priv->capabilities = g_value_get_uint (value); break; case PROP_BT_DEVICE: - /* Construct only */ + /* construct-only */ priv->bt_device = g_value_dup_object (value); g_signal_connect (priv->bt_device, "removed", G_CALLBACK (bluez_device_removed), object); break; @@ -1174,6 +1175,7 @@ nm_device_bt_class_init (NMDeviceBtClass *klass) device_class->complete_connection = complete_connection; device_class->is_available = is_available; device_class->component_added = component_added; + device_class->get_configured_mtu = nm_modem_get_configured_mtu; device_class->state_changed = device_state_changed; @@ -1198,12 +1200,13 @@ nm_device_bt_class_init (NMDeviceBtClass *klass) g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); signals[PPP_STATS] = - g_signal_new ("ppp-stats", + g_signal_new (NM_DEVICE_BT_PPP_STATS, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE, 2, - G_TYPE_UINT, G_TYPE_UINT); + G_TYPE_UINT /*guint32 in_bytes*/, + G_TYPE_UINT /*guint32 out_bytes*/); nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), NMDBUS_TYPE_DEVICE_BLUETOOTH_SKELETON, diff --git a/src/devices/bluetooth/nm-device-bt.h b/src/devices/bluetooth/nm-device-bt.h index 43bd4257..9bcf6ca8 100644 --- a/src/devices/bluetooth/nm-device-bt.h +++ b/src/devices/bluetooth/nm-device-bt.h @@ -37,6 +37,8 @@ #define NM_DEVICE_BT_CAPABILITIES "bt-capabilities" #define NM_DEVICE_BT_DEVICE "bt-device" +#define NM_DEVICE_BT_PPP_STATS "ppp-stats" + typedef struct _NMDeviceBt NMDeviceBt; typedef struct _NMDeviceBtClass NMDeviceBtClass; diff --git a/src/devices/nm-arping-manager.c b/src/devices/nm-arping-manager.c index 7b765844..51f80e08 100644 --- a/src/devices/nm-arping-manager.c +++ b/src/devices/nm-arping-manager.c @@ -81,13 +81,14 @@ G_DEFINE_TYPE (NMArpingManager, nm_arping_manager, G_TYPE_OBJECT) #define _NMLOG(level, ...) \ G_STMT_START { \ char _sbuf[64]; \ + int _ifindex = (self) ? NM_ARPING_MANAGER_GET_PRIVATE (self)->ifindex : 0; \ \ nm_log ((level), _NMLOG_DOMAIN, \ + nm_platform_link_get_name (NM_PLATFORM_GET, _ifindex), \ + NULL, \ "%s%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ _NMLOG_PREFIX_NAME, \ - self ? nm_sprintf_buf (_sbuf, "[%p,%d]", \ - self, \ - NM_ARPING_MANAGER_GET_PRIVATE (self)->ifindex) : "" \ + self ? nm_sprintf_buf (_sbuf, "[%p,%d]", self, _ifindex) : "" \ _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ } G_STMT_END diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c index 34d34eb4..3325c948 100644 --- a/src/devices/nm-device-bond.c +++ b/src/devices/nm-device-bond.c @@ -101,7 +101,7 @@ complete_connection (NMDevice *device, { NMSettingBond *s_bond; - nm_utils_complete_generic (NM_PLATFORM_GET, + nm_utils_complete_generic (nm_device_get_platform (device), connection, NM_SETTING_BOND_SETTING_NAME, existing_connections, @@ -131,7 +131,7 @@ set_bond_attr (NMDevice *device, NMBondMode mode, const char *attr, const char * if (!_nm_setting_bond_option_supported (attr, mode)) return FALSE; - ret = nm_platform_sysctl_master_set_option (NM_PLATFORM_GET, ifindex, attr, value); + ret = nm_platform_sysctl_master_set_option (nm_device_get_platform (device), ifindex, attr, value); if (!ret) _LOGW (LOGD_PLATFORM, "failed to set bonding attribute '%s' to '%s'", attr, value); return ret; @@ -165,7 +165,7 @@ update_connection (NMDevice *device, NMConnection *connection) /* Read bond options from sysfs and update the Bond setting to match */ options = nm_setting_bond_get_valid_options (s_bond); while (options && *options) { - gs_free char *value = nm_platform_sysctl_master_get_option (NM_PLATFORM_GET, ifindex, *options); + gs_free char *value = nm_platform_sysctl_master_get_option (nm_device_get_platform (device), ifindex, *options); const char *defvalue = nm_setting_bond_get_option_default (s_bond, *options); char *p; @@ -328,7 +328,7 @@ apply_bonding_config (NMDevice *device) set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_PRIMARY, value ? value : ""); /* ARP targets: clear and initialize the list */ - contents = nm_platform_sysctl_master_get_option (NM_PLATFORM_GET, ifindex, + contents = nm_platform_sysctl_master_get_option (nm_device_get_platform (device), ifindex, NM_SETTING_BOND_OPTION_ARP_IP_TARGET); set_arp_targets (device, mode, contents, " \n", "-"); value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET); @@ -363,21 +363,19 @@ apply_bonding_config (NMDevice *device) } static NMActStageReturn -act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) +act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *out_failure_reason) { NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; gboolean no_firmware = FALSE; - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - ret = NM_DEVICE_CLASS (nm_device_bond_parent_class)->act_stage1_prepare (dev, reason); + ret = NM_DEVICE_CLASS (nm_device_bond_parent_class)->act_stage1_prepare (dev, out_failure_reason); if (ret != NM_ACT_STAGE_RETURN_SUCCESS) return ret; /* Interface must be down to set bond options */ nm_device_take_down (dev, TRUE); ret = apply_bonding_config (dev); - if (ret) + if (ret != NM_ACT_STAGE_RETURN_FAILURE) ret = nm_device_hw_addr_set_cloned (dev, nm_device_get_applied_connection (dev), FALSE); nm_device_bring_up (dev, TRUE, &no_firmware); @@ -393,12 +391,13 @@ enslave_slave (NMDevice *device, NMDeviceBond *self = NM_DEVICE_BOND (device); gboolean success = TRUE, no_firmware = FALSE; const char *slave_iface = nm_device_get_ip_iface (slave); + NMConnection *master_con; nm_device_master_check_slave_physical_port (device, slave, LOGD_BOND); if (configure) { nm_device_take_down (slave, TRUE); - success = nm_platform_link_enslave (NM_PLATFORM_GET, + success = nm_platform_link_enslave (nm_device_get_platform (device), nm_device_get_ip_ifindex (device), nm_device_get_ip_ifindex (slave)); nm_device_bring_up (slave, TRUE, &no_firmware); @@ -407,6 +406,25 @@ enslave_slave (NMDevice *device, return FALSE; _LOGI (LOGD_BOND, "enslaved bond slave %s", slave_iface); + + /* The active_slave option can be set only after the interface is enslaved */ + master_con = nm_device_get_applied_connection (device); + if (master_con) { + NMSettingBond *s_bond = nm_connection_get_setting_bond (master_con); + const char *active; + + if (s_bond) { + active = nm_setting_bond_get_option_by_name (s_bond, "active_slave"); + if (active && nm_streq0 (active, nm_device_get_iface (slave))) { + nm_platform_sysctl_master_set_option (nm_device_get_platform (device), + nm_device_get_ifindex (device), + "active_slave", + active); + _LOGD (LOGD_BOND, "setting slave %s as active one for master %s", + active, nm_device_get_iface (device)); + } + } + } } else _LOGI (LOGD_BOND, "bond slave %s was enslaved", slave_iface); @@ -428,7 +446,7 @@ release_slave (NMDevice *device, */ address = g_strdup (nm_device_get_hw_address (device)); - success = nm_platform_link_release (NM_PLATFORM_GET, + success = nm_platform_link_release (nm_device_get_platform (device), nm_device_get_ip_ifindex (device), nm_device_get_ip_ifindex (slave)); @@ -440,7 +458,7 @@ release_slave (NMDevice *device, nm_device_get_ip_iface (slave)); } - nm_platform_process_events (NM_PLATFORM_GET); + nm_platform_process_events (nm_device_get_platform (device)); if (nm_device_update_hw_address (device)) nm_device_hw_addr_set (device, address, "restore", FALSE); @@ -468,7 +486,7 @@ create_and_realize (NMDevice *device, g_assert (iface); - plerr = nm_platform_link_bond_add (NM_PLATFORM_GET, iface, out_plink); + plerr = nm_platform_link_bond_add (nm_device_get_platform (device), iface, out_plink); if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create bond interface '%s' for '%s': %s", @@ -480,6 +498,116 @@ create_and_realize (NMDevice *device, return TRUE; } +static gboolean +check_changed_options (NMSettingBond *s_a, NMSettingBond *s_b, GError **error) +{ + guint i, num; + const char *name = NULL, *value_a = NULL, *value_b = NULL; + + /* Check that options in @s_a have compatible changes in @s_b */ + + num = nm_setting_bond_get_num_options (s_a); + for (i = 0; i < num; i++) { + nm_setting_bond_get_option (s_a, i, &name, &value_a); + + /* We support changes to these */ + if (NM_IN_STRSET (name, + NM_SETTING_BOND_OPTION_ACTIVE_SLAVE, + NM_SETTING_BOND_OPTION_PRIMARY)) { + continue; + } + + /* Missing in @s_b, but has a default value in @s_a */ + value_b = nm_setting_bond_get_option_by_name (s_b, name); + if ( !value_b + && nm_streq0 (value_a, nm_setting_bond_get_option_default (s_a, name))) { + continue; + } + + /* Reject any other changes */ + if (!nm_streq0 (value_a, value_b)) { + g_set_error (error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + "Can't reapply '%s' bond option", + name); + return FALSE; + } + } + + return TRUE; +} + +static gboolean +can_reapply_change (NMDevice *device, + const char *setting_name, + NMSetting *s_old, + NMSetting *s_new, + GHashTable *diffs, + GError **error) +{ + NMDeviceClass *device_class; + NMSettingBond *s_bond_old, *s_bond_new; + + /* Only handle bond setting here, delegate other settings to parent class */ + if (nm_streq (setting_name, NM_SETTING_BOND_SETTING_NAME)) { + if (!nm_device_hash_check_invalid_keys (diffs, + NM_SETTING_BOND_SETTING_NAME, + error, + NM_SETTING_BOND_OPTIONS)) + return FALSE; + + s_bond_old = NM_SETTING_BOND (s_old); + s_bond_new = NM_SETTING_BOND (s_new); + + if ( !check_changed_options (s_bond_old, s_bond_new, error) + || !check_changed_options (s_bond_new, s_bond_old, error)) { + return FALSE; + } + + return TRUE; + } + + device_class = NM_DEVICE_CLASS (nm_device_bond_parent_class); + return device_class->can_reapply_change (device, + setting_name, + s_old, + s_new, + diffs, + error); +} + +static void +reapply_connection (NMDevice *device, NMConnection *con_old, NMConnection *con_new) +{ + NMDeviceBond *self = NM_DEVICE_BOND (device); + const char *value; + NMSettingBond *s_bond; + NMBondMode mode; + + NM_DEVICE_CLASS (nm_device_bond_parent_class)->reapply_connection (device, + con_old, + con_new); + + _LOGD (LOGD_BOND, "reapplying bond settings"); + s_bond = nm_connection_get_setting_bond (con_new); + g_return_if_fail (s_bond); + + value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MODE); + if (!value) + value = "balance-rr"; + + mode = _nm_setting_bond_mode_from_string (value); + g_return_if_fail (mode != NM_BOND_MODE_UNKNOWN); + + /* Primary */ + value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_PRIMARY); + set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_PRIMARY, value ? value : ""); + + /* Active slave */ + set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_ACTIVE_SLAVE); +} + /*****************************************************************************/ static void @@ -508,6 +636,8 @@ nm_device_bond_class_init (NMDeviceBondClass *klass) parent_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired; parent_class->enslave_slave = enslave_slave; parent_class->release_slave = release_slave; + parent_class->can_reapply_change = can_reapply_change; + parent_class->reapply_connection = reapply_connection; nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), NMDBUS_TYPE_DEVICE_BOND_SKELETON, diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c index 613d59cd..01c4eb22 100644 --- a/src/devices/nm-device-bridge.c +++ b/src/devices/nm-device-bridge.c @@ -107,7 +107,7 @@ complete_connection (NMDevice *device, { NMSettingBridge *s_bridge; - nm_utils_complete_generic (NM_PLATFORM_GET, + nm_utils_complete_generic (nm_device_get_platform (device), connection, NM_SETTING_BRIDGE_SETTING_NAME, existing_connections, @@ -197,9 +197,9 @@ commit_option (NMDevice *device, NMSetting *setting, const Option *option, gbool value = g_strdup_printf ("%u", uval); if (slave) - nm_platform_sysctl_slave_set_option (NM_PLATFORM_GET, ifindex, option->sysname, value); + nm_platform_sysctl_slave_set_option (nm_device_get_platform (device), ifindex, option->sysname, value); else - nm_platform_sysctl_master_set_option (NM_PLATFORM_GET, ifindex, option->sysname, value); + nm_platform_sysctl_master_set_option (nm_device_get_platform (device), ifindex, option->sysname, value); } static void @@ -243,7 +243,7 @@ update_connection (NMDevice *device, NMConnection *connection) } for (option = master_options; option->name; option++) { - gs_free char *str = nm_platform_sysctl_master_get_option (NM_PLATFORM_GET, ifindex, option->sysname); + gs_free char *str = nm_platform_sysctl_master_get_option (nm_device_get_platform (device), ifindex, option->sysname); int value; if (str) { @@ -282,7 +282,7 @@ master_update_slave_connection (NMDevice *device, } for (option = slave_options; option->name; option++) { - gs_free char *str = nm_platform_sysctl_slave_get_option (NM_PLATFORM_GET, ifindex_slave, option->sysname); + gs_free char *str = nm_platform_sysctl_slave_get_option (nm_device_get_platform (device), ifindex_slave, option->sysname); int value; if (str) { @@ -305,14 +305,14 @@ master_update_slave_connection (NMDevice *device, } static NMActStageReturn -act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) +act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMActStageReturn ret; NMConnection *connection = nm_device_get_applied_connection (device); - g_assert (connection); + g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); - ret = NM_DEVICE_CLASS (nm_device_bridge_parent_class)->act_stage1_prepare (device, reason); + ret = NM_DEVICE_CLASS (nm_device_bridge_parent_class)->act_stage1_prepare (device, out_failure_reason); if (ret != NM_ACT_STAGE_RETURN_SUCCESS) return ret; @@ -333,7 +333,7 @@ enslave_slave (NMDevice *device, NMDeviceBridge *self = NM_DEVICE_BRIDGE (device); if (configure) { - if (!nm_platform_link_enslave (NM_PLATFORM_GET, nm_device_get_ip_ifindex (device), nm_device_get_ip_ifindex (slave))) + if (!nm_platform_link_enslave (nm_device_get_platform (device), nm_device_get_ip_ifindex (device), nm_device_get_ip_ifindex (slave))) return FALSE; commit_slave_options (slave, nm_connection_get_setting_bridge_port (connection)); @@ -357,7 +357,7 @@ release_slave (NMDevice *device, gboolean success; if (configure) { - success = nm_platform_link_release (NM_PLATFORM_GET, + success = nm_platform_link_release (nm_device_get_platform (device), nm_device_get_ip_ifindex (device), nm_device_get_ip_ifindex (slave)); @@ -401,7 +401,7 @@ create_and_realize (NMDevice *device, } } - plerr = nm_platform_link_bridge_add (NM_PLATFORM_GET, + plerr = nm_platform_link_bridge_add (nm_device_get_platform (device), iface, hwaddr ? mac_address : NULL, hwaddr ? ETH_ALEN : 0, diff --git a/src/devices/nm-device-dummy.c b/src/devices/nm-device-dummy.c new file mode 100644 index 00000000..dce4f7bc --- /dev/null +++ b/src/devices/nm-device-dummy.c @@ -0,0 +1,205 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Copyright 2017 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include "nm-device-dummy.h" + +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> + +#include "nm-act-request.h" +#include "nm-device-private.h" +#include "nm-ip4-config.h" +#include "platform/nm-platform.h" +#include "nm-device-factory.h" +#include "nm-setting-dummy.h" +#include "nm-core-internal.h" + +#include "introspection/org.freedesktop.NetworkManager.Device.Dummy.h" + +#include "nm-device-logging.h" +_LOG_DECLARE_SELF(NMDeviceDummy); + +/*****************************************************************************/ + +struct _NMDeviceDummy { + NMDevice parent; +}; + +struct _NMDeviceDummyClass { + NMDeviceClass parent; +}; + +G_DEFINE_TYPE (NMDeviceDummy, nm_device_dummy, NM_TYPE_DEVICE) + +/*****************************************************************************/ + +static NMDeviceCapabilities +get_generic_capabilities (NMDevice *dev) +{ + return NM_DEVICE_CAP_IS_SOFTWARE; +} + +static gboolean +complete_connection (NMDevice *device, + NMConnection *connection, + const char *specific_object, + const GSList *existing_connections, + GError **error) +{ + NMSettingDummy *s_dummy; + + nm_utils_complete_generic (nm_device_get_platform (device), + connection, + NM_SETTING_DUMMY_SETTING_NAME, + existing_connections, + NULL, + _("Dummy connection"), + NULL, + TRUE); + + s_dummy = nm_connection_get_setting_dummy (connection); + if (!s_dummy) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, + "A 'dummy' setting is required."); + return FALSE; + } + + return TRUE; +} + +static void +update_connection (NMDevice *device, NMConnection *connection) +{ + NMSettingDummy *s_dummy = nm_connection_get_setting_dummy (connection); + + if (!s_dummy) { + s_dummy = (NMSettingDummy *) nm_setting_dummy_new (); + nm_connection_add_setting (connection, (NMSetting *) s_dummy); + } +} + +static gboolean +create_and_realize (NMDevice *device, + NMConnection *connection, + NMDevice *parent, + const NMPlatformLink **out_plink, + GError **error) +{ + const char *iface = nm_device_get_iface (device); + NMPlatformError plerr; + NMSettingDummy *s_dummy; + + s_dummy = nm_connection_get_setting_dummy (connection); + g_assert (s_dummy); + + plerr = nm_platform_link_dummy_add (nm_device_get_platform (device), iface, out_plink); + if (plerr != NM_PLATFORM_ERROR_SUCCESS) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, + "Failed to create dummy interface '%s' for '%s': %s", + iface, + nm_connection_get_id (connection), + nm_platform_error_to_string (plerr)); + return FALSE; + } + + return TRUE; +} + +static gboolean +check_connection_compatible (NMDevice *device, NMConnection *connection) +{ + NMSettingDummy *s_dummy; + + if (!NM_DEVICE_CLASS (nm_device_dummy_parent_class)->check_connection_compatible (device, connection)) + return FALSE; + + s_dummy = nm_connection_get_setting_dummy (connection); + if (!s_dummy) + return FALSE; + + return TRUE; +} + +static NMActStageReturn +act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) +{ + NMActStageReturn ret; + + ret = NM_DEVICE_CLASS (nm_device_dummy_parent_class)->act_stage1_prepare (device, out_failure_reason); + if (ret != NM_ACT_STAGE_RETURN_SUCCESS) + return ret; + + if (!nm_device_hw_addr_set_cloned (device, nm_device_get_applied_connection (device), FALSE)) + return NM_ACT_STAGE_RETURN_FAILURE; + + return NM_ACT_STAGE_RETURN_SUCCESS; +} + +/*****************************************************************************/ + +static void +nm_device_dummy_init (NMDeviceDummy *self) +{ +} + +static void +nm_device_dummy_class_init (NMDeviceDummyClass *klass) +{ + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); + + NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_DUMMY) + + device_class->connection_type = NM_SETTING_DUMMY_SETTING_NAME; + device_class->complete_connection = complete_connection; + device_class->check_connection_compatible = check_connection_compatible; + device_class->create_and_realize = create_and_realize; + device_class->get_generic_capabilities = get_generic_capabilities; + device_class->update_connection = update_connection; + device_class->act_stage1_prepare = act_stage1_prepare; + device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired; + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_DUMMY_SKELETON, + NULL); +} + + +/*****************************************************************************/ + +#define NM_TYPE_DUMMY_DEVICE_FACTORY (nm_dummy_device_factory_get_type ()) +#define NM_DUMMY_DEVICE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DUMMY_DEVICE_FACTORY, NMDummyDeviceFactory)) + +static NMDevice * +create_device (NMDeviceFactory *factory, + const char *iface, + const NMPlatformLink *plink, + NMConnection *connection, + gboolean *out_ignore) +{ + return (NMDevice *) g_object_new (NM_TYPE_DEVICE_DUMMY, + NM_DEVICE_IFACE, iface, + NM_DEVICE_TYPE_DESC, "Dummy", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_DUMMY, + NM_DEVICE_LINK_TYPE, NM_LINK_TYPE_DUMMY, + NULL); +} + +NM_DEVICE_FACTORY_DEFINE_INTERNAL (DUMMY, Dummy, dummy, + NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_DUMMY) + NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_DUMMY_SETTING_NAME), + factory_class->create_device = create_device; +); diff --git a/src/devices/nm-device-dummy.h b/src/devices/nm-device-dummy.h new file mode 100644 index 00000000..cc89a847 --- /dev/null +++ b/src/devices/nm-device-dummy.h @@ -0,0 +1,38 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2017 Red Hat, Inc. + */ + +#ifndef __NETWORKMANAGER_DEVICE_DUMMY_H__ +#define __NETWORKMANAGER_DEVICE_DUMMY_H__ + +#include "nm-device-generic.h" + +#define NM_TYPE_DEVICE_DUMMY (nm_device_dummy_get_type ()) +#define NM_DEVICE_DUMMY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_DUMMY, NMDeviceDummy)) +#define NM_DEVICE_DUMMY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_DUMMY, NMDeviceDummyClass)) +#define NM_IS_DEVICE_DUMMY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_DUMMY)) +#define NM_IS_DEVICE_DUMMY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_DUMMY)) +#define NM_DEVICE_DUMMY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_DUMMY, NMDeviceDummyClass)) + +typedef struct _NMDeviceDummy NMDeviceDummy; +typedef struct _NMDeviceDummyClass NMDeviceDummyClass; + +GType nm_device_dummy_get_type (void); + +#endif /* __NETWORKMANAGER_DEVICE_DUMMY_H__ */ diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c index 5df16df0..4c5aeb5e 100644 --- a/src/devices/nm-device-ethernet.c +++ b/src/devices/nm-device-ethernet.c @@ -29,7 +29,7 @@ #include <unistd.h> #include <errno.h> -#include <gudev/gudev.h> +#include <libudev.h> #include "nm-device-private.h" #include "nm-act-request.h" @@ -59,8 +59,6 @@ _LOG_DECLARE_SELF(NMDeviceEthernet); /*****************************************************************************/ -#define WIRED_SECRETS_TRIES "wired-secrets-tries" - #define PPPOE_RECONNECT_DELAY 7 #define PPPOE_ENCAP_OVERHEAD 8 /* 2 bytes for PPP, 6 for PPPoE */ @@ -71,7 +69,6 @@ typedef struct Supplicant { NMSupplicantInterface *iface; /* signal handler ids */ - gulong iface_error_id; gulong iface_state_id; /* Timeouts and idles */ @@ -158,8 +155,8 @@ static void _update_s390_subchannels (NMDeviceEthernet *self) { NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - gs_unref_object GUdevDevice *dev = NULL; - gs_unref_object GUdevDevice *parent = NULL; + struct udev_device *dev = NULL; + struct udev_device *parent = NULL; const char *parent_path, *item; int ifindex; GDir *dir; @@ -175,21 +172,20 @@ _update_s390_subchannels (NMDeviceEthernet *self) } ifindex = nm_device_get_ifindex ((NMDevice *) self); - dev = (GUdevDevice *) nm_g_object_ref (nm_platform_link_get_udev_device (NM_PLATFORM_GET, ifindex)); + dev = nm_platform_link_get_udev_device (nm_device_get_platform (NM_DEVICE (self)), ifindex); if (!dev) return; /* Try for the "ccwgroup" parent */ - parent = g_udev_device_get_parent_with_subsystem (dev, "ccwgroup", NULL); + parent = udev_device_get_parent_with_subsystem_devtype (dev, "ccwgroup", NULL); if (!parent) { /* FIXME: whatever 'lcs' devices' subsystem is here... */ - if (!parent) { - /* Not an s390 device */ - return; - } + + /* Not an s390 device */ + return; } - parent_path = g_udev_device_get_sysfs_path (parent); + parent_path = udev_device_get_syspath (parent); dir = g_dir_open (parent_path, 0, &error); if (!dir) { _LOGW (LOGD_DEVICE | LOGD_PLATFORM, "update-s390: failed to open directory '%s': %s", @@ -213,7 +209,7 @@ _update_s390_subchannels (NMDeviceEthernet *self) gs_free char *path = NULL, *value = NULL; path = g_strdup_printf ("%s/%s", parent_path, item); - value = nm_platform_sysctl_get (NM_PLATFORM_GET, NMP_SYSCTL_PATHID_ABSOLUTE (path)); + value = nm_platform_sysctl_get (nm_device_get_platform (NM_DEVICE (self)), NMP_SYSCTL_PATHID_ABSOLUTE (path)); if ( !strcmp (item, "portname") && !g_strcmp0 (value, "no portname required")) { @@ -259,16 +255,18 @@ _update_s390_subchannels (NMDeviceEthernet *self) } static void -clear_secrets_tries (NMDevice *device) +reset_8021x_autoconnect_retries (NMDevice *device) { NMActRequest *req; - NMConnection *connection; + NMSettingsConnection *connection; req = nm_device_get_act_request (device); - if (req) { - connection = nm_act_request_get_applied_connection (req); - /* Clear wired secrets tries on success, failure, or when deactivating */ - g_object_set_data (G_OBJECT (connection), WIRED_SECRETS_TRIES, NULL); + if ( req + && nm_device_get_applied_setting (device, NM_TYPE_SETTING_802_1X)) { + connection = nm_act_request_get_settings_connection (req); + g_return_if_fail (connection); + /* Reset autoconnect retries on success, failure, or when deactivating */ + nm_settings_connection_reset_autoconnect_retries (connection); } } @@ -281,10 +279,11 @@ device_state_changed (NMDevice *device, if (new_state > NM_DEVICE_STATE_ACTIVATED) wired_secrets_cancel (NM_DEVICE_ETHERNET (device)); - if ( new_state == NM_DEVICE_STATE_ACTIVATED - || new_state == NM_DEVICE_STATE_FAILED - || new_state == NM_DEVICE_STATE_DISCONNECTED) - clear_secrets_tries (device); + if (NM_IN_SET (new_state, + NM_DEVICE_STATE_ACTIVATED, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_DISCONNECTED)) + reset_8021x_autoconnect_retries (device); } static void @@ -305,7 +304,7 @@ get_generic_capabilities (NMDevice *device) int ifindex = nm_device_get_ifindex (device); if (ifindex > 0) { - if (nm_platform_link_supports_carrier_detect (NM_PLATFORM_GET, ifindex)) + if (nm_platform_link_supports_carrier_detect (nm_device_get_platform (device), ifindex)) return NM_DEVICE_CAP_CARRIER_DETECT; else { _LOGI (LOGD_PLATFORM, "driver '%s' does not support carrier detection.", @@ -423,22 +422,12 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) /* 802.1X */ static void -supplicant_interface_clear_handlers (NMDeviceEthernet *self) +supplicant_interface_release (NMDeviceEthernet *self) { NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); nm_clear_g_source (&priv->supplicant_timeout_id); nm_clear_g_source (&priv->supplicant.con_timeout_id); - nm_clear_g_signal_handler (priv->supplicant.iface, &priv->supplicant.iface_error_id); -} - -static void -supplicant_interface_release (NMDeviceEthernet *self) -{ - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - - supplicant_interface_clear_handlers (self); - nm_clear_g_signal_handler (priv->supplicant.iface, &priv->supplicant.iface_state_id); if (priv->supplicant.iface) { @@ -580,7 +569,7 @@ build_supplicant_config (NMDeviceEthernet *self, connection = nm_device_get_applied_connection (NM_DEVICE (self)); g_assert (connection); con_uuid = nm_connection_get_uuid (connection); - mtu = nm_platform_link_get_mtu (NM_PLATFORM_GET, + mtu = nm_platform_link_get_mtu (nm_device_get_platform (NM_DEVICE (self)), nm_device_get_ifindex (NM_DEVICE (self))); config = nm_supplicant_config_new (); @@ -595,9 +584,24 @@ build_supplicant_config (NMDeviceEthernet *self, } static void +supplicant_iface_assoc_cb (NMSupplicantInterface *iface, + GError *error, + gpointer user_data) +{ + NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data); + + if (error && !nm_utils_error_is_cancelled (error, TRUE)) { + supplicant_interface_release (self); + nm_device_queue_state (NM_DEVICE (self), + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED); + } +} + +static void supplicant_iface_state_cb (NMSupplicantInterface *iface, - guint32 new_state, - guint32 old_state, + int new_state_i, + int old_state_i, int disconnect_reason, gpointer user_data) { @@ -605,9 +609,10 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface, NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); NMDevice *device = NM_DEVICE (self); NMSupplicantConfig *config; - gboolean success = FALSE; NMDeviceState devstate; GError *error = NULL; + NMSupplicantInterfaceState new_state = new_state_i; + NMSupplicantInterfaceState old_state = old_state_i; if (new_state == old_state) return; @@ -622,30 +627,23 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface, case NM_SUPPLICANT_INTERFACE_STATE_READY: config = build_supplicant_config (self, &error); if (config) { - success = nm_supplicant_interface_set_config (priv->supplicant.iface, config, &error); + nm_supplicant_interface_assoc (priv->supplicant.iface, config, + supplicant_iface_assoc_cb, self); g_object_unref (config); - - if (!success) { - _LOGE (LOGD_DEVICE | LOGD_ETHER, - "Activation: (ethernet) couldn't send security configuration to the supplicant: %s", - error->message); - g_clear_error (&error); - } } else { _LOGE (LOGD_DEVICE | LOGD_ETHER, "Activation: (ethernet) couldn't build security configuration: %s", error->message); g_clear_error (&error); - } - if (!success) { nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED); } break; case NM_SUPPLICANT_INTERFACE_STATE_COMPLETED: - supplicant_interface_clear_handlers (self); + nm_clear_g_source (&priv->supplicant_timeout_id); + nm_clear_g_source (&priv->supplicant.con_timeout_id); /* If this is the initial association during device activation, * schedule the next activation stage. @@ -677,39 +675,26 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface, } } -static void -supplicant_iface_connection_error_cb (NMSupplicantInterface *iface, - const char *name, - const char *message, - gpointer user_data) -{ - NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data); - - _LOGW (LOGD_DEVICE | LOGD_ETHER, - "Activation: (ethernet) association request to the supplicant failed: %s - %s", - name, message); - - supplicant_interface_release (self); - nm_device_queue_state (NM_DEVICE (self), - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED); -} - static NMActStageReturn handle_auth_or_fail (NMDeviceEthernet *self, NMActRequest *req, gboolean new_secrets) { const char *setting_name; - guint32 tries; NMConnection *applied_connection; + NMSettingsConnection *settings_connection; + int tries_left; applied_connection = nm_act_request_get_applied_connection (req); + settings_connection = nm_act_request_get_settings_connection (req); - tries = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (applied_connection), WIRED_SECRETS_TRIES)); - if (tries > 3) + tries_left = nm_settings_connection_get_autoconnect_retries (settings_connection); + if (tries_left == 0) return NM_ACT_STAGE_RETURN_FAILURE; + if (tries_left > 0) + nm_settings_connection_set_autoconnect_retries (settings_connection, tries_left - 1); + nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE); nm_active_connection_clear_secrets (NM_ACTIVE_CONNECTION (req)); @@ -719,7 +704,6 @@ handle_auth_or_fail (NMDeviceEthernet *self, wired_secrets_get_secrets (self, setting_name, NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION | (new_secrets ? NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW : 0)); - g_object_set_data (G_OBJECT (applied_connection), WIRED_SECRETS_TRIES, GUINT_TO_POINTER (++tries)); } else _LOGI (LOGD_DEVICE, "Cleared secrets, but setting didn't need any secrets."); @@ -771,6 +755,7 @@ static gboolean supplicant_interface_init (NMDeviceEthernet *self) { NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + guint timeout; supplicant_interface_release (self); @@ -790,14 +775,11 @@ supplicant_interface_init (NMDeviceEthernet *self) G_CALLBACK (supplicant_iface_state_cb), self); - /* Hook up error signal handler to capture association errors */ - priv->supplicant.iface_error_id = g_signal_connect (priv->supplicant.iface, - NM_SUPPLICANT_INTERFACE_CONNECTION_ERROR, - G_CALLBACK (supplicant_iface_connection_error_cb), - self); - - /* Set up a timeout on the connection attempt to fail it after 25 seconds */ - priv->supplicant.con_timeout_id = g_timeout_add_seconds (25, supplicant_connection_timeout_cb, self); + /* Set up a timeout on the connection attempt */ + timeout = nm_device_get_supplicant_timeout (NM_DEVICE (self)); + priv->supplicant.con_timeout_id = g_timeout_add_seconds (timeout, + supplicant_connection_timeout_cb, + self); return TRUE; } @@ -846,7 +828,7 @@ link_negotiation_set (NMDevice *device) } } - if (!nm_platform_ethtool_get_link_settings (NM_PLATFORM_GET, nm_device_get_ifindex (device), + if (!nm_platform_ethtool_get_link_settings (nm_device_get_platform (device), nm_device_get_ifindex (device), &link_autoneg, &link_speed, &link_duplex)) { _LOGW (LOGD_DEVICE, "set-link: unable to retrieve link negotiation"); return; @@ -870,7 +852,7 @@ link_negotiation_set (NMDevice *device) duplex ? "" : "*"); } - if (!nm_platform_ethtool_set_link_settings (NM_PLATFORM_GET, + if (!nm_platform_ethtool_set_link_settings (nm_device_get_platform (device), nm_device_get_ifindex (device), autoneg, speed, @@ -893,15 +875,13 @@ pppoe_reconnect_delay (gpointer user_data) } static NMActStageReturn -act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) +act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *out_failure_reason) { NMDeviceEthernet *self = NM_DEVICE_ETHERNET (dev); NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); NMActStageReturn ret; - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - ret = NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->act_stage1_prepare (dev, reason); + ret = NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->act_stage1_prepare (dev, out_failure_reason); if (ret != NM_ACT_STAGE_RETURN_SUCCESS) return ret; @@ -935,7 +915,7 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) } static NMActStageReturn -nm_8021x_stage2_config (NMDeviceEthernet *self, NMDeviceStateReason *reason) +nm_8021x_stage2_config (NMDeviceEthernet *self, NMDeviceStateReason *out_failure_reason) { NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); NMConnection *connection; @@ -944,11 +924,12 @@ nm_8021x_stage2_config (NMDeviceEthernet *self, NMDeviceStateReason *reason) NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; connection = nm_device_get_applied_connection (NM_DEVICE (self)); - g_assert (connection); + g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); + security = nm_connection_get_setting_802_1x (connection); if (!security) { _LOGE (LOGD_DEVICE, "Invalid or missing 802.1X security"); - *reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED; + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_CONFIG_FAILED); return ret; } @@ -966,7 +947,7 @@ nm_8021x_stage2_config (NMDeviceEthernet *self, NMDeviceStateReason *reason) ret = handle_auth_or_fail (self, req, FALSE); if (ret != NM_ACT_STAGE_RETURN_POSTPONE) - *reason = NM_DEVICE_STATE_REASON_NO_SECRETS; + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_NO_SECRETS); } else { _LOGI (LOGD_DEVICE | LOGD_ETHER, "Activation: (ethernet) connection '%s' requires no security. No secrets needed.", @@ -975,7 +956,7 @@ nm_8021x_stage2_config (NMDeviceEthernet *self, NMDeviceStateReason *reason) if (supplicant_interface_init (self)) ret = NM_ACT_STAGE_RETURN_POSTPONE; else - *reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED; + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_CONFIG_FAILED); } return ret; @@ -1017,43 +998,42 @@ ppp_ip4_config (NMPPPManager *ppp_manager, } static NMActStageReturn -pppoe_stage3_ip4_config_start (NMDeviceEthernet *self, NMDeviceStateReason *reason) +pppoe_stage3_ip4_config_start (NMDeviceEthernet *self, NMDeviceStateReason *out_failure_reason) { NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); NMSettingPppoe *s_pppoe; NMActRequest *req; GError *err = NULL; - NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; req = nm_device_get_act_request (NM_DEVICE (self)); - g_assert (req); + g_return_val_if_fail (req, NM_ACT_STAGE_RETURN_FAILURE); s_pppoe = (NMSettingPppoe *) nm_device_get_applied_setting ((NMDevice *) self, NM_TYPE_SETTING_PPPOE); - g_assert (s_pppoe); + g_return_val_if_fail (s_pppoe, NM_ACT_STAGE_RETURN_FAILURE); priv->ppp_manager = nm_ppp_manager_create (nm_device_get_iface (NM_DEVICE (self)), &err); - if ( priv->ppp_manager - && nm_ppp_manager_start (priv->ppp_manager, req, - nm_setting_pppoe_get_username (s_pppoe), - 30, 0, &err)) { - g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_STATE_CHANGED, - G_CALLBACK (ppp_state_changed), - self); - g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_IP4_CONFIG, - G_CALLBACK (ppp_ip4_config), - self); - ret = NM_ACT_STAGE_RETURN_POSTPONE; - } else { + + if ( !priv->ppp_manager + || !nm_ppp_manager_start (priv->ppp_manager, req, + nm_setting_pppoe_get_username (s_pppoe), + 30, 0, &err)) { _LOGW (LOGD_DEVICE, "PPPoE failed to start: %s", err->message); g_error_free (err); g_clear_object (&priv->ppp_manager); - *reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED; + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_PPP_START_FAILED); + return NM_ACT_STAGE_RETURN_FAILURE; } - return ret; + g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_STATE_CHANGED, + G_CALLBACK (ppp_state_changed), + self); + g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_IP4_CONFIG, + G_CALLBACK (ppp_ip4_config), + self); + return NM_ACT_STAGE_RETURN_POSTPONE; } /*****************************************************************************/ @@ -1144,7 +1124,7 @@ dcb_state (NMDevice *device, gboolean timeout) g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_CONFIG); - carrier = nm_platform_link_is_connected (NM_PLATFORM_GET, nm_device_get_ifindex (device)); + carrier = nm_platform_link_is_connected (nm_device_get_platform (device), nm_device_get_ifindex (device)); _LOGD (LOGD_DCB, "dcb_state() wait %d carrier %d timeout %d", priv->dcb_wait, carrier, timeout); switch (priv->dcb_wait) { @@ -1262,13 +1242,13 @@ wake_on_lan_enable (NMDevice *device) } wol = NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE; found: - return nm_platform_ethtool_set_wake_on_lan (NM_PLATFORM_GET, nm_device_get_ifindex (device), wol, password); + return nm_platform_ethtool_set_wake_on_lan (nm_device_get_platform (device), nm_device_get_ifindex (device), wol, password); } /*****************************************************************************/ static NMActStageReturn -act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) +act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMDeviceEthernet *self = (NMDeviceEthernet *) device; NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); @@ -1277,11 +1257,9 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; NMSettingDcb *s_dcb; - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - s_con = NM_SETTING_CONNECTION (nm_device_get_applied_setting (device, NM_TYPE_SETTING_CONNECTION)); - g_assert (s_con); + g_return_val_if_fail (s_con, NM_ACT_STAGE_RETURN_FAILURE); nm_clear_g_source (&priv->dcb_timeout_id); nm_clear_g_signal_handler (device, &priv->dcb_carrier_id); @@ -1297,7 +1275,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) NM_TYPE_SETTING_802_1X); if (security) { /* FIXME: for now 802.1x is mutually exclusive with DCB */ - return nm_8021x_stage2_config (self, reason); + return nm_8021x_stage2_config (self, out_failure_reason); } } @@ -1307,9 +1285,9 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) s_dcb = (NMSettingDcb *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_DCB); if (s_dcb) { /* lldpad really really wants the carrier to be up */ - if (nm_platform_link_is_connected (NM_PLATFORM_GET, nm_device_get_ifindex (device))) { + if (nm_platform_link_is_connected (nm_device_get_platform (device), nm_device_get_ifindex (device))) { if (!dcb_enable (device)) { - *reason = NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED; + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED); return NM_ACT_STAGE_RETURN_FAILURE; } } else { @@ -1343,7 +1321,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) if (mxu) { _LOGD (LOGD_PPP, "set MTU to %u (PPP interface MRU %u, MTU %u)", mxu + PPPOE_ENCAP_OVERHEAD, mru, mtu); - nm_platform_link_set_mtu (NM_PLATFORM_GET, + nm_platform_link_set_mtu (nm_device_get_platform (device), nm_device_get_ifindex (device), mxu + PPPOE_ENCAP_OVERHEAD); } @@ -1356,21 +1334,19 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) static NMActStageReturn act_stage3_ip4_config_start (NMDevice *device, NMIP4Config **out_config, - NMDeviceStateReason *reason) + NMDeviceStateReason *out_failure_reason) { NMSettingConnection *s_con; const char *connection_type; - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - s_con = NM_SETTING_CONNECTION (nm_device_get_applied_setting (device, NM_TYPE_SETTING_CONNECTION)); - g_assert (s_con); + g_return_val_if_fail (s_con, NM_ACT_STAGE_RETURN_FAILURE); connection_type = nm_setting_connection_get_connection_type (s_con); if (!strcmp (connection_type, NM_SETTING_PPPOE_SETTING_NAME)) - return pppoe_stage3_ip4_config_start (NM_DEVICE_ETHERNET (device), reason); + return pppoe_stage3_ip4_config_start (NM_DEVICE_ETHERNET (device), out_failure_reason); - return NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->act_stage3_ip4_config_start (device, out_config, reason); + return NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->act_stage3_ip4_config_start (device, out_config, out_failure_reason); } static guint32 @@ -1392,7 +1368,7 @@ deactivate (NMDevice *device) GError *error = NULL; /* Clear wired secrets tries when deactivating */ - clear_secrets_tries (device); + reset_8021x_autoconnect_retries (device); nm_clear_g_source (&priv->pppoe_wait_id); @@ -1451,7 +1427,7 @@ complete_connection (NMDevice *device, /* Default to an ethernet-only connection, but if a PPPoE setting was given * then PPPoE should be our connection type. */ - nm_utils_complete_generic (NM_PLATFORM_GET, + nm_utils_complete_generic (nm_device_get_platform (device), connection, s_pppoe ? NM_SETTING_PPPOE_SETTING_NAME : NM_SETTING_WIRED_SETTING_NAME, existing_connections, @@ -1609,7 +1585,7 @@ get_link_speed (NMDevice *device) NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); guint32 speed; - if (!nm_platform_ethtool_get_link_settings (NM_PLATFORM_GET, nm_device_get_ifindex (device), NULL, &speed, NULL)) + if (!nm_platform_ethtool_get_link_settings (nm_device_get_platform (device), nm_device_get_ifindex (device), NULL, &speed, NULL)) return; if (priv->speed == speed) return; @@ -1647,6 +1623,53 @@ is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags) return !!nm_device_get_initial_hw_address (device); } +static gboolean +can_reapply_change (NMDevice *device, + const char *setting_name, + NMSetting *s_old, + NMSetting *s_new, + GHashTable *diffs, + GError **error) +{ + NMDeviceClass *device_class; + + /* Only handle wired setting here, delegate other settings to parent class */ + if (nm_streq (setting_name, NM_SETTING_WIRED_SETTING_NAME)) { + return nm_device_hash_check_invalid_keys (diffs, + NM_SETTING_WIRED_SETTING_NAME, + error, + NM_SETTING_WIRED_MTU, /* reapplied with IP config */ + NM_SETTING_WIRED_SPEED, + NM_SETTING_WIRED_DUPLEX, + NM_SETTING_WIRED_AUTO_NEGOTIATE, + NM_SETTING_WIRED_WAKE_ON_LAN, + NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD); + } + + device_class = NM_DEVICE_CLASS (nm_device_ethernet_parent_class); + return device_class->can_reapply_change (device, + setting_name, + s_old, + s_new, + diffs, + error); +} + +static void +reapply_connection (NMDevice *device, NMConnection *con_old, NMConnection *con_new) +{ + NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device); + + NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->reapply_connection (device, + con_old, + con_new); + + _LOGD (LOGD_DEVICE, "reapplying wired settings"); + + link_negotiation_set (device); + wake_on_lan_enable (device); +} + static void dispose (GObject *object) { @@ -1744,6 +1767,8 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass) parent_class->carrier_changed = carrier_changed; parent_class->link_changed = link_changed; parent_class->is_available = is_available; + parent_class->can_reapply_change = can_reapply_change; + parent_class->reapply_connection = reapply_connection; parent_class->state_changed = device_state_changed; diff --git a/src/devices/nm-device-factory.c b/src/devices/nm-device-factory.c index 0ce2cb48..f512b8b2 100644 --- a/src/devices/nm-device-factory.c +++ b/src/devices/nm-device-factory.c @@ -32,7 +32,8 @@ #include "nm-utils.h" #define PLUGIN_PREFIX "libnm-device-plugin-" -#define PLUGIN_PATH_TAG "NMManager-plugin-path" + +static NM_CACHED_QUARK_FCN ("NMManager-plugin-path", plugin_path_quark) /*****************************************************************************/ @@ -350,13 +351,13 @@ _add_factory (NMDeviceFactory *factory, if (found) { nm_log_warn (LOGD_PLATFORM, "Loading device plugin failed: multiple plugins " "for same type (using '%s' instead of '%s')", - (char *) g_object_get_data (G_OBJECT (found), PLUGIN_PATH_TAG), + (char *) g_object_get_qdata (G_OBJECT (found), plugin_path_quark ()), path); return FALSE; } } - g_object_set_data_full (G_OBJECT (factory), PLUGIN_PATH_TAG, g_strdup (path), g_free); + g_object_set_qdata_full (G_OBJECT (factory), plugin_path_quark (), g_strdup (path), g_free); for (i = 0; link_types && link_types[i] > NM_LINK_TYPE_UNKNOWN; i++) g_hash_table_insert (factories_by_link, GUINT_TO_POINTER (link_types[i]), g_object_ref (factory)); for (i = 0; setting_types && setting_types[i]; i++) @@ -402,6 +403,7 @@ nm_device_factory_manager_load_factories (NMDeviceFactoryManagerFactoryFunc call _ADD_INTERNAL (nm_bond_device_factory_get_type); _ADD_INTERNAL (nm_bridge_device_factory_get_type); + _ADD_INTERNAL (nm_dummy_device_factory_get_type); _ADD_INTERNAL (nm_ethernet_device_factory_get_type); _ADD_INTERNAL (nm_infiniband_device_factory_get_type); _ADD_INTERNAL (nm_ip_tunnel_device_factory_get_type); diff --git a/src/devices/nm-device-generic.c b/src/devices/nm-device-generic.c index 2f51c69d..f6a670b2 100644 --- a/src/devices/nm-device-generic.c +++ b/src/devices/nm-device-generic.c @@ -54,11 +54,11 @@ G_DEFINE_TYPE (NMDeviceGeneric, nm_device_generic, NM_TYPE_DEVICE) /*****************************************************************************/ static NMDeviceCapabilities -get_generic_capabilities (NMDevice *dev) +get_generic_capabilities (NMDevice *device) { - int ifindex = nm_device_get_ifindex (dev); + int ifindex = nm_device_get_ifindex (device); - if (ifindex > 0 && nm_platform_link_supports_carrier_detect (NM_PLATFORM_GET, ifindex)) + if (ifindex > 0 && nm_platform_link_supports_carrier_detect (nm_device_get_platform (device), ifindex)) return NM_DEVICE_CAP_CARRIER_DETECT; else return NM_DEVICE_CAP_NONE; @@ -84,7 +84,7 @@ realize_start_notify (NMDevice *device, const NMPlatformLink *plink) g_clear_pointer (&priv->type_description, g_free); ifindex = nm_device_get_ip_ifindex (NM_DEVICE (self)); if (ifindex > 0) - priv->type_description = g_strdup (nm_platform_link_get_type_name (NM_PLATFORM_GET, ifindex)); + priv->type_description = g_strdup (nm_platform_link_get_type_name (nm_device_get_platform (device), ifindex)); } static gboolean diff --git a/src/devices/nm-device-infiniband.c b/src/devices/nm-device-infiniband.c index 60f1aefa..f7875d09 100644 --- a/src/devices/nm-device-infiniband.c +++ b/src/devices/nm-device-infiniband.c @@ -75,7 +75,7 @@ get_generic_capabilities (NMDevice *device) } static NMActStageReturn -act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) +act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) { nm_auto_close int dirfd = -1; NMActStageReturn ret; @@ -84,34 +84,32 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) const char *transport_mode; gboolean ok, no_firmware = FALSE; - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - ret = NM_DEVICE_CLASS (nm_device_infiniband_parent_class)->act_stage1_prepare (dev, reason); + ret = NM_DEVICE_CLASS (nm_device_infiniband_parent_class)->act_stage1_prepare (device, out_failure_reason); if (ret != NM_ACT_STAGE_RETURN_SUCCESS) return ret; - s_infiniband = (NMSettingInfiniband *) nm_device_get_applied_setting (dev, NM_TYPE_SETTING_INFINIBAND); - g_assert (s_infiniband); + s_infiniband = (NMSettingInfiniband *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_INFINIBAND); + g_return_val_if_fail (s_infiniband, NM_ACT_STAGE_RETURN_FAILURE); transport_mode = nm_setting_infiniband_get_transport_mode (s_infiniband); - dirfd = nm_platform_sysctl_open_netdir (NM_PLATFORM_GET, nm_device_get_ifindex (dev), ifname_verified); + dirfd = nm_platform_sysctl_open_netdir (nm_device_get_platform (device), nm_device_get_ifindex (device), ifname_verified); if (dirfd < 0) { if (!strcmp (transport_mode, "datagram")) return NM_ACT_STAGE_RETURN_SUCCESS; else { - *reason = NM_DEVICE_STATE_REASON_INFINIBAND_MODE; + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_INFINIBAND_MODE); return NM_ACT_STAGE_RETURN_FAILURE; } } /* With some drivers the interface must be down to set transport mode */ - nm_device_take_down (dev, TRUE); - ok = nm_platform_sysctl_set (NM_PLATFORM_GET, NMP_SYSCTL_PATHID_NETDIR (dirfd, ifname_verified, "mode"), transport_mode); - nm_device_bring_up (dev, TRUE, &no_firmware); + nm_device_take_down (device, TRUE); + ok = nm_platform_sysctl_set (nm_device_get_platform (device), NMP_SYSCTL_PATHID_NETDIR (dirfd, ifname_verified, "mode"), transport_mode); + nm_device_bring_up (device, TRUE, &no_firmware); if (!ok) { - *reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED; + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_CONFIG_FAILED); return NM_ACT_STAGE_RETURN_FAILURE; } @@ -186,7 +184,7 @@ complete_connection (NMDevice *device, const char *setting_mac; const char *hw_address; - nm_utils_complete_generic (NM_PLATFORM_GET, + nm_utils_complete_generic (nm_device_get_platform (device), connection, NM_SETTING_INFINIBAND_SETTING_NAME, existing_connections, @@ -242,7 +240,7 @@ update_connection (NMDevice *device, NMConnection *connection) ifindex = nm_device_get_ifindex (device); if (ifindex > 0) { - if (!nm_platform_link_infiniband_get_properties (NM_PLATFORM_GET, ifindex, NULL, NULL, &transport_mode)) + if (!nm_platform_link_infiniband_get_properties (nm_device_get_platform (device), ifindex, NULL, NULL, &transport_mode)) transport_mode = "datagram"; } g_object_set (G_OBJECT (s_infiniband), NM_SETTING_INFINIBAND_TRANSPORT_MODE, transport_mode, NULL); @@ -291,7 +289,7 @@ create_and_realize (NMDevice *device, return FALSE; } - plerr = nm_platform_link_infiniband_add (NM_PLATFORM_GET, priv->parent_ifindex, priv->p_key, out_plink); + plerr = nm_platform_link_infiniband_add (nm_device_get_platform (device), priv->parent_ifindex, priv->p_key, out_plink); if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create InfiniBand P_Key interface '%s' for '%s': %s", @@ -321,7 +319,7 @@ unrealize (NMDevice *device, GError **error) return FALSE; } - plerr = nm_platform_link_infiniband_delete (NM_PLATFORM_GET, priv->parent_ifindex, priv->p_key); + plerr = nm_platform_link_infiniband_delete (nm_device_get_platform (device), priv->parent_ifindex, priv->p_key); if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to remove InfiniBand P_Key interface '%s': %s", diff --git a/src/devices/nm-device-ip-tunnel.c b/src/devices/nm-device-ip-tunnel.c index 58544377..53b7cf4e 100644 --- a/src/devices/nm-device-ip-tunnel.c +++ b/src/devices/nm-device-ip-tunnel.c @@ -124,8 +124,8 @@ update_properties_from_ifindex (NMDevice *device, int ifindex) NMDeviceIPTunnel *self = NM_DEVICE_IP_TUNNEL (device); NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (self); int parent_ifindex = 0; - in_addr_t local4, remote4; - struct in6_addr local6, remote6; + in_addr_t local4 = 0, remote4 = 0; + struct in6_addr local6 = { 0 }, remote6 = { 0 }; guint8 ttl = 0, tos = 0, encap_limit = 0; gboolean pmtud = FALSE; guint32 flow_label = 0; @@ -157,7 +157,7 @@ clear: if (priv->mode == NM_IP_TUNNEL_MODE_GRE) { const NMPlatformLnkGre *lnk; - lnk = nm_platform_link_get_lnk_gre (NM_PLATFORM_GET, ifindex, NULL); + lnk = nm_platform_link_get_lnk_gre (nm_device_get_platform (device), ifindex, NULL); if (!lnk) { _LOGW (LOGD_PLATFORM, "could not read %s properties", "gre"); goto clear; @@ -202,7 +202,7 @@ clear: } else if (priv->mode == NM_IP_TUNNEL_MODE_SIT) { const NMPlatformLnkSit *lnk; - lnk = nm_platform_link_get_lnk_sit (NM_PLATFORM_GET, ifindex, NULL); + lnk = nm_platform_link_get_lnk_sit (nm_device_get_platform (device), ifindex, NULL); if (!lnk) { _LOGW (LOGD_PLATFORM, "could not read %s properties", "sit"); goto clear; @@ -217,7 +217,7 @@ clear: } else if (priv->mode == NM_IP_TUNNEL_MODE_IPIP) { const NMPlatformLnkIpIp *lnk; - lnk = nm_platform_link_get_lnk_ipip (NM_PLATFORM_GET, ifindex, NULL); + lnk = nm_platform_link_get_lnk_ipip (nm_device_get_platform (device), ifindex, NULL); if (!lnk) { _LOGW (LOGD_PLATFORM, "could not read %s properties", "ipip"); goto clear; @@ -233,7 +233,7 @@ clear: || priv->mode == NM_IP_TUNNEL_MODE_IP6IP6) { const NMPlatformLnkIp6Tnl *lnk; - lnk = nm_platform_link_get_lnk_ip6tnl (NM_PLATFORM_GET, ifindex, NULL); + lnk = nm_platform_link_get_lnk_ip6tnl (nm_device_get_platform (device), ifindex, NULL); if (!lnk) { _LOGW (LOGD_PLATFORM, "could not read %s properties", "ip6tnl"); goto clear; @@ -332,7 +332,7 @@ complete_connection (NMDevice *device, { NMSettingIPTunnel *s_ip_tunnel; - nm_utils_complete_generic (NM_PLATFORM_GET, + nm_utils_complete_generic (nm_device_get_platform (device), connection, NM_SETTING_IP_TUNNEL_SETTING_NAME, existing_connections, @@ -641,7 +641,7 @@ create_and_realize (NMDevice *device, lnk_gre.output_flags = NM_GRE_KEY; } - plerr = nm_platform_link_gre_add (NM_PLATFORM_GET, iface, &lnk_gre, out_plink); + plerr = nm_platform_link_gre_add (nm_device_get_platform (device), iface, &lnk_gre, out_plink); if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create GRE interface '%s' for '%s': %s", @@ -667,7 +667,7 @@ create_and_realize (NMDevice *device, lnk_sit.tos = nm_setting_ip_tunnel_get_tos (s_ip_tunnel); lnk_sit.path_mtu_discovery = nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel); - plerr = nm_platform_link_sit_add (NM_PLATFORM_GET, iface, &lnk_sit, out_plink); + plerr = nm_platform_link_sit_add (nm_device_get_platform (device), iface, &lnk_sit, out_plink); if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create SIT interface '%s' for '%s': %s", @@ -693,7 +693,7 @@ create_and_realize (NMDevice *device, lnk_ipip.tos = nm_setting_ip_tunnel_get_tos (s_ip_tunnel); lnk_ipip.path_mtu_discovery = nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel); - plerr = nm_platform_link_ipip_add (NM_PLATFORM_GET, iface, &lnk_ipip, out_plink); + plerr = nm_platform_link_ipip_add (nm_device_get_platform (device), iface, &lnk_ipip, out_plink); if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create IPIP interface '%s' for '%s': %s", @@ -722,7 +722,7 @@ create_and_realize (NMDevice *device, lnk_ip6tnl.flow_label = nm_setting_ip_tunnel_get_flow_label (s_ip_tunnel); lnk_ip6tnl.proto = nm_setting_ip_tunnel_get_mode (s_ip_tunnel) == NM_IP_TUNNEL_MODE_IPIP6 ? IPPROTO_IPIP : IPPROTO_IPV6; - plerr = nm_platform_link_ip6tnl_add (NM_PLATFORM_GET, iface, &lnk_ip6tnl, out_plink); + plerr = nm_platform_link_ip6tnl_add (nm_device_get_platform (device), iface, &lnk_ip6tnl, out_plink); if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create IPIP interface '%s' for '%s': %s", @@ -784,6 +784,33 @@ unrealize_notify (NMDevice *device) update_properties_from_ifindex (device, 0); } +static gboolean +can_reapply_change (NMDevice *device, + const char *setting_name, + NMSetting *s_old, + NMSetting *s_new, + GHashTable *diffs, + GError **error) +{ + NMDeviceClass *device_class; + + /* Only handle ip-tunnel setting here, delegate other settings to parent class */ + if (nm_streq (setting_name, NM_SETTING_IP_TUNNEL_SETTING_NAME)) { + return nm_device_hash_check_invalid_keys (diffs, + NM_SETTING_IP_TUNNEL_SETTING_NAME, + error, + NM_SETTING_IP_TUNNEL_MTU); /* reapplied with IP config */ + } + + device_class = NM_DEVICE_CLASS (nm_device_ip_tunnel_parent_class); + return device_class->can_reapply_change (device, + setting_name, + s_old, + s_new, + diffs, + error); +} + /*****************************************************************************/ static void @@ -866,16 +893,32 @@ constructed (GObject *object) } static void +dispose (GObject *object) +{ + NMDeviceIPTunnel *self = NM_DEVICE_IP_TUNNEL (object); + NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (self); + + g_clear_pointer (&priv->local, g_free); + g_clear_pointer (&priv->remote, g_free); + g_clear_pointer (&priv->input_key, g_free); + g_clear_pointer (&priv->output_key, g_free); + + G_OBJECT_CLASS (nm_device_ip_tunnel_parent_class)->dispose (object); +} + +static void nm_device_ip_tunnel_class_init (NMDeviceIPTunnelClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); object_class->constructed = constructed; + object_class->dispose = dispose; object_class->get_property = get_property; object_class->set_property = set_property; device_class->link_changed = link_changed; + device_class->can_reapply_change = can_reapply_change; device_class->complete_connection = complete_connection; device_class->update_connection = update_connection; device_class->check_connection_compatible = check_connection_compatible; diff --git a/src/devices/nm-device-logging.h b/src/devices/nm-device-logging.h index b7ec58fd..419a4a51 100644 --- a/src/devices/nm-device-logging.h +++ b/src/devices/nm-device-logging.h @@ -24,7 +24,8 @@ #include "nm-device.h" #define _LOG_DECLARE_SELF(t) \ -_nm_unused inline static NMDevice * \ +_nm_unused \ +static inline NMDevice * \ _nm_device_log_self_to_device (t *self) \ { \ return (NMDevice *) self; \ @@ -33,7 +34,9 @@ _nm_device_log_self_to_device (t *self) \ #undef _NMLOG_ENABLED #define _NMLOG_ENABLED(level, domain) ( nm_logging_enabled ((level), (domain)) ) #define _NMLOG(level, domain, ...) \ - nm_log_obj ((level), (domain), (self), "device", \ + nm_log_obj ((level), (domain), \ + (self) ? nm_device_get_iface (_nm_device_log_self_to_device (self)) : NULL, \ + NULL, (self), "device", \ "(%s): " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ (self) ? (nm_device_get_iface (_nm_device_log_self_to_device (self)) ?: "(null)") : "(none)" \ _NM_UTILS_MACRO_REST(__VA_ARGS__)) diff --git a/src/devices/nm-device-macsec.c b/src/devices/nm-device-macsec.c index c511a0e7..8add3f6f 100644 --- a/src/devices/nm-device-macsec.c +++ b/src/devices/nm-device-macsec.c @@ -45,7 +45,6 @@ typedef struct Supplicant { NMSupplicantInterface *iface; /* signal handler ids */ - gulong iface_error_id; gulong iface_state_id; /* Timeouts and idles */ @@ -90,8 +89,6 @@ G_DEFINE_TYPE (NMDeviceMacsec, nm_device_macsec, NM_TYPE_DEVICE) /******************************************************************/ -#define MACSEC_SECRETS_TRIES "macsec-secrets-tries" - static void macsec_secrets_cancel (NMDeviceMacsec *self); /******************************************************************/ @@ -113,7 +110,7 @@ parent_state_changed (NMDevice *parent, NMDeviceMacsec *self = NM_DEVICE_MACSEC (user_data); /* We'll react to our own carrier state notifications. Ignore the parent's. */ - if (reason == NM_DEVICE_STATE_REASON_CARRIER) + if (nm_device_state_reason_check (reason) == NM_DEVICE_STATE_REASON_CARRIER) return; nm_device_set_unmanaged_by_flags (NM_DEVICE (self), NM_UNMANAGED_PARENT, !nm_device_get_managed (parent, FALSE), reason); @@ -176,7 +173,7 @@ update_properties (NMDevice *device) ifindex = nm_device_get_ifindex (device); g_return_if_fail (ifindex > 0); - props = nm_platform_link_get_lnk_macsec (NM_PLATFORM_GET, ifindex, &plink); + props = nm_platform_link_get_lnk_macsec (nm_device_get_platform (device), ifindex, &plink); if (!props) { _LOGW (LOGD_PLATFORM, "could not get macsec properties"); @@ -222,7 +219,7 @@ build_supplicant_config (NMDeviceMacsec *self, GError **error) connection = nm_device_get_applied_connection (NM_DEVICE (self)); g_assert (connection); con_uuid = nm_connection_get_uuid (connection); - mtu = nm_platform_link_get_mtu (NM_PLATFORM_GET, + mtu = nm_platform_link_get_mtu (nm_device_get_platform (NM_DEVICE (self)), nm_device_get_ifindex (NM_DEVICE (self))); config = nm_supplicant_config_new (); @@ -248,22 +245,12 @@ build_supplicant_config (NMDeviceMacsec *self, GError **error) } static void -supplicant_interface_clear_handlers (NMDeviceMacsec *self) +supplicant_interface_release (NMDeviceMacsec *self) { NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE (self); nm_clear_g_source (&priv->supplicant_timeout_id); nm_clear_g_source (&priv->supplicant.con_timeout_id); - nm_clear_g_signal_handler (priv->supplicant.iface, &priv->supplicant.iface_error_id); -} - -static void -supplicant_interface_release (NMDeviceMacsec *self) -{ - NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE (self); - - supplicant_interface_clear_handlers (self); - nm_clear_g_signal_handler (priv->supplicant.iface, &priv->supplicant.iface_state_id); if (priv->supplicant.iface) { @@ -273,21 +260,18 @@ supplicant_interface_release (NMDeviceMacsec *self) } static void -supplicant_iface_connection_error_cb (NMSupplicantInterface *iface, - const char *name, - const char *message, - gpointer user_data) +supplicant_iface_assoc_cb (NMSupplicantInterface *iface, + GError *error, + gpointer user_data) { NMDeviceMacsec *self = NM_DEVICE_MACSEC (user_data); - _LOGW (LOGD_DEVICE, - "Activation: association request to the supplicant failed: %s - %s", - name, message); - - supplicant_interface_release (self); - nm_device_queue_state (NM_DEVICE (self), - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED); + if (error && !nm_utils_error_is_cancelled (error, TRUE)) { + supplicant_interface_release (self); + nm_device_queue_state (NM_DEVICE (self), + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED); + } } static void @@ -412,8 +396,8 @@ time_out: static void supplicant_iface_state_cb (NMSupplicantInterface *iface, - guint32 new_state, - guint32 old_state, + int new_state_i, + int old_state_i, int disconnect_reason, gpointer user_data) { @@ -421,9 +405,10 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface, NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE (self); NMDevice *device = NM_DEVICE (self); NMSupplicantConfig *config; - gboolean success = FALSE; NMDeviceState devstate; GError *error = NULL; + NMSupplicantInterfaceState new_state = new_state_i; + NMSupplicantInterfaceState old_state = old_state_i; if (new_state == old_state) return; @@ -438,30 +423,23 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface, case NM_SUPPLICANT_INTERFACE_STATE_READY: config = build_supplicant_config (self, &error); if (config) { - success = nm_supplicant_interface_set_config (priv->supplicant.iface, config, &error); + nm_supplicant_interface_assoc (priv->supplicant.iface, config, + supplicant_iface_assoc_cb, self); g_object_unref (config); - - if (!success) { - _LOGE (LOGD_DEVICE, - "Activation: couldn't send security configuration to the supplicant: %s", - error->message); - g_clear_error (&error); - } } else { _LOGE (LOGD_DEVICE, "Activation: couldn't build security configuration: %s", error->message); g_clear_error (&error); - } - if (!success) { nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED); } break; case NM_SUPPLICANT_INTERFACE_STATE_COMPLETED: - supplicant_interface_clear_handlers (self); + nm_clear_g_source (&priv->supplicant_timeout_id); + nm_clear_g_source (&priv->supplicant.con_timeout_id); nm_device_bring_up (device, TRUE, NULL); /* If this is the initial association during device activation, @@ -500,15 +478,20 @@ handle_auth_or_fail (NMDeviceMacsec *self, gboolean new_secrets) { const char *setting_name; - guint32 tries; + int tries_left; NMConnection *applied_connection; + NMSettingsConnection *settings_connection; applied_connection = nm_act_request_get_applied_connection (req); + settings_connection = nm_act_request_get_settings_connection (req); - tries = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (applied_connection), MACSEC_SECRETS_TRIES)); - if (tries > 3) + tries_left = nm_settings_connection_get_autoconnect_retries (settings_connection); + if (tries_left == 0) return NM_ACT_STAGE_RETURN_FAILURE; + if (tries_left > 0) + nm_settings_connection_set_autoconnect_retries (settings_connection, tries_left - 1); + nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE); nm_active_connection_clear_secrets (NM_ACTIVE_CONNECTION (req)); @@ -518,7 +501,6 @@ handle_auth_or_fail (NMDeviceMacsec *self, macsec_secrets_get_secrets (self, setting_name, NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION | (new_secrets ? NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW : 0)); - g_object_set_data (G_OBJECT (applied_connection), MACSEC_SECRETS_TRIES, GUINT_TO_POINTER (++tries)); } else _LOGI (LOGD_DEVICE, "Cleared secrets, but setting didn't need any secrets."); @@ -571,6 +553,7 @@ supplicant_interface_init (NMDeviceMacsec *self) { NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE (self); NMDevice *parent; + guint timeout; parent = nm_device_parent_get_device (NM_DEVICE (self)); g_return_val_if_fail (parent, FALSE); @@ -593,20 +576,16 @@ supplicant_interface_init (NMDeviceMacsec *self) G_CALLBACK (supplicant_iface_state_cb), self); - /* Hook up error signal handler to capture association errors */ - priv->supplicant.iface_error_id = g_signal_connect (priv->supplicant.iface, - NM_SUPPLICANT_INTERFACE_CONNECTION_ERROR, - G_CALLBACK (supplicant_iface_connection_error_cb), - self); - - /* Set up a timeout on the connection attempt to fail it after 25 seconds */ - priv->supplicant.con_timeout_id = g_timeout_add_seconds (25, supplicant_connection_timeout_cb, self); - + /* Set up a timeout on the connection attempt */ + timeout = nm_device_get_supplicant_timeout (NM_DEVICE (self)); + priv->supplicant.con_timeout_id = g_timeout_add_seconds (timeout, + supplicant_connection_timeout_cb, + self); return TRUE; } static NMActStageReturn -act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) +act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMDeviceMacsec *self = NM_DEVICE_MACSEC (device); NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE (self); @@ -615,7 +594,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) const char *setting_name; connection = nm_device_get_applied_connection (NM_DEVICE (self)); - g_assert (connection); + g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); if (!priv->supplicant.mgr) priv->supplicant.mgr = g_object_ref (nm_supplicant_manager_get ()); @@ -631,7 +610,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) ret = handle_auth_or_fail (self, req, FALSE); if (ret != NM_ACT_STAGE_RETURN_POSTPONE) - *reason = NM_DEVICE_STATE_REASON_NO_SECRETS; + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_NO_SECRETS); } else { _LOGI (LOGD_DEVICE | LOGD_ETHER, "Activation: connection '%s' requires no security. No secrets needed.", @@ -640,7 +619,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) if (supplicant_interface_init (self)) ret = NM_ACT_STAGE_RETURN_POSTPONE; else - *reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED; + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_CONFIG_FAILED); } return ret; @@ -735,7 +714,7 @@ create_and_realize (NMDevice *device, parent_ifindex = nm_device_get_ifindex (parent); g_warn_if_fail (parent_ifindex > 0); - plerr = nm_platform_link_macsec_add (NM_PLATFORM_GET, iface, parent_ifindex, &lnk, out_plink); + plerr = nm_platform_link_macsec_add (nm_device_get_platform (device), iface, parent_ifindex, &lnk, out_plink); if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create macsec interface '%s' for '%s': %s", @@ -758,17 +737,19 @@ link_changed (NMDevice *device, update_properties (device); } + static void -clear_secrets_tries (NMDevice *device) +reset_autoconnect_retries (NMDevice *device) { NMActRequest *req; - NMConnection *connection; + NMSettingsConnection *connection; req = nm_device_get_act_request (device); if (req) { - connection = nm_act_request_get_applied_connection (req); - /* Clear macsec secrets tries on success, failure, or when deactivating */ - g_object_set_data (G_OBJECT (connection), MACSEC_SECRETS_TRIES, NULL); + connection = nm_act_request_get_settings_connection (req); + g_return_if_fail (connection); + /* Reset autoconnect retries on success, failure, or when deactivating */ + nm_settings_connection_reset_autoconnect_retries (connection); } } @@ -784,7 +765,7 @@ device_state_changed (NMDevice *device, if ( new_state == NM_DEVICE_STATE_ACTIVATED || new_state == NM_DEVICE_STATE_FAILED || new_state == NM_DEVICE_STATE_DISCONNECTED) - clear_secrets_tries (device); + reset_autoconnect_retries (device); } /******************************************************************/ diff --git a/src/devices/nm-device-macvlan.c b/src/devices/nm-device-macvlan.c index 94206716..cea2b984 100644 --- a/src/devices/nm-device-macvlan.c +++ b/src/devices/nm-device-macvlan.c @@ -131,7 +131,7 @@ parent_state_changed (NMDevice *parent, NMDeviceMacvlan *self = NM_DEVICE_MACVLAN (user_data); /* We'll react to our own carrier state notifications. Ignore the parent's. */ - if (reason == NM_DEVICE_STATE_REASON_CARRIER) + if (nm_device_state_reason_check (reason) == NM_DEVICE_STATE_REASON_CARRIER) return; nm_device_set_unmanaged_by_flags (NM_DEVICE (self), NM_UNMANAGED_PARENT, !nm_device_get_managed (parent, FALSE), reason); @@ -185,9 +185,9 @@ update_properties (NMDevice *device) const NMPlatformLink *plink; if (priv->props.tap) - props = nm_platform_link_get_lnk_macvtap (NM_PLATFORM_GET, nm_device_get_ifindex (device), &plink); + props = nm_platform_link_get_lnk_macvtap (nm_device_get_platform (device), nm_device_get_ifindex (device), &plink); else - props = nm_platform_link_get_lnk_macvlan (NM_PLATFORM_GET, nm_device_get_ifindex (device), &plink); + props = nm_platform_link_get_lnk_macvlan (nm_device_get_platform (device), nm_device_get_ifindex (device), &plink); if (!props) { _LOGW (LOGD_PLATFORM, "could not get %s properties", priv->props.tap ? "macvtap" : "macvlan"); @@ -251,7 +251,7 @@ create_and_realize (NMDevice *device, lnk.no_promisc = !nm_setting_macvlan_get_promiscuous (s_macvlan); lnk.tap = nm_setting_macvlan_get_tap (s_macvlan); - plerr = nm_platform_link_macvlan_add (NM_PLATFORM_GET, iface, parent_ifindex, &lnk, out_plink); + plerr = nm_platform_link_macvlan_add (nm_device_get_platform (device), iface, parent_ifindex, &lnk, out_plink); if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create %s interface '%s' for '%s': %s", @@ -399,7 +399,7 @@ complete_connection (NMDevice *device, { NMSettingMacvlan *s_macvlan; - nm_utils_complete_generic (NM_PLATFORM_GET, + nm_utils_complete_generic (nm_device_get_platform (device), connection, NM_SETTING_MACVLAN_SETTING_NAME, existing_connections, @@ -474,13 +474,11 @@ update_connection (NMDevice *device, NMConnection *connection) } static NMActStageReturn -act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) +act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *out_failure_reason) { NMActStageReturn ret; - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - ret = NM_DEVICE_CLASS (nm_device_macvlan_parent_class)->act_stage1_prepare (dev, reason); + ret = NM_DEVICE_CLASS (nm_device_macvlan_parent_class)->act_stage1_prepare (dev, out_failure_reason); if (ret != NM_ACT_STAGE_RETURN_SUCCESS) return ret; diff --git a/src/devices/nm-device-private.h b/src/devices/nm-device-private.h index 2023feb5..a4067f9c 100644 --- a/src/devices/nm-device-private.h +++ b/src/devices/nm-device-private.h @@ -134,4 +134,9 @@ guint32 nm_device_get_configured_mtu_for_wired (NMDevice *self, gboolean *out_is NM_DEVICE_CLASS (klass)->link_types = link_types; \ } +gboolean _nm_device_hash_check_invalid_keys (GHashTable *hash, const char *setting_name, + GError **error, const char **argv); +#define nm_device_hash_check_invalid_keys(hash, setting_name, error, ...) \ + _nm_device_hash_check_invalid_keys (hash, setting_name, error, ((const char *[]) { __VA_ARGS__, NULL })) + #endif /* NM_DEVICE_PRIVATE_H */ diff --git a/src/devices/nm-device-tun.c b/src/devices/nm-device-tun.c index a937ae2d..b4af4416 100644 --- a/src/devices/nm-device-tun.c +++ b/src/devices/nm-device-tun.c @@ -80,7 +80,7 @@ update_properties (NMDeviceTun *self) ifindex = nm_device_get_ifindex (NM_DEVICE (self)); if (ifindex > 0) { - if (!nm_platform_link_tun_get_properties (NM_PLATFORM_GET, ifindex, &props)) { + if (!nm_platform_link_tun_get_properties (nm_device_get_platform (NM_DEVICE (self)), ifindex, &props)) { _LOGD (LOGD_DEVICE, "tun-properties: cannot loading tun properties from platform for ifindex %d", ifindex); ifindex = 0; } else if (g_strcmp0 (priv->mode, props.mode) != 0) { @@ -138,7 +138,7 @@ complete_connection (NMDevice *device, { NMSettingTun *s_tun; - nm_utils_complete_generic (NM_PLATFORM_GET, + nm_utils_complete_generic (nm_device_get_platform (device), connection, NM_SETTING_TUN_SETTING_NAME, existing_connections, @@ -181,7 +181,7 @@ update_connection (NMDevice *device, NMConnection *connection) nm_connection_add_setting (connection, (NMSetting *) s_tun); } - if (!nm_platform_link_tun_get_properties (NM_PLATFORM_GET, nm_device_get_ifindex (device), &props)) { + if (!nm_platform_link_tun_get_properties (nm_device_get_platform (device), nm_device_get_ifindex (device), &props)) { _LOGW (LOGD_PLATFORM, "failed to get TUN interface info while updating connection."); return; } @@ -232,7 +232,7 @@ create_and_realize (NMDevice *device, user = _nm_utils_ascii_str_to_int64 (nm_setting_tun_get_owner (s_tun), 10, 0, G_MAXINT32, -1); group = _nm_utils_ascii_str_to_int64 (nm_setting_tun_get_group (s_tun), 10, 0, G_MAXINT32, -1); - plerr = nm_platform_link_tun_add (NM_PLATFORM_GET, iface, + plerr = nm_platform_link_tun_add (nm_device_get_platform (device), iface, nm_setting_tun_get_mode (s_tun) == NM_SETTING_TUN_MODE_TAP, user, group, nm_setting_tun_get_pi (s_tun), @@ -291,15 +291,13 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) } static NMActStageReturn -act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) +act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMDeviceTun *self = NM_DEVICE_TUN (device); NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self); NMActStageReturn ret; - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - ret = NM_DEVICE_CLASS (nm_device_tun_parent_class)->act_stage1_prepare (device, reason); + ret = NM_DEVICE_CLASS (nm_device_tun_parent_class)->act_stage1_prepare (device, out_failure_reason); if (ret != NM_ACT_STAGE_RETURN_SUCCESS) return ret; diff --git a/src/devices/nm-device-veth.c b/src/devices/nm-device-veth.c index 1971aeeb..11916c59 100644 --- a/src/devices/nm-device-veth.c +++ b/src/devices/nm-device-veth.c @@ -69,7 +69,7 @@ update_properties (NMDevice *device) ifindex = nm_device_get_ifindex (device); - if (!nm_platform_link_veth_get_properties (NM_PLATFORM_GET, ifindex, &peer_ifindex)) + if (!nm_platform_link_veth_get_properties (nm_device_get_platform (device), ifindex, &peer_ifindex)) peer_ifindex = 0; nm_device_parent_set_ifindex (device, peer_ifindex); diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c index 45d7cf67..06db6446 100644 --- a/src/devices/nm-device-vlan.c +++ b/src/devices/nm-device-vlan.c @@ -79,7 +79,7 @@ parent_state_changed (NMDevice *parent, NMDeviceVlan *self = NM_DEVICE_VLAN (user_data); /* We'll react to our own carrier state notifications. Ignore the parent's. */ - if (reason == NM_DEVICE_STATE_REASON_CARRIER) + if (nm_device_state_reason_check (reason) == NM_DEVICE_STATE_REASON_CARRIER) return; nm_device_set_unmanaged_by_flags (NM_DEVICE (self), NM_UNMANAGED_PARENT, !nm_device_get_managed (parent, FALSE), reason); @@ -90,13 +90,14 @@ parent_hwaddr_maybe_changed (NMDevice *parent, GParamSpec *pspec, gpointer user_data) { - NMDeviceVlan *self = NM_DEVICE_VLAN (user_data); + NMDevice *device = NM_DEVICE (user_data); + NMDeviceVlan *self = NM_DEVICE_VLAN (device); NMConnection *connection; const char *new_mac, *old_mac; NMSettingIPConfig *s_ip6; /* Never touch assumed devices */ - if (nm_device_uses_assumed_connection ((NMDevice *) self)) + if (nm_device_sys_iface_state_is_external_or_assume (device)) return; connection = nm_device_get_applied_connection ((NMDevice *) self); @@ -121,7 +122,7 @@ parent_hwaddr_maybe_changed (NMDevice *parent, */ s_ip6 = nm_connection_get_setting_ip6_config (connection); if (s_ip6) - nm_device_reactivate_ip6_config (NM_DEVICE (self), s_ip6, s_ip6); + nm_device_reactivate_ip6_config (NM_DEVICE (self), s_ip6, s_ip6, FALSE); } } @@ -185,7 +186,7 @@ update_properties (NMDevice *device) ifindex = nm_device_get_ifindex (device); if (ifindex > 0) - plnk = nm_platform_link_get_lnk_vlan (NM_PLATFORM_GET, ifindex, &plink); + plnk = nm_platform_link_get_lnk_vlan (nm_device_get_platform (device), ifindex, &plink); if ( plnk && plink->parent > 0) @@ -248,7 +249,7 @@ create_and_realize (NMDevice *device, vlan_id = nm_setting_vlan_get_id (s_vlan); - plerr = nm_platform_link_vlan_add (NM_PLATFORM_GET, + plerr = nm_platform_link_vlan_add (nm_device_get_platform (device), iface, parent_ifindex, vlan_id, @@ -424,7 +425,7 @@ complete_connection (NMDevice *device, { NMSettingVlan *s_vlan; - nm_utils_complete_generic (NM_PLATFORM_GET, + nm_utils_complete_generic (nm_device_get_platform (device), connection, NM_SETTING_VLAN_SETTING_NAME, existing_connections, @@ -471,7 +472,7 @@ update_connection (NMDevice *device, NMConnection *connection) nm_connection_add_setting (connection, (NMSetting *) s_vlan); } - polnk = nm_platform_link_get_lnk (NM_PLATFORM_GET, ifindex, NM_LINK_TYPE_VLAN, &plink); + polnk = nm_platform_link_get_lnk (nm_device_get_platform (device), ifindex, NM_LINK_TYPE_VLAN, &plink); if (polnk) vlan_id = polnk->lnk_vlan.id; @@ -522,15 +523,13 @@ update_connection (NMDevice *device, NMConnection *connection) } static NMActStageReturn -act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) +act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMDevice *parent_device; NMSettingVlan *s_vlan; NMActStageReturn ret; - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - ret = NM_DEVICE_CLASS (nm_device_vlan_parent_class)->act_stage1_prepare (device, reason); + ret = NM_DEVICE_CLASS (nm_device_vlan_parent_class)->act_stage1_prepare (device, out_failure_reason); if (ret != NM_ACT_STAGE_RETURN_SUCCESS) return ret; @@ -557,7 +556,7 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) &egress_map, &n_egress_map); - nm_platform_link_vlan_change (NM_PLATFORM_GET, + nm_platform_link_vlan_change (nm_device_get_platform (device), nm_device_get_ifindex (device), NM_VLAN_FLAGS_ALL, nm_setting_vlan_get_flags (s_vlan), @@ -585,7 +584,7 @@ get_configured_mtu (NMDevice *self, gboolean *out_is_user_config) /* Inherit the MTU from parent device, if any */ ifindex = nm_device_parent_get_ifindex (self); if (ifindex > 0) - mtu = nm_platform_link_get_mtu (NM_PLATFORM_GET, ifindex); + mtu = nm_platform_link_get_mtu (nm_device_get_platform (NM_DEVICE (self)), ifindex); return mtu ?: NM_DEVICE_DEFAULT_MTU_WIRED; } diff --git a/src/devices/nm-device-vxlan.c b/src/devices/nm-device-vxlan.c index b4508133..d0b88874 100644 --- a/src/devices/nm-device-vxlan.c +++ b/src/devices/nm-device-vxlan.c @@ -87,7 +87,7 @@ update_properties (NMDevice *device) GObject *object = G_OBJECT (device); const NMPlatformLnkVxlan *props; - props = nm_platform_link_get_lnk_vxlan (NM_PLATFORM_GET, nm_device_get_ifindex (device), NULL); + props = nm_platform_link_get_lnk_vxlan (nm_device_get_platform (device), nm_device_get_ifindex (device), NULL); if (!props) { _LOGW (LOGD_PLATFORM, "could not get vxlan properties"); return; @@ -217,7 +217,7 @@ create_and_realize (NMDevice *device, props.l2miss = nm_setting_vxlan_get_l2_miss (s_vxlan); props.l3miss = nm_setting_vxlan_get_l3_miss (s_vxlan); - plerr = nm_platform_link_vxlan_add (NM_PLATFORM_GET, iface, &props, out_plink); + plerr = nm_platform_link_vxlan_add (nm_device_get_platform (device), iface, &props, out_plink); if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create VXLAN interface '%s' for '%s': %s", @@ -361,7 +361,7 @@ complete_connection (NMDevice *device, { NMSettingVxlan *s_vxlan; - nm_utils_complete_generic (NM_PLATFORM_GET, + nm_utils_complete_generic (nm_device_get_platform (device), connection, NM_SETTING_VXLAN_SETTING_NAME, existing_connections, @@ -496,13 +496,11 @@ update_connection (NMDevice *device, NMConnection *connection) } static NMActStageReturn -act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) +act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMActStageReturn ret; - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - ret = NM_DEVICE_CLASS (nm_device_vxlan_parent_class)->act_stage1_prepare (device, reason); + ret = NM_DEVICE_CLASS (nm_device_vxlan_parent_class)->act_stage1_prepare (device, out_failure_reason); if (ret != NM_ACT_STAGE_RETURN_SUCCESS) return ret; diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 2a2d276d..da581a0d 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2005 - 2013 Red Hat, Inc. + * Copyright (C) 2005 - 2017 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ @@ -56,6 +56,7 @@ #include "settings/nm-settings-connection.h" #include "settings/nm-settings.h" #include "nm-auth-utils.h" +#include "nm-netns.h" #include "nm-dispatcher.h" #include "nm-config.h" #include "dns/nm-dns-manager.h" @@ -66,6 +67,8 @@ #include "nm-lldp-listener.h" #include "nm-audit-manager.h" #include "nm-arping-manager.h" +#include "nm-connectivity.h" +#include "nm-dbus-interface.h" #include "nm-device-logging.h" _LOG_DECLARE_SELF (NMDevice); @@ -130,6 +133,13 @@ typedef enum { HW_ADDR_TYPE_GENERATED, } HwAddrType; +typedef enum { + FIREWALL_STATE_UNMANAGED = 0, + FIREWALL_STATE_INITIALIZED, + FIREWALL_STATE_WAIT_STAGE_3, + FIREWALL_STATE_WAIT_IP_CONFIG, +} FirewallState; + /*****************************************************************************/ enum { @@ -189,6 +199,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDevice, PROP_REFRESH_RATE_MS, PROP_TX_BYTES, PROP_RX_BYTES, + PROP_CONNECTIVITY, ); typedef struct _NMDevicePrivate { @@ -206,6 +217,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 +262,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 +273,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,19 +302,25 @@ 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; + gulong config_changed_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 */ + 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; @@ -311,6 +330,7 @@ typedef struct _NMDevicePrivate { /* Proxy Configuration */ NMProxyConfig *proxy_config; NMPacrunnerManager *pacrunner_manager; + NMPacrunnerCallId *pacrunner_call_id; /* IP4 configuration info */ NMIP4Config * ip4_config; /* Combined config from VPN, settings, and device */ @@ -331,9 +351,8 @@ typedef struct _NMDevicePrivate { NMPlatformIP4Route v4; NMPlatformIP6Route v6; } default_route; - - bool v4_commit_first_time; - bool v6_commit_first_time; + bool v4_has_shadowed_routes; + const char *ip4_rp_filter; /* DHCPv4 tracking */ struct { @@ -342,6 +361,8 @@ typedef struct _NMDevicePrivate { NMDhcp4Config * config; guint restart_id; guint num_tries_left; + char * pac_url; + bool was_active; } dhcp4; struct { @@ -359,7 +380,8 @@ typedef struct _NMDevicePrivate { gulong dnsmasq_state_id; /* Firewall */ - bool fw_ready; + FirewallState fw_state:4; + NMFirewallManager *fw_mgr; NMFirewallManagerCallId fw_call; /* IPv4LL stuff */ @@ -411,12 +433,14 @@ typedef struct _NMDevicePrivate { guint restart_id; guint num_tries_left; guint needed_prefixes; + bool was_active; } dhcp6; gboolean needs_ip6_subnet; /* allow autoconnect feature */ - bool autoconnect; + bool autoconnect_intern:1; + bool autoconnect_user:1; /* master interface for bridge/bond/team slave */ NMDevice * master; @@ -432,7 +456,12 @@ typedef struct _NMDevicePrivate { NMSettings *settings; + NMNetns *netns; + NMLldpListener *lldp_listener; + NMConnectivityState connectivity_state; + guint concheck_periodic_id; + guint64 concheck_seq; guint check_delete_unrealized_id; @@ -451,29 +480,25 @@ G_DEFINE_ABSTRACT_TYPE (NMDevice, nm_device, NM_TYPE_EXPORTED_OBJECT) /*****************************************************************************/ -static void nm_device_set_proxy_config (NMDevice *self, GHashTable *options); +static void nm_device_set_proxy_config (NMDevice *self, const char *pac_url); static gboolean nm_device_set_ip4_config (NMDevice *self, NMIP4Config *config, guint32 default_route_metric, gboolean commit, - gboolean routes_full_sync, - NMDeviceStateReason *reason); + gboolean routes_full_sync); static gboolean ip4_config_merge_and_apply (NMDevice *self, NMIP4Config *config, - gboolean commit, - NMDeviceStateReason *out_reason); + gboolean commit); static gboolean nm_device_set_ip6_config (NMDevice *self, NMIP6Config *config, gboolean commit, - gboolean routes_full_sync, - NMDeviceStateReason *reason); + gboolean routes_full_sync); static gboolean ip6_config_merge_and_apply (NMDevice *self, - gboolean commit, - NMDeviceStateReason *out_reason); + 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); @@ -482,6 +507,9 @@ static NMActStageReturn linklocal6_start (NMDevice *self); static void _carrier_wait_check_queued_act_request (NMDevice *self); +static void nm_device_set_autoconnect_both (NMDevice *self, gboolean autoconnect); +static void nm_device_set_autoconnect_full (NMDevice *self, int autoconnect_intern, int autoconnect_user); + static const char *_activation_func_to_string (ActivationHandleFunc func); static void activation_source_handle_cb (NMDevice *self, int family); @@ -494,10 +522,12 @@ static gboolean queued_ip4_config_change (gpointer user_data); static gboolean queued_ip6_config_change (gpointer user_data); static void ip_check_ping_watch_cb (GPid pid, gint status, gpointer user_data); static gboolean ip_config_valid (NMDeviceState state); -static NMActStageReturn dhcp4_start (NMDevice *self, NMConnection *connection, NMDeviceStateReason *reason); -static gboolean dhcp6_start (NMDevice *self, gboolean wait_for_ll, NMDeviceStateReason *reason); +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); @@ -605,6 +635,81 @@ nm_device_get_settings (NMDevice *self) return NM_DEVICE_GET_PRIVATE (self)->settings; } +NMNetns * +nm_device_get_netns (NMDevice *self) +{ + return NM_DEVICE_GET_PRIVATE (self)->netns; +} + +NMPlatform * +nm_device_get_platform (NMDevice *self) +{ + return nm_netns_get_platform (nm_device_get_netns (self)); +} + +/*****************************************************************************/ + +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) { @@ -633,16 +738,48 @@ init_ip6_config_dns_priority (NMDevice *self, NMIP6Config *config) /*****************************************************************************/ +static gboolean +nm_device_ipv4_sysctl_set (NMDevice *self, const char *property, const char *value) +{ + NMPlatform *platform = nm_device_get_platform (self); + gs_free char *value_to_free = NULL; + const char *value_to_set; + + if (value) { + value_to_set = value; + } else { + /* Set to a default value when we've got a NULL @value. */ + value_to_free = nm_platform_sysctl_get (platform, + NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_ip4_property_path ("default", property))); + value_to_set = value_to_free; + } + + return nm_platform_sysctl_set (platform, + NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_ip4_property_path (nm_device_get_ip_iface (self), property)), + value_to_set); +} + +static guint32 +nm_device_ipv4_sysctl_get_uint32 (NMDevice *self, const char *property, guint32 fallback) +{ + return nm_platform_sysctl_get_int_checked (nm_device_get_platform (self), + NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_ip4_property_path (nm_device_get_ip_iface (self), property)), + 10, + 0, + G_MAXUINT32, + fallback); +} + gboolean nm_device_ipv6_sysctl_set (NMDevice *self, const char *property, const char *value) { - return nm_platform_sysctl_set (NM_PLATFORM_GET, NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_ip6_property_path (nm_device_get_ip_iface (self), property)), value); + return nm_platform_sysctl_set (nm_device_get_platform (self), NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_ip6_property_path (nm_device_get_ip_iface (self), property)), value); } static guint32 nm_device_ipv6_sysctl_get_uint32 (NMDevice *self, const char *property, guint32 fallback) { - return nm_platform_sysctl_get_int_checked (NM_PLATFORM_GET, + return nm_platform_sysctl_get_int_checked (nm_device_get_platform (self), NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_ip6_property_path (nm_device_get_ip_iface (self), property)), 10, 0, @@ -872,7 +1009,7 @@ nm_device_set_ip_iface (NMDevice *self, const char *iface) if (nm_streq0 (iface, priv->ip_iface)) { if (!iface) return FALSE; - ifindex = nm_platform_if_nametoindex (NM_PLATFORM_GET, iface); + ifindex = nm_platform_if_nametoindex (nm_device_get_platform (self), iface); if ( ifindex <= 0 || priv->ip_ifindex == ifindex) return FALSE; @@ -890,7 +1027,7 @@ nm_device_set_ip_iface (NMDevice *self, const char *iface) * with this name still exists and we resolve the ifindex * anew. */ - priv->ip_ifindex = nm_platform_if_nametoindex (NM_PLATFORM_GET, iface); + priv->ip_ifindex = nm_platform_if_nametoindex (nm_device_get_platform (self), iface); if (priv->ip_ifindex > 0) _LOGD (LOGD_DEVICE, "ip-ifname: set ifname '%s', ifindex %d", iface, priv->ip_ifindex); else @@ -902,11 +1039,11 @@ nm_device_set_ip_iface (NMDevice *self, const char *iface) } if (priv->ip_ifindex > 0) { - if (nm_platform_check_support_user_ipv6ll (NM_PLATFORM_GET)) - nm_platform_link_set_user_ipv6ll_enabled (NM_PLATFORM_GET, priv->ip_ifindex, TRUE); + if (nm_platform_check_support_user_ipv6ll (nm_device_get_platform (self))) + nm_platform_link_set_user_ipv6ll_enabled (nm_device_get_platform (self), priv->ip_ifindex, TRUE); - if (!nm_platform_link_is_up (NM_PLATFORM_GET, priv->ip_ifindex)) - nm_platform_link_set_up (NM_PLATFORM_GET, priv->ip_ifindex, NULL); + if (!nm_platform_link_is_up (nm_device_get_platform (self), priv->ip_ifindex)) + nm_platform_link_set_up (nm_device_get_platform (self), priv->ip_ifindex, NULL); } /* We don't care about any saved values from the old iface */ @@ -1108,7 +1245,7 @@ _stats_timeout_cb (gpointer user_data) _LOGT (LOGD_DEVICE, "stats: refresh %d", ifindex); if (ifindex > 0) - nm_platform_link_refresh (NM_PLATFORM_GET, ifindex); + nm_platform_link_refresh (nm_device_get_platform (self), ifindex); return G_SOURCE_CONTINUE; } @@ -1165,7 +1302,7 @@ _stats_set_refresh_rate (NMDevice *self, guint refresh_rate_ms) * we don't get the result right away. */ ifindex = nm_device_get_ip_ifindex (self); if (ifindex > 0) - nm_platform_link_refresh (NM_PLATFORM_GET, ifindex); + nm_platform_link_refresh (nm_device_get_platform (self), ifindex); priv->stats.timeout_id = g_timeout_add (refresh_rate_ms, _stats_timeout_cb, self); } @@ -1184,7 +1321,7 @@ get_ip_iface_identifier (NMDevice *self, NMUtilsIPv6IfaceId *out_iid) ifindex = nm_device_get_ip_ifindex (self); g_return_val_if_fail (ifindex > 0, FALSE); - pllink = nm_platform_link_get (NM_PLATFORM_GET, ifindex); + pllink = nm_platform_link_get (nm_device_get_platform (self), ifindex); if ( !pllink || NM_IN_SET (pllink->type, NM_LINK_TYPE_NONE, NM_LINK_TYPE_UNKNOWN)) return FALSE; @@ -1231,7 +1368,7 @@ nm_device_get_ip_iface_identifier (NMDevice *self, NMUtilsIPv6IfaceId *iid, gboo if (!ignore_token) { s_ip6 = (NMSettingIP6Config *) - nm_device_get_applied_setting (self, NM_TYPE_SETTING_IP6_CONFIG); + nm_device_get_applied_setting (self, NM_TYPE_SETTING_IP6_CONFIG); g_return_val_if_fail (s_ip6, FALSE); token = nm_setting_ip6_config_get_token (s_ip6); } @@ -1345,6 +1482,8 @@ nm_device_get_priority (NMDevice *self) return 450; case NM_DEVICE_TYPE_VXLAN: return 500; + case NM_DEVICE_TYPE_DUMMY: + return 550; case NM_DEVICE_TYPE_WIFI: return 600; case NM_DEVICE_TYPE_OLPC_MESH: @@ -1368,6 +1507,26 @@ nm_device_get_priority (NMDevice *self) } static guint32 +route_metric_with_penalty (NMDevice *self, guint32 metric) +{ +#if WITH_CONCHECK + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + const guint32 PENALTY = 20000; + + /* Beware: for IPv6, a metric of 0 effectively means 1024. + * Only pass a normalized IPv6 metric (nm_utils_ip6_route_metric_normalize). */ + + if ( priv->connectivity_state != NM_CONNECTIVITY_FULL + && nm_connectivity_check_enabled (nm_connectivity_get ())) { + if (metric >= G_MAXUINT32 - PENALTY) + return G_MAXUINT32; + return metric + PENALTY; + } +#endif + return metric; +} + +static guint32 _get_ipx_route_metric (NMDevice *self, gboolean is_v4) { @@ -1449,9 +1608,9 @@ _update_default_route (NMDevice *self, int addr_family, gboolean has, gboolean i *p_is_assumed = is_assumed; if (addr_family == AF_INET) - nm_default_route_manager_ip4_update_default_route (nm_default_route_manager_get (), self); + nm_default_route_manager_ip4_update_default_route (nm_netns_get_default_route_manager (priv->netns), self); else - nm_default_route_manager_ip6_update_default_route (nm_default_route_manager_get (), self); + nm_default_route_manager_ip6_update_default_route (nm_netns_get_default_route_manager (priv->netns), self); } const NMPlatformIP4Route * @@ -1529,7 +1688,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; } @@ -1590,33 +1749,174 @@ nm_device_get_physical_port_id (NMDevice *self) /*****************************************************************************/ +static void +update_connectivity_state (NMDevice *self, NMConnectivityState state) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + /* If the connectivity check is disabled, make an optimistic guess. */ + if (state == NM_CONNECTIVITY_UNKNOWN) { + if (priv->state == NM_DEVICE_STATE_ACTIVATED) { + if (priv->default_route.v4_has || priv->default_route.v6_has) + state = NM_CONNECTIVITY_FULL; + else + state = NM_CONNECTIVITY_LIMITED; + } else { + state = NM_CONNECTIVITY_NONE; + } + } + + if (priv->connectivity_state != state) { +#if WITH_CONCHECK + _LOGD (LOGD_CONCHECK, "state changed from %s to %s", + nm_connectivity_state_to_string (priv->connectivity_state), + nm_connectivity_state_to_string (state)); +#endif + priv->connectivity_state = state; + _notify (self, PROP_CONNECTIVITY); + + if (nm_device_get_state (self) == NM_DEVICE_STATE_ACTIVATED) { + if (!ip4_config_merge_and_apply (self, NULL, TRUE)) + _LOGW (LOGD_IP4, "Failed to update IPv4 default route metric"); + if (!ip6_config_merge_and_apply (self, TRUE)) + _LOGW (LOGD_IP6, "Failed to update IPv6 default route metric"); + } + } +} + +typedef struct { + NMDevice *self; + NMDeviceConnectivityCallback callback; + gpointer user_data; + guint64 seq; +} ConnectivityCheckData; + +static void +concheck_done (ConnectivityCheckData *data) +{ + NMDevice *self = data->self; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + /* The unsolicited connectivity checks don't hook a callback. */ + if (data->callback) + data->callback (data->self, priv->connectivity_state, data->user_data); + g_object_unref (data->self); + g_slice_free (ConnectivityCheckData, data); +} + +#if WITH_CONCHECK +static void +concheck_cb (GObject *source_object, GAsyncResult *result, gpointer user_data) +{ + ConnectivityCheckData *data = user_data; + NMDevice *self = data->self; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMConnectivity *connectivity = NM_CONNECTIVITY (source_object); + NMConnectivityState state; + GError *error = NULL; + + state = nm_connectivity_check_finish (connectivity, result, &error); + if (error) { + _LOGW (LOGD_DEVICE, "connectivity checking on '%s' failed: %s", + nm_device_get_iface (self), error->message); + g_error_free (error); + } + + if (data->seq == priv->concheck_seq) + update_connectivity_state (data->self, state); + concheck_done (data); +} +#endif /* WITH_CONCHECK */ + static gboolean -nm_device_uses_generated_assumed_connection (NMDevice *self) +no_concheck (gpointer user_data) { + ConnectivityCheckData *data = user_data; + + concheck_done (data); + return G_SOURCE_REMOVE; +} + +void +nm_device_check_connectivity (NMDevice *self, + NMDeviceConnectivityCallback callback, + gpointer user_data) +{ + ConnectivityCheckData *data; +#if WITH_CONCHECK NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMSettingsConnection *connection; +#endif - if ( priv->act_request - && nm_active_connection_get_assumed (NM_ACTIVE_CONNECTION (priv->act_request))) { - connection = nm_act_request_get_settings_connection (priv->act_request); - if ( connection - && nm_settings_connection_get_nm_generated_assumed (connection)) - return TRUE; + data = g_slice_new0 (ConnectivityCheckData); + data->self = g_object_ref (self); + data->callback = callback; + data->user_data = user_data; + +#if WITH_CONCHECK + if (priv->concheck_periodic_id) { + data->seq = ++priv->concheck_seq; + + /* Kick off a real connectivity check. */ + nm_connectivity_check_async (nm_connectivity_get (), + nm_device_get_iface (self), + concheck_cb, + data); + return; } - return FALSE; +#endif + + /* Fake one. */ + g_idle_add (no_concheck, data); } -gboolean -nm_device_uses_assumed_connection (NMDevice *self) +NMConnectivityState +nm_device_get_connectivity_state (NMDevice *self) +{ + g_return_val_if_fail (NM_IS_DEVICE (self), NM_CONNECTIVITY_UNKNOWN); + + return NM_DEVICE_GET_PRIVATE (self)->connectivity_state; +} + +#if WITH_CONCHECK +static void +concheck_periodic (NMConnectivity *connectivity, NMDevice *self) +{ + nm_device_check_connectivity (self, NULL, NULL); +} +#endif + +static void +concheck_periodic_update (NMDevice *self) { +#if WITH_CONCHECK NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + gboolean check_enable; - if ( priv->act_request - && nm_active_connection_get_assumed (NM_ACTIVE_CONNECTION (priv->act_request))) - return TRUE; - return FALSE; + check_enable = (priv->state == NM_DEVICE_STATE_ACTIVATED) + && (priv->default_route.v4_has || priv->default_route.v6_has); + + if (check_enable && !priv->concheck_periodic_id) { + /* We just gained a default route. Enable periodic checking. */ + priv->concheck_periodic_id = g_signal_connect (nm_connectivity_get (), + NM_CONNECTIVITY_PERIODIC_CHECK, + G_CALLBACK (concheck_periodic), self); + /* Also kick off a check right away. */ + nm_device_check_connectivity (self, NULL, NULL); + } else if (!check_enable && priv->concheck_periodic_id) { + /* The default route has gone off, and so has connectivity. */ + g_signal_handler_disconnect (nm_connectivity_get (), priv->concheck_periodic_id); + priv->concheck_periodic_id = 0; + update_connectivity_state (self, NM_CONNECTIVITY_NONE); + } +#else + /* update_connectivity_state() figures out how to lie about + * connectivity state if the actual state is not really known. */ + update_connectivity_state (self, NM_CONNECTIVITY_UNKNOWN); +#endif } +/*****************************************************************************/ + static SlaveInfo * find_slave_info (NMDevice *self, NMDevice *slave) { @@ -1722,7 +2022,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) @@ -1785,7 +2085,7 @@ is_unmanaged_external_down (NMDevice *self, gboolean consider_can) /* Manage externally-created software interfaces only when they are IFF_UP */ if ( priv->ifindex <= 0 || !priv->up - || !(priv->slaves || nm_platform_link_can_assume (NM_PLATFORM_GET, priv->ifindex))) + || !(priv->slaves || nm_platform_link_can_assume (nm_device_get_platform (self), priv->ifindex))) return NM_UNMAN_FLAG_OP_SET_UNMANAGED; return NM_UNMAN_FLAG_OP_SET_MANAGED; @@ -1857,7 +2157,7 @@ nm_device_update_dynamic_ip_setup (NMDevice *self) if (priv->lldp_listener && nm_lldp_listener_is_running (priv->lldp_listener)) { nm_lldp_listener_stop (priv->lldp_listener); - addr = nm_platform_link_get_address (NM_PLATFORM_GET, priv->ifindex, &addr_length); + addr = nm_platform_link_get_address (nm_device_get_platform (self), priv->ifindex, &addr_length); if (!nm_lldp_listener_start (priv->lldp_listener, nm_device_get_ifindex (self), &error)) { _LOGD (LOGD_DEVICE, "LLDP listener %p could not be restarted: %s", @@ -2029,7 +2329,7 @@ device_recheck_slave_status (NMDevice *self, const NMPlatformLink *plink) } else { _LOGW (LOGD_DEVICE, "enslaved to unknown device %d %s", plink->master, - nm_platform_link_get_name (NM_PLATFORM_GET, plink->master)); + nm_platform_link_get_name (nm_device_get_platform (self), plink->master)); } } } @@ -2120,13 +2420,13 @@ device_link_changed (NMDevice *self) priv->device_link_changed_id = 0; ifindex = nm_device_get_ifindex (self); - pllink = nm_platform_link_get (NM_PLATFORM_GET, ifindex); + pllink = nm_platform_link_get (nm_device_get_platform (self), ifindex); if (!pllink) return G_SOURCE_REMOVE; info = *pllink; - udi = nm_platform_link_get_udi (NM_PLATFORM_GET, info.ifindex); + udi = nm_platform_link_get_udi (nm_device_get_platform (self), info.ifindex); if (udi && g_strcmp0 (udi, priv->udi)) { /* Update UDI to what udev gives us */ g_free (priv->udi); @@ -2234,11 +2534,11 @@ device_link_changed (NMDevice *self) /* the link was down and just came up. That happens for example, while changing MTU. * We must restore IP configuration. */ if (priv->ip4_state == IP_DONE) { - if (!ip4_config_merge_and_apply (self, NULL, TRUE, NULL)) + if (!ip4_config_merge_and_apply (self, NULL, TRUE)) _LOGW (LOGD_IP4, "failed applying IP4 config after link comes up again"); } if (priv->ip6_state == IP_DONE) { - if (!ip6_config_merge_and_apply (self, TRUE, NULL)) + if (!ip6_config_merge_and_apply (self, TRUE)) _LOGW (LOGD_IP6, "failed applying IP6 config after link comes up again"); } } @@ -2274,7 +2574,7 @@ device_ip_link_changed (NMDevice *self) if (!priv->ip_ifindex) return G_SOURCE_REMOVE; - pllink = nm_platform_link_get (NM_PLATFORM_GET, priv->ip_ifindex); + pllink = nm_platform_link_get (nm_device_get_platform (self), priv->ip_ifindex); if (!pllink) return G_SOURCE_REMOVE; @@ -2316,6 +2616,45 @@ link_changed_cb (NMPlatform *platform, } static void +ip4_rp_filter_update (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + const char *ip4_rp_filter; + + if ( priv->v4_has_shadowed_routes + || priv->default_route.v4_has) { + if (nm_device_ipv4_sysctl_get_uint32 (self, "rp_filter", 0) != 1) { + /* Don't touch the rp_filter if it's not strict. */ + return; + } + /* Loose rp_filter */ + ip4_rp_filter = "2"; + } else { + /* Default rp_filter */ + ip4_rp_filter = NULL; + } + + if (ip4_rp_filter != priv->ip4_rp_filter) { + nm_device_ipv4_sysctl_set (self, "rp_filter", ip4_rp_filter); + priv->ip4_rp_filter = ip4_rp_filter; + } +} + +static void +ip4_routes_changed_changed_cb (NMRouteManager *route_manager, NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + int ifindex = nm_device_get_ip_ifindex (self); + + if (nm_device_sys_iface_state_is_external_or_assume (self)) + return; + + priv->v4_has_shadowed_routes = nm_route_manager_ip4_routes_shadowed (route_manager, + ifindex); + ip4_rp_filter_update (self); +} + +static void link_changed (NMDevice *self, const NMPlatformLink *pllink) { /* stub implementation of virtual function to allow subclasses to chain up. */ @@ -2368,6 +2707,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 * @@ -2383,6 +2724,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) { @@ -2406,7 +2748,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; } @@ -2434,7 +2776,7 @@ nm_device_create_and_realize (NMDevice *self, const NMPlatformLink *plink = NULL; /* Must be set before device is realized */ - priv->is_nm_owned = !nm_platform_link_get_by_ifname (NM_PLATFORM_GET, priv->iface); + priv->is_nm_owned = !nm_platform_link_get_by_ifname (nm_device_get_platform (self), priv->iface); _LOGD (LOGD_DEVICE, "create (is %snm-owned)", priv->is_nm_owned ? "" : "not "); @@ -2446,7 +2788,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)) { @@ -2465,7 +2807,7 @@ update_device_from_platform_link (NMDevice *self, const NMPlatformLink *plink) g_return_if_fail (plink != NULL); - udi = nm_platform_link_get_udi (NM_PLATFORM_GET, plink->ifindex); + udi = nm_platform_link_get_udi (nm_device_get_platform (self), plink->ifindex); if (udi && !g_strcmp0 (udi, priv->udi)) { g_free (priv->udi); priv->udi = g_strdup (udi); @@ -2492,17 +2834,41 @@ update_device_from_platform_link (NMDevice *self, const NMPlatformLink *plink) } static void -config_changed_update_ignore_carrier (NMConfig *config, - NMConfigData *config_data, - NMConfigChangeFlags changes, - NMConfigData *old_data, - NMDevice *self) +device_init_sriov_num_vfs (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + gs_free char *value = NULL; + int num_vfs; + + if ( priv->ifindex > 0 + && nm_device_has_capability (self, NM_DEVICE_CAP_SRIOV)) { + value = nm_config_data_get_device_config (NM_CONFIG_GET_DATA, + "sriov-num-vfs", + self, + NULL); + num_vfs = _nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXINT32, -1); + if (num_vfs >= 0) { + nm_platform_link_set_sriov_num_vfs (nm_device_get_platform (self), + priv->ifindex, num_vfs); + } + } +} + +static void +config_changed (NMConfig *config, + NMConfigData *config_data, + NMConfigChangeFlags changes, + NMConfigData *old_data, + NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); if ( priv->state <= NM_DEVICE_STATE_DISCONNECTED || priv->state > NM_DEVICE_STATE_ACTIVATED) priv->ignore_carrier = nm_config_data_get_ignore_carrier (config_data, self); + + if (NM_FLAGS_HAS (changes, NM_CONFIG_CHANGE_VALUES)) + device_init_sriov_num_vfs (self); } static void @@ -2511,7 +2877,7 @@ check_carrier (NMDevice *self) int ifindex = nm_device_get_ip_ifindex (self); if (!nm_device_has_capability (self, NM_DEVICE_CAP_NONSTANDARD_CARRIER)) - nm_device_set_carrier (self, nm_platform_link_is_connected (NM_PLATFORM_GET, ifindex)); + nm_device_set_carrier (self, nm_platform_link_is_connected (nm_device_get_platform (self), ifindex)); } static void @@ -2527,6 +2893,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 @@ -2535,7 +2902,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; @@ -2573,6 +2942,8 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink) _notify (self, PROP_MTU); } + nm_device_sys_iface_state_set (self, NM_DEVICE_SYS_IFACE_STATE_EXTERNAL); + if (plink) { g_return_if_fail (link_type_compatible (self, plink->type, NULL, NULL)); update_device_from_platform_link (self, plink); @@ -2580,21 +2951,21 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink) } if (priv->ifindex > 0) { - priv->physical_port_id = nm_platform_link_get_physical_port_id (NM_PLATFORM_GET, priv->ifindex); + priv->physical_port_id = nm_platform_link_get_physical_port_id (nm_device_get_platform (self), priv->ifindex); _notify (self, PROP_PHYSICAL_PORT_ID); - priv->dev_id = nm_platform_link_get_dev_id (NM_PLATFORM_GET, priv->ifindex); + priv->dev_id = nm_platform_link_get_dev_id (nm_device_get_platform (self), priv->ifindex); - if (nm_platform_link_is_software (NM_PLATFORM_GET, priv->ifindex)) + if (nm_platform_link_is_software (nm_device_get_platform (self), priv->ifindex)) capabilities |= NM_DEVICE_CAP_IS_SOFTWARE; - mtu = nm_platform_link_get_mtu (NM_PLATFORM_GET, priv->ifindex); + mtu = nm_platform_link_get_mtu (nm_device_get_platform (self), priv->ifindex); if (priv->mtu != mtu) { priv->mtu = mtu; _notify (self, PROP_MTU); } - nm_platform_link_get_driver_info (NM_PLATFORM_GET, + nm_platform_link_get_driver_info (nm_device_get_platform (self), priv->ifindex, NULL, &priv->driver_version, @@ -2604,8 +2975,11 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink) if (priv->firmware_version) _notify (self, PROP_FIRMWARE_VERSION); - if (nm_platform_check_support_user_ipv6ll (NM_PLATFORM_GET)) - priv->nm_ipv6ll = nm_platform_link_get_user_ipv6ll_enabled (NM_PLATFORM_GET, priv->ifindex); + if (nm_platform_check_support_user_ipv6ll (nm_device_get_platform (self))) + priv->nm_ipv6ll = nm_platform_link_get_user_ipv6ll_enabled (nm_device_get_platform (self), priv->ifindex); + + if (nm_platform_link_supports_sriov (nm_device_get_platform (self), priv->ifindex)) + capabilities |= NM_DEVICE_CAP_SRIOV; } if (klass->get_generic_capabilities) @@ -2629,10 +3003,10 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink) /* Note: initial hardware address must be read before calling get_ignore_carrier() */ config = nm_config_get (); priv->ignore_carrier = nm_config_data_get_ignore_carrier (nm_config_get_data (config), self); - if (!priv->ignore_carrier_id) { - priv->ignore_carrier_id = g_signal_connect (config, + if (!priv->config_changed_id) { + priv->config_changed_id = g_signal_connect (config, NM_CONFIG_SIGNAL_CONFIG_CHANGED, - G_CALLBACK (config_changed_update_ignore_carrier), + G_CALLBACK (config_changed), self); } @@ -2647,13 +3021,22 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink) priv->carrier = TRUE; } + device_init_sriov_num_vfs (self); + nm_assert (!priv->stats.timeout_id); real_rate = _stats_refresh_rate_real (priv->stats.refresh_rate_ms); if (real_rate) priv->stats.timeout_id = g_timeout_add (real_rate, _stats_timeout_cb, self); + nm_device_set_autoconnect_full (self, !!DEFAULT_AUTOCONNECT, TRUE); + 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, @@ -2787,7 +3170,7 @@ nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error) if (!NM_DEVICE_GET_CLASS (self)->unrealize (self, error)) return FALSE; } else if (ifindex > 0) { - nm_platform_link_delete (NM_PLATFORM_GET, ifindex); + nm_platform_link_delete (nm_device_get_platform (self), ifindex); } } @@ -2841,12 +3224,12 @@ nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error) priv->capabilities |= NM_DEVICE_GET_CLASS (self)->get_generic_capabilities (self); _notify (self, PROP_CAPABILITIES); - nm_clear_g_signal_handler (nm_config_get (), &priv->ignore_carrier_id); + nm_clear_g_signal_handler (nm_config_get (), &priv->config_changed_id); priv->real = FALSE; _notify (self, PROP_REAL); - nm_device_set_autoconnect (self, DEFAULT_AUTOCONNECT); + nm_device_set_autoconnect_both (self, FALSE); g_object_thaw_notify (G_OBJECT (self)); @@ -2939,7 +3322,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), @@ -2962,12 +3344,10 @@ slave_state_changed (NMDevice *slave, release = TRUE; } - /* Don't touch the device if its state changed externally. */ - if (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"); @@ -2983,32 +3363,36 @@ slave_state_changed (NMDevice *slave, * * If @self is capable of enslaving other devices (ie it's a bridge, bond, team, * etc) then this function adds @slave to the slave list for later enslavement. + * + * Returns: %TRUE if the slave was enslaved. %FALSE means, the slave was already + * enslaved and nothing was done. */ -static void +static gboolean nm_device_master_add_slave (NMDevice *self, NMDevice *slave, gboolean configure) { NMDevicePrivate *priv; NMDevicePrivate *slave_priv; SlaveInfo *info; + gboolean changed = FALSE; - g_return_if_fail (NM_IS_DEVICE (self)); - g_return_if_fail (NM_IS_DEVICE (slave)); - g_return_if_fail (NM_DEVICE_GET_CLASS (self)->enslave_slave != NULL); + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + g_return_val_if_fail (NM_IS_DEVICE (slave), FALSE); + g_return_val_if_fail (NM_DEVICE_GET_CLASS (self)->enslave_slave != NULL, FALSE); priv = NM_DEVICE_GET_PRIVATE (self); slave_priv = NM_DEVICE_GET_PRIVATE (slave); info = find_slave_info (self, slave); - _LOGt (LOGD_CORE, "master: add one slave %p/%s%s", slave, nm_device_get_iface (slave), + _LOGT (LOGD_CORE, "master: add one slave %p/%s%s", slave, nm_device_get_iface (slave), info ? " (already registered)" : ""); if (configure) - g_return_if_fail (nm_device_get_state (slave) >= NM_DEVICE_STATE_DISCONNECTED); + g_return_val_if_fail (nm_device_get_state (slave) >= NM_DEVICE_STATE_DISCONNECTED, FALSE); if (!info) { - g_return_if_fail (!slave_priv->master); - g_return_if_fail (!slave_priv->is_enslaved); + g_return_val_if_fail (!slave_priv->master, FALSE); + g_return_val_if_fail (!slave_priv->is_enslaved, FALSE); info = g_slice_new0 (SlaveInfo); info->slave = g_object_ref (slave); @@ -3028,13 +3412,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: @@ -3127,14 +3513,14 @@ nm_device_master_release_slaves (NMDevice *self) gboolean configure = TRUE; /* Don't release the slaves if this connection doesn't belong to NM. */ - if (nm_device_uses_generated_assumed_connection (self)) + if (nm_device_sys_iface_state_is_external (self)) return; reason = priv->state_reason; if (priv->state == NM_DEVICE_STATE_FAILED) reason = NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED; - if (!nm_platform_link_get (NM_PLATFORM_GET, priv->ifindex)) + if (!nm_platform_link_get (nm_device_get_platform (self), priv->ifindex)) configure = FALSE; while (priv->slaves) { @@ -3205,6 +3591,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) { @@ -3243,15 +3637,19 @@ nm_device_slave_notify_release (NMDevice *self, NMDeviceStateReason reason) if ( priv->state > NM_DEVICE_STATE_DISCONNECTED && priv->state <= NM_DEVICE_STATE_ACTIVATED) { - if (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 (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", @@ -3319,8 +3717,8 @@ nm_device_removed (NMDevice *self, gboolean unconfigure_ip_config) _update_default_route (self, AF_INET6, priv->default_route.v6_has, TRUE); _update_default_route (self, AF_INET, FALSE, TRUE); _update_default_route (self, AF_INET6, FALSE, TRUE); - nm_device_set_ip4_config (self, NULL, 0, FALSE, FALSE, NULL); - nm_device_set_ip6_config (self, NULL, FALSE, FALSE, NULL); + nm_device_set_ip4_config (self, NULL, 0, FALSE, FALSE); + nm_device_set_ip6_config (self, NULL, FALSE, FALSE); } static gboolean @@ -3398,25 +3796,50 @@ nm_device_set_enabled (NMDevice *self, gboolean enabled) gboolean nm_device_get_autoconnect (NMDevice *self) { + NMDevicePrivate *priv; + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); - return NM_DEVICE_GET_PRIVATE (self)->autoconnect; + priv = NM_DEVICE_GET_PRIVATE (self); + return priv->autoconnect_intern && priv->autoconnect_user; } -void -nm_device_set_autoconnect (NMDevice *self, gboolean autoconnect) +static void +nm_device_set_autoconnect_full (NMDevice *self, int autoconnect_intern, int autoconnect_user) { NMDevicePrivate *priv; + gboolean old_value; g_return_if_fail (NM_IS_DEVICE (self)); - autoconnect = !!autoconnect; - priv = NM_DEVICE_GET_PRIVATE (self); - if (priv->autoconnect != autoconnect) { - priv->autoconnect = autoconnect; + + old_value = nm_device_get_autoconnect (self); + if (autoconnect_intern != -1) + priv->autoconnect_intern = autoconnect_intern; + if (autoconnect_user != -1) + priv->autoconnect_user = autoconnect_user; + if (old_value != nm_device_get_autoconnect (self)) _notify (self, PROP_AUTOCONNECT); - } +} + +void +nm_device_set_autoconnect_intern (NMDevice *self, gboolean autoconnect) +{ + nm_device_set_autoconnect_full (self, !!autoconnect, -1); +} + +static void +nm_device_set_autoconnect_both (NMDevice *self, gboolean autoconnect) +{ + autoconnect = !!autoconnect; + nm_device_set_autoconnect_full (self, autoconnect, autoconnect); +} + +static gboolean +get_autoconnect_allowed (NMDevice *self) +{ + return TRUE; } static gboolean @@ -3441,10 +3864,12 @@ gboolean nm_device_autoconnect_allowed (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMDeviceClass *klass = NM_DEVICE_GET_CLASS (self); GValue instance = G_VALUE_INIT; GValue retval = G_VALUE_INIT; - if (!priv->autoconnect) + if ( !nm_device_get_autoconnect (self) + || !klass->get_autoconnect_allowed (self)) return FALSE; /* Unrealized devices can always autoconnect. */ @@ -3535,7 +3960,7 @@ device_has_config (NMDevice *self) return TRUE; /* Master-slave relationship is also a configuration */ - if (priv->slaves || nm_platform_link_get_master (NM_PLATFORM_GET, priv->ifindex) > 0) + if (priv->slaves || nm_platform_link_get_master (nm_device_get_platform (self), priv->ifindex) > 0) return TRUE; return FALSE; @@ -3598,7 +4023,7 @@ nm_device_generate_connection (NMDevice *self, NMDevice *master) NMSetting *s_con; NMSetting *s_ip4; NMSetting *s_ip6; - gs_free char *uuid = NULL; + char uuid[37]; const char *ip4_method, *ip6_method; GError *error = NULL; const NMPlatformLink *pllink; @@ -3615,10 +4040,9 @@ nm_device_generate_connection (NMDevice *self, NMDevice *master) connection = nm_simple_connection_new (); s_con = nm_setting_connection_new (); - uuid = nm_utils_uuid_generate (); g_object_set (s_con, - NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_UUID, nm_utils_uuid_generate_buf (uuid), NM_SETTING_CONNECTION_ID, ifname, NM_SETTING_CONNECTION_AUTOCONNECT, FALSE, NM_SETTING_CONNECTION_INTERFACE_NAME, ifname, @@ -3649,7 +4073,7 @@ nm_device_generate_connection (NMDevice *self, NMDevice *master) s_ip6 = nm_ip6_config_create_setting (priv->ip6_config); nm_connection_add_setting (connection, s_ip6); - pllink = nm_platform_link_get (NM_PLATFORM_GET, priv->ifindex); + pllink = nm_platform_link_get (nm_device_get_platform (self), priv->ifindex); if (pllink && pllink->inet6_token.id) { _LOGD (LOGD_IP6, "IPv6 tokenized identifier present"); g_object_set (s_ip6, @@ -3889,12 +4313,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); @@ -4101,7 +4527,7 @@ get_ip_config_may_fail (NMDevice *self, int family) g_assert_not_reached (); } - return nm_setting_ip_config_get_may_fail (s_ip); + return !s_ip || nm_setting_ip_config_get_may_fail (s_ip); } static void @@ -4133,7 +4559,7 @@ master_ready (NMDevice *self, /* If the master didn't change, add-slave only rechecks whether to assume a connection. */ nm_device_master_add_slave (master, self, - nm_active_connection_get_assumed (active) ? FALSE : TRUE); + !nm_device_sys_iface_state_is_external_or_assume (self)); } static void @@ -4185,7 +4611,7 @@ lldp_rx_enabled (NMDevice *self) } static NMActStageReturn -act_stage1_prepare (NMDevice *self, NMDeviceStateReason *reason) +act_stage1_prepare (NMDevice *self, NMDeviceStateReason *out_failure_reason) { return NM_ACT_STAGE_RETURN_SUCCESS; } @@ -4201,8 +4627,6 @@ activate_stage1_device_prepare (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - NMActiveConnection *active = NM_ACTIVE_CONNECTION (priv->act_request); _set_ip_state (self, AF_INET, IP_NONE); _set_ip_state (self, AF_INET6, IP_NONE); @@ -4214,15 +4638,17 @@ 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)) { - ret = NM_DEVICE_GET_CLASS (self)->act_stage1_prepare (self, &reason); + 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); if (ret == NM_ACT_STAGE_RETURN_POSTPONE) { return; } else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, failure_reason); return; } - g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); + g_return_if_fail (ret == NM_ACT_STAGE_RETURN_SUCCESS); } nm_device_activate_schedule_stage2_device_config (self); @@ -4249,12 +4675,48 @@ nm_device_activate_schedule_stage1_device_prepare (NMDevice *self) } static NMActStageReturn -act_stage2_config (NMDevice *self, NMDeviceStateReason *reason) +act_stage2_config (NMDevice *self, NMDeviceStateReason *out_failure_reason) { - /* Nothing to do */ return NM_ACT_STAGE_RETURN_SUCCESS; } +static void +lldp_init (NMDevice *self, gboolean restart) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (priv->ifindex > 0 && lldp_rx_enabled (self)) { + gs_free_error GError *error = NULL; + gconstpointer addr; + size_t addr_length; + + if (priv->lldp_listener) { + if (restart && nm_lldp_listener_is_running (priv->lldp_listener)) + nm_lldp_listener_stop (priv->lldp_listener); + } else { + priv->lldp_listener = nm_lldp_listener_new (); + g_signal_connect (priv->lldp_listener, + "notify::" NM_LLDP_LISTENER_NEIGHBORS, + G_CALLBACK (lldp_neighbors_changed), + self); + } + + if (!nm_lldp_listener_is_running (priv->lldp_listener)) { + addr = nm_platform_link_get_address (nm_device_get_platform (self), priv->ifindex, &addr_length); + + if (nm_lldp_listener_start (priv->lldp_listener, nm_device_get_ifindex (self), &error)) + _LOGD (LOGD_DEVICE, "LLDP listener %p started", priv->lldp_listener); + else { + _LOGD (LOGD_DEVICE, "LLDP listener %p could not be started: %s", + priv->lldp_listener, error->message); + } + } + } else { + if (priv->lldp_listener) + nm_lldp_listener_stop (priv->lldp_listener); + } +} + /* * activate_stage2_device_config * @@ -4267,15 +4729,15 @@ activate_stage2_device_config (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMActStageReturn ret; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; gboolean no_firmware = FALSE; - NMActiveConnection *active = NM_ACTIVE_CONNECTION (priv->act_request); GSList *iter; nm_device_state_changed (self, NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_REASON_NONE); /* Assumed connections were already set up outside NetworkManager */ - if (!nm_active_connection_get_assumed (active)) { + if (!nm_device_sys_iface_state_is_external_or_assume (self)) { + NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE; + if (!nm_device_bring_up (self, FALSE, &no_firmware)) { if (no_firmware) nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_FIRMWARE_MISSING); @@ -4284,11 +4746,11 @@ activate_stage2_device_config (NMDevice *self) return; } - ret = NM_DEVICE_GET_CLASS (self)->act_stage2_config (self, &reason); + ret = NM_DEVICE_GET_CLASS (self)->act_stage2_config (self, &failure_reason); if (ret == NM_ACT_STAGE_RETURN_POSTPONE) return; else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, failure_reason); return; } g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); @@ -4301,36 +4763,13 @@ activate_stage2_device_config (NMDevice *self) if (slave_state == NM_DEVICE_STATE_IP_CONFIG) nm_device_master_enslave_slave (self, info->slave, nm_device_get_applied_connection (info->slave)); - else if ( nm_device_uses_generated_assumed_connection (self) + else if ( priv->act_request + && nm_device_sys_iface_state_is_external (self) && slave_state <= NM_DEVICE_STATE_DISCONNECTED) nm_device_queue_recheck_assume (info->slave); } - if (lldp_rx_enabled (self) && priv->ifindex > 0) { - gs_free_error GError *error = NULL; - gconstpointer addr; - size_t addr_length; - - if (priv->lldp_listener) - nm_lldp_listener_stop (priv->lldp_listener); - else { - priv->lldp_listener = nm_lldp_listener_new (); - g_signal_connect (priv->lldp_listener, - "notify::" NM_LLDP_LISTENER_NEIGHBORS, - G_CALLBACK (lldp_neighbors_changed), - self); - } - - addr = nm_platform_link_get_address (NM_PLATFORM_GET, priv->ifindex, &addr_length); - - if (nm_lldp_listener_start (priv->lldp_listener, nm_device_get_ifindex (self), &error)) - _LOGD (LOGD_DEVICE, "LLDP listener %p started", priv->lldp_listener); - else { - _LOGD (LOGD_DEVICE, "LLDP listener %p could not be started: %s", - priv->lldp_listener, error->message); - } - } - + lldp_init (self, TRUE); nm_device_activate_schedule_stage3_ip_config_start (self); } @@ -4426,7 +4865,7 @@ check_ip_state (NMDevice *self, gboolean may_fail) && (priv->ip6_state == IP_FAIL || (ip6_ignore && priv->ip6_state == IP_DONE))) { /* Either both methods failed, or only one failed and the other is * disabled */ - if (nm_device_uses_assumed_connection (self)) { + if (nm_device_sys_iface_state_is_external_or_assume (self)) { /* We have assumed configuration, but couldn't redo it. No problem, * move to check state. */ _set_ip_state (self, AF_INET, IP_DONE); @@ -4610,7 +5049,7 @@ ipv4_dad_start (NMDevice *self, NMIP4Config **configs, ArpingCallback cb) } timeout = get_ipv4_dad_timeout (self); - hw_addr = nm_platform_link_get_address (NM_PLATFORM_GET, + hw_addr = nm_platform_link_get_address (nm_device_get_platform (self), nm_device_get_ip_ifindex (self), &hw_addr_len); @@ -4618,7 +5057,7 @@ ipv4_dad_start (NMDevice *self, NMIP4Config **configs, ArpingCallback cb) || !hw_addr || !hw_addr_len || !addr_found - || nm_device_uses_assumed_connection (self)) { + || nm_device_sys_iface_state_is_external_or_assume (self)) { /* DAD not needed, signal success */ cb (self, configs, TRUE); @@ -4759,7 +5198,7 @@ nm_device_handle_ipv4ll_event (sd_ipv4ll *ll, int event, void *data) nm_clear_g_source (&priv->ipv4ll_timeout); nm_device_activate_schedule_ip4_config_result (self, config); } else if (priv->ip4_state == IP_DONE) { - if (!ip4_config_merge_and_apply (self, config, TRUE, NULL)) { + if (!ip4_config_merge_and_apply (self, config, TRUE)) { _LOGE (LOGD_AUTOIP4, "failed to update IP4 config for autoip change."); nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_FAILED); } @@ -4793,7 +5232,7 @@ ipv4ll_timeout_cb (gpointer user_data) } static NMActStageReturn -ipv4ll_start (NMDevice *self, NMDeviceStateReason *reason) +ipv4ll_start (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); const struct ether_addr *addr; @@ -4805,55 +5244,51 @@ ipv4ll_start (NMDevice *self, NMDeviceStateReason *reason) r = sd_ipv4ll_new (&priv->ipv4ll); if (r < 0) { _LOGE (LOGD_AUTOIP4, "IPv4LL: new() failed with error %d", r); - goto fail; + return NM_ACT_STAGE_RETURN_FAILURE; } r = sd_ipv4ll_attach_event (priv->ipv4ll, NULL, 0); if (r < 0) { _LOGE (LOGD_AUTOIP4, "IPv4LL: attach_event() failed with error %d", r); - goto fail; + return NM_ACT_STAGE_RETURN_FAILURE; } ifindex = nm_device_get_ip_ifindex (self); - addr = nm_platform_link_get_address (NM_PLATFORM_GET, ifindex, &addr_len); + addr = nm_platform_link_get_address (nm_device_get_platform (self), ifindex, &addr_len); if (!addr || addr_len != ETH_ALEN) { _LOGE (LOGD_AUTOIP4, "IPv4LL: can't retrieve hardware address"); - goto fail; + return NM_ACT_STAGE_RETURN_FAILURE; } r = sd_ipv4ll_set_mac (priv->ipv4ll, addr); if (r < 0) { _LOGE (LOGD_AUTOIP4, "IPv4LL: set_mac() failed with error %d", r); - goto fail; + return NM_ACT_STAGE_RETURN_FAILURE; } r = sd_ipv4ll_set_ifindex (priv->ipv4ll, ifindex); if (r < 0) { _LOGE (LOGD_AUTOIP4, "IPv4LL: set_ifindex() failed with error %d", r); - goto fail; + return NM_ACT_STAGE_RETURN_FAILURE; } r = sd_ipv4ll_set_callback (priv->ipv4ll, nm_device_handle_ipv4ll_event, self); if (r < 0) { _LOGE (LOGD_AUTOIP4, "IPv4LL: set_callback() failed with error %d", r); - goto fail; + return NM_ACT_STAGE_RETURN_FAILURE; } r = sd_ipv4ll_start (priv->ipv4ll); if (r < 0) { _LOGE (LOGD_AUTOIP4, "IPv4LL: start() failed with error %d", r); - goto fail; + return NM_ACT_STAGE_RETURN_FAILURE; } _LOGI (LOGD_DEVICE | LOGD_AUTOIP4, "IPv4LL: started"); /* Start a timeout to bound the address attempt */ priv->ipv4ll_timeout = g_timeout_add_seconds (20, ipv4ll_timeout_cb, self); - return NM_ACT_STAGE_RETURN_POSTPONE; -fail: - *reason = NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED; - return NM_ACT_STAGE_RETURN_FAILURE; } /*****************************************************************************/ @@ -4866,9 +5301,9 @@ _device_get_default_route_from_platform (NMDevice *self, int addr_family, NMPlat GArray *routes; if (addr_family == AF_INET) - routes = nm_platform_ip4_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT); + routes = nm_platform_ip4_route_get_all (nm_device_get_platform (self), ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT); else - routes = nm_platform_ip6_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT); + routes = nm_platform_ip6_route_get_all (nm_device_get_platform (self), ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT); if (routes) { guint route_metric = G_MAXUINT32, m; @@ -4923,7 +5358,7 @@ ensure_con_ip4_config (NMDevice *self) nm_connection_get_setting_ip4_config (connection), nm_device_get_ip4_route_metric (self)); - if (nm_device_uses_assumed_connection (self)) { + if (nm_device_sys_iface_state_is_external_or_assume (self)) { /* For assumed connections ignore all addresses and routes. */ nm_ip4_config_reset_addresses (priv->con_ip4_config); nm_ip4_config_reset_routes (priv->con_ip4_config); @@ -4949,7 +5384,7 @@ ensure_con_ip6_config (NMDevice *self) nm_connection_get_setting_ip6_config (connection), nm_device_get_ip6_route_metric (self)); - if (nm_device_uses_assumed_connection (self)) { + if (nm_device_sys_iface_state_is_external_or_assume (self)) { /* For assumed connections ignore all addresses and routes. */ nm_ip6_config_reset_addresses (priv->con_ip6_config); nm_ip6_config_reset_routes (priv->con_ip6_config); @@ -4965,6 +5400,7 @@ dhcp4_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); nm_clear_g_source (&priv->dhcp4.restart_id); + g_clear_pointer (&priv->dhcp4.pac_url, g_free); if (priv->dhcp4.client) { /* Stop any ongoing DHCP transaction on this device */ @@ -4997,8 +5433,7 @@ _ip4_config_merge_default (gpointer value, gpointer user_data) static gboolean ip4_config_merge_and_apply (NMDevice *self, NMIP4Config *config, - gboolean commit, - NMDeviceStateReason *out_reason) + gboolean commit) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMConnection *connection; @@ -5091,7 +5526,7 @@ ip4_config_merge_and_apply (NMDevice *self, * but if the IP method is automatic we need to update the default route to * maintain connectivity. */ - if (nm_device_uses_generated_assumed_connection (self) && !auto_method) + if (nm_device_sys_iface_state_is_external (self) && !auto_method) goto END_ADD_DEFAULT_ROUTE; /* At this point, we treat assumed and non-assumed connections alike. @@ -5100,7 +5535,7 @@ ip4_config_merge_and_apply (NMDevice *self, */ connection_has_default_route - = nm_default_route_manager_ip4_connection_has_default_route (nm_default_route_manager_get (), + = nm_default_route_manager_ip4_connection_has_default_route (nm_netns_get_default_route_manager (priv->netns), connection, &connection_is_never_default); if ( !priv->v4_commit_first_time @@ -5136,7 +5571,7 @@ ip4_config_merge_and_apply (NMDevice *self, memset (&priv->default_route.v4, 0, sizeof (priv->default_route.v4)); priv->default_route.v4.rt_source = NM_IP_CONFIG_SOURCE_USER; priv->default_route.v4.gateway = gateway; - priv->default_route.v4.metric = default_route_metric; + priv->default_route.v4.metric = route_metric_with_penalty (self, default_route_metric); priv->default_route.v4.mss = nm_ip4_config_get_mss (composite); if (!has_direct_route) { @@ -5167,9 +5602,9 @@ END_ADD_DEFAULT_ROUTE: routes_full_sync = commit && priv->v4_commit_first_time - && !nm_device_uses_assumed_connection (self); + && !nm_device_sys_iface_state_is_external_or_assume (self); - success = nm_device_set_ip4_config (self, composite, default_route_metric, commit, routes_full_sync, out_reason); + success = nm_device_set_ip4_config (self, composite, default_route_metric, commit, routes_full_sync); g_object_unref (composite); if (commit) @@ -5180,23 +5615,17 @@ END_ADD_DEFAULT_ROUTE: static gboolean dhcp4_lease_change (NMDevice *self, NMIP4Config *config) { - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; + g_return_val_if_fail (config, FALSE); - g_return_val_if_fail (config != NULL, FALSE); - - if (!ip4_config_merge_and_apply (self, config, TRUE, &reason)) { + if (!ip4_config_merge_and_apply (self, config, TRUE)) { _LOGW (LOGD_DHCP4, "failed to update IPv4 config for DHCP change."); return FALSE; } - /* Notify dispatcher scripts of new DHCP4 config */ - nm_dispatcher_call (DISPATCHER_ACTION_DHCP4_CHANGE, - nm_device_get_settings_connection (self), - nm_device_get_applied_connection (self), - self, - NULL, - NULL, - NULL); + nm_dispatcher_call_device (NM_DISPATCHER_ACTION_DHCP4_CHANGE, + self, + NULL, + NULL, NULL, NULL); nm_device_remove_pending_action (self, NM_PENDING_ACTION_DHCP4, FALSE); @@ -5208,7 +5637,6 @@ dhcp4_restart_cb (gpointer user_data) { NMDevice *self = user_data; NMDevicePrivate *priv; - NMDeviceStateReason reason; NMConnection *connection; g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); @@ -5217,7 +5645,7 @@ dhcp4_restart_cb (gpointer user_data) priv->dhcp4.restart_id = 0; connection = nm_device_get_applied_connection (self); - if (dhcp4_start (self, connection, &reason) == NM_ACT_STAGE_RETURN_FAILURE) + if (dhcp4_start (self, connection) == NM_ACT_STAGE_RETURN_FAILURE) dhcp_schedule_restart (self, AF_INET, NULL); return FALSE; @@ -5243,19 +5671,11 @@ dhcp4_fail (NMDevice *self, gboolean timeout) return; } - /* Instead of letting an assumed connection fail (which means that the - * device will transition to the ACTIVATED state without IP configuration), - * retry DHCP again. - */ - if (nm_device_uses_assumed_connection (self)) { - dhcp_schedule_restart (self, AF_INET, "connection is assumed"); - return; - } - if ( priv->dhcp4.num_tries_left == DHCP_NUM_TRIES_MAX - && (timeout || (priv->ip4_state == IP_CONF))) + && (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) { + else if (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. */ @@ -5305,7 +5725,9 @@ dhcp4_state_changed (NMDhcpClient *client, break; } - nm_device_set_proxy_config (self, options); + 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); nm_dhcp4_config_set_options (priv->dhcp4.config, options); _notify (self, PROP_DHCP4_CONFIG); @@ -5373,8 +5795,7 @@ dhcp4_get_timeout (NMDevice *self, NMSettingIP4Config *s_ip4) static NMActStageReturn dhcp4_start (NMDevice *self, - NMConnection *connection, - NMDeviceStateReason *reason) + NMConnection *connection) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMSettingIPConfig *s_ip4; @@ -5388,7 +5809,7 @@ dhcp4_start (NMDevice *self, nm_exported_object_clear_and_unexport (&priv->dhcp4.config); priv->dhcp4.config = nm_dhcp4_config_new (); - hw_addr = nm_platform_link_get_address (NM_PLATFORM_GET, nm_device_get_ip_ifindex (self), &hw_addr_len); + hw_addr = nm_platform_link_get_address (nm_device_get_platform (self), nm_device_get_ip_ifindex (self), &hw_addr_len); if (hw_addr_len) { tmp = g_byte_array_sized_new (hw_addr_len); g_byte_array_append (tmp, hw_addr, hw_addr_len); @@ -5413,10 +5834,8 @@ dhcp4_start (NMDevice *self, if (tmp) g_byte_array_free (tmp, TRUE); - if (!priv->dhcp4.client) { - *reason = NM_DEVICE_STATE_REASON_DHCP_START_FAILED; + if (!priv->dhcp4.client) return NM_ACT_STAGE_RETURN_FAILURE; - } priv->dhcp4.state_sigid = g_signal_connect (priv->dhcp4.client, NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED, @@ -5425,6 +5844,9 @@ dhcp4_start (NMDevice *self, nm_device_add_pending_action (self, NM_PENDING_ACTION_DHCP4, TRUE); + if (nm_device_sys_iface_state_is_external_or_assume (self)) + priv->dhcp4.was_active = TRUE; + /* DHCP devices will be notified by the DHCP manager when stuff happens */ return NM_ACT_STAGE_RETURN_POSTPONE; } @@ -5433,8 +5855,6 @@ gboolean nm_device_dhcp4_renew (NMDevice *self, gboolean release) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMActStageReturn ret; - NMDeviceStateReason reason; NMConnection *connection; g_return_val_if_fail (priv->dhcp4.client != NULL, FALSE); @@ -5445,12 +5865,10 @@ nm_device_dhcp4_renew (NMDevice *self, gboolean release) dhcp4_cleanup (self, CLEANUP_TYPE_DECONFIGURE, release); connection = nm_device_get_applied_connection (self); - g_assert (connection); + g_return_val_if_fail (connection, FALSE); /* Start DHCP again on the interface */ - ret = dhcp4_start (self, connection, &reason); - - return (ret != NM_ACT_STAGE_RETURN_FAILURE); + return dhcp4_start (self, connection) != NM_ACT_STAGE_RETURN_FAILURE; } /*****************************************************************************/ @@ -5499,24 +5917,22 @@ reserve_shared_ip (NMDevice *self, NMSettingIPConfig *s_ip4, NMPlatformIP4Addres } static NMIP4Config * -shared4_new_config (NMDevice *self, NMConnection *connection, NMDeviceStateReason *reason) +shared4_new_config (NMDevice *self, NMConnection *connection) { NMIP4Config *config = NULL; NMPlatformIP4Address address; g_return_val_if_fail (self != NULL, NULL); - if (!reserve_shared_ip (self, nm_connection_get_setting_ip4_config (connection), &address)) { - *reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE; + if (!reserve_shared_ip (self, nm_connection_get_setting_ip4_config (connection), &address)) return NULL; - } config = nm_ip4_config_new (nm_device_get_ip_ifindex (self)); address.addr_source = NM_IP_CONFIG_SOURCE_SHARED; nm_ip4_config_add_address (config, &address); /* Remove the address lock when the object gets disposed */ - g_object_set_data_full (G_OBJECT (config), "shared-ip", + g_object_set_qdata_full (G_OBJECT (config), NM_CACHED_QUARK ("shared-ip"), GUINT_TO_POINTER (address.address), release_shared_ip); @@ -5586,7 +6002,7 @@ connection_requires_carrier (NMConnection *connection) return TRUE; } - /* If an IP version wants a carrier and and the other IP version isn't + /* If an IP version wants a carrier and the other IP version isn't * used, the connection requires carrier since it will just fail without one. */ if (ip4_carrier_wanted && !ip6_used) @@ -5626,7 +6042,7 @@ ip4_requires_slaves (NMConnection *connection) static NMActStageReturn act_stage3_ip4_config_start (NMDevice *self, NMIP4Config **out_config, - NMDeviceStateReason *reason) + NMDeviceStateReason *out_failure_reason) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMConnection *connection; @@ -5635,10 +6051,8 @@ act_stage3_ip4_config_start (NMDevice *self, GSList *slaves; gboolean ready_slaves; - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - connection = nm_device_get_applied_connection (self); - g_assert (connection); + g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); if ( connection_ip4_method_requires_carrier (connection, NULL) && priv->is_master @@ -5667,11 +6081,15 @@ act_stage3_ip4_config_start (NMDevice *self, priv->dhcp4.num_tries_left = DHCP_NUM_TRIES_MAX; /* Start IPv4 addressing based on the method requested */ - if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0) - ret = dhcp4_start (self, connection, reason); - else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL) == 0) - ret = ipv4ll_start (self, reason); - else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0) { + if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0) { + ret = dhcp4_start (self, connection); + if (ret == NM_ACT_STAGE_RETURN_FAILURE) + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_DHCP_START_FAILED); + } else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL) == 0) { + ret = ipv4ll_start (self); + if (ret == NM_ACT_STAGE_RETURN_FAILURE) + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED); + } else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0) { NMIP4Config **configs, *config; config = nm_ip4_config_new (nm_device_get_ip_ifindex (self)); @@ -5685,12 +6103,14 @@ act_stage3_ip4_config_start (NMDevice *self, ret = NM_ACT_STAGE_RETURN_POSTPONE; } else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0) { if (out_config) { - *out_config = shared4_new_config (self, connection, reason); + *out_config = shared4_new_config (self, connection); if (*out_config) { priv->dnsmasq_manager = nm_dnsmasq_manager_new (nm_device_get_ip_iface (self)); ret = NM_ACT_STAGE_RETURN_SUCCESS; - } else + } else { + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); ret = NM_ACT_STAGE_RETURN_FAILURE; + } } else g_return_val_if_reached (NM_ACT_STAGE_RETURN_FAILURE); } else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0) @@ -5744,8 +6164,7 @@ _ip6_config_merge_default (gpointer value, gpointer user_data) static gboolean ip6_config_merge_and_apply (NMDevice *self, - gboolean commit, - NMDeviceStateReason *out_reason) + gboolean commit) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMConnection *connection; @@ -5849,7 +6268,7 @@ ip6_config_merge_and_apply (NMDevice *self, * but if the IP method is automatic we need to update the default route to * maintain connectivity. */ - if (nm_device_uses_generated_assumed_connection (self) && !auto_method) + if (nm_device_sys_iface_state_is_external (self) && !auto_method) goto END_ADD_DEFAULT_ROUTE; /* At this point, we treat assumed and non-assumed connections alike. @@ -5858,7 +6277,7 @@ ip6_config_merge_and_apply (NMDevice *self, */ connection_has_default_route - = nm_default_route_manager_ip6_connection_has_default_route (nm_default_route_manager_get (), + = nm_default_route_manager_ip6_connection_has_default_route (nm_netns_get_default_route_manager (priv->netns), connection, &connection_is_never_default); if ( !priv->v6_commit_first_time @@ -5894,7 +6313,8 @@ ip6_config_merge_and_apply (NMDevice *self, memset (&priv->default_route.v6, 0, sizeof (priv->default_route.v6)); priv->default_route.v6.rt_source = NM_IP_CONFIG_SOURCE_USER; priv->default_route.v6.gateway = *gateway; - priv->default_route.v6.metric = nm_device_get_ip6_route_metric (self); + priv->default_route.v6.metric = route_metric_with_penalty (self, + nm_device_get_ip6_route_metric (self)); priv->default_route.v6.mss = nm_ip6_config_get_mss (composite); if (!has_direct_route) { @@ -5923,7 +6343,7 @@ END_ADD_DEFAULT_ROUTE: NMUtilsIPv6IfaceId iid; if (token && nm_utils_ipv6_interface_identifier_get_from_token (&iid, token)) { - nm_platform_link_set_ipv6_token (NM_PLATFORM_GET, + nm_platform_link_set_ipv6_token (nm_device_get_platform (self), nm_device_get_ip_ifindex (self), iid); } @@ -5931,9 +6351,9 @@ END_ADD_DEFAULT_ROUTE: routes_full_sync = commit && priv->v6_commit_first_time - && !nm_device_uses_assumed_connection (self); + && !nm_device_sys_iface_state_is_external_or_assume (self); - success = nm_device_set_ip6_config (self, composite, commit, routes_full_sync, out_reason); + success = nm_device_set_ip6_config (self, composite, commit, routes_full_sync); g_object_unref (composite); if (commit) priv->v6_commit_first_time = FALSE; @@ -5945,7 +6365,6 @@ dhcp6_lease_change (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMSettingsConnection *settings_connection; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; if (priv->dhcp6.ip6_config == NULL) { _LOGW (LOGD_DHCP6, "failed to get DHCPv6 config for rebind"); @@ -5958,16 +6377,15 @@ dhcp6_lease_change (NMDevice *self) g_assert (settings_connection); /* Apply the updated config */ - if (!ip6_config_merge_and_apply (self, TRUE, &reason)) { + if (!ip6_config_merge_and_apply (self, TRUE)) { _LOGW (LOGD_DHCP6, "failed to update IPv6 config in response to DHCP event"); return FALSE; } - /* Notify dispatcher scripts of new DHCPv6 config */ - nm_dispatcher_call (DISPATCHER_ACTION_DHCP6_CHANGE, - settings_connection, - nm_device_get_applied_connection (self), - self, NULL, NULL, NULL); + nm_dispatcher_call_device (NM_DISPATCHER_ACTION_DHCP6_CHANGE, + self, + NULL, + NULL, NULL, NULL); nm_device_remove_pending_action (self, NM_PENDING_ACTION_DHCP6, FALSE); @@ -5979,14 +6397,13 @@ dhcp6_restart_cb (gpointer user_data) { NMDevice *self = user_data; NMDevicePrivate *priv; - NMDeviceStateReason reason; g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); priv = NM_DEVICE_GET_PRIVATE (self); priv->dhcp6.restart_id = 0; - if (!dhcp6_start (self, FALSE, &reason)) + if (!dhcp6_start (self, FALSE)) dhcp_schedule_restart (self, AF_INET6, NULL); return FALSE; @@ -6044,19 +6461,11 @@ dhcp6_fail (NMDevice *self, gboolean timeout) return; } - /* Instead of letting an assumed connection fail (which means that the - * device will transition to the ACTIVATED state without IP configuration), - * retry DHCP again. - */ - if (nm_device_uses_assumed_connection (self)) { - dhcp_schedule_restart (self, AF_INET6, "connection is assumed"); - return; - } - if ( priv->dhcp6.num_tries_left == DHCP_NUM_TRIES_MAX - && (timeout || (priv->ip6_state == IP_CONF))) + && (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) { + else if (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. */ @@ -6194,17 +6603,20 @@ dhcp6_start_with_link_ready (NMDevice *self, NMConnection *connection) s_ip6 = nm_connection_get_setting_ip6_config (connection); g_assert (s_ip6); - hw_addr = nm_platform_link_get_address (NM_PLATFORM_GET, nm_device_get_ip_ifindex (self), &hw_addr_len); + if (priv->ext_ip6_config_captured) + ll_addr = nm_ip6_config_get_address_first_nontentative (priv->ext_ip6_config_captured, TRUE); + + if (!ll_addr) { + _LOGW (LOGD_DHCP6, "can't start DHCPv6: no link-local address"); + return FALSE; + } + + hw_addr = nm_platform_link_get_address (nm_device_get_platform (self), nm_device_get_ip_ifindex (self), &hw_addr_len); if (hw_addr_len) { tmp = g_byte_array_sized_new (hw_addr_len); g_byte_array_append (tmp, hw_addr, hw_addr_len); } - if (priv->ext_ip6_config_captured) - ll_addr = nm_ip6_config_get_address_first_nontentative (priv->ext_ip6_config_captured, TRUE); - - g_return_val_if_fail (ll_addr, FALSE); - priv->dhcp6.client = nm_dhcp_manager_start_ip6 (nm_dhcp_manager_get (), nm_device_get_ip_iface (self), nm_device_get_ip_ifindex (self), @@ -6233,11 +6645,14 @@ dhcp6_start_with_link_ready (NMDevice *self, NMConnection *connection) self); } + if (nm_device_sys_iface_state_is_external_or_assume (self)) + priv->dhcp4.was_active = TRUE; + return !!priv->dhcp6.client; } static gboolean -dhcp6_start (NMDevice *self, gboolean wait_for_ll, NMDeviceStateReason *reason) +dhcp6_start (NMDevice *self, gboolean wait_for_ll) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMConnection *connection; @@ -6271,10 +6686,8 @@ dhcp6_start (NMDevice *self, gboolean wait_for_ll, NMDeviceStateReason *reason) g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); } - if (!dhcp6_start_with_link_ready (self, connection)) { - NM_SET_OUT (reason, NM_DEVICE_STATE_REASON_DHCP_START_FAILED); + if (!dhcp6_start_with_link_ready (self, connection)) return FALSE; - } return TRUE; } @@ -6292,7 +6705,7 @@ nm_device_dhcp6_renew (NMDevice *self, gboolean release) dhcp6_cleanup (self, CLEANUP_TYPE_DECONFIGURE, release); /* Start DHCP again on the interface */ - return dhcp6_start (self, FALSE, NULL); + return dhcp6_start (self, FALSE); } /*****************************************************************************/ @@ -6344,7 +6757,7 @@ nm_device_use_ip6_subnet (NMDevice *self, const NMPlatformIP6Address *subnet) subnet->preferred); /* This also updates the ndisc if there are actual changes. */ - if (!ip6_config_merge_and_apply (self, TRUE, NULL)) + if (!ip6_config_merge_and_apply (self, TRUE)) _LOGW (LOGD_IP6, "ipv6-pd: failed applying IP6 config for connection sharing"); } @@ -6380,7 +6793,7 @@ nm_device_copy_ip6_dns_config (NMDevice *self, NMDevice *from_device) nm_ip6_config_get_search (from_config, i)); } - if (!ip6_config_merge_and_apply (self, TRUE, NULL)) + if (!ip6_config_merge_and_apply (self, TRUE)) _LOGW (LOGD_IP6, "ipv6-pd: failed applying DNS config for connection sharing"); } @@ -6419,7 +6832,8 @@ linklocal6_complete (NMDevice *self) const char *method; g_assert (priv->linklocal6_timeout_id); - g_assert (nm_ip6_config_get_address_first_nontentative (priv->ip6_config, TRUE)); + g_assert (priv->ext_ip6_config_captured); + g_assert (nm_ip6_config_get_address_first_nontentative (priv->ext_ip6_config_captured, TRUE)); linklocal6_cleanup (self); @@ -6521,7 +6935,7 @@ check_and_add_ipv6ll_addr (NMDevice *self) } _LOGD (LOGD_IP6, "linklocal6: adding IPv6LL address %s", nm_utils_inet6_ntop (&lladdr, NULL)); - if (!nm_platform_ip6_address_add (NM_PLATFORM_GET, + if (!nm_platform_ip6_address_add (nm_device_get_platform (self), ip_ifindex, lladdr, 64, @@ -6543,8 +6957,8 @@ linklocal6_start (NMDevice *self) linklocal6_cleanup (self); - if ( priv->ip6_config - && nm_ip6_config_get_address_first_nontentative (priv->ip6_config, TRUE)) + if ( priv->ext_ip6_config_captured + && nm_ip6_config_get_address_first_nontentative (priv->ext_ip6_config_captured, TRUE)) return NM_ACT_STAGE_RETURN_SUCCESS; connection = nm_device_get_applied_connection (self); @@ -6632,7 +7046,7 @@ _commit_mtu (NMDevice *self, const NMIP4Config *config) if (ifindex <= 0) return; - if (nm_device_uses_assumed_connection (self)) { + if (nm_device_sys_iface_state_is_external_or_assume (self)) { /* for assumed connections we don't tamper with the MTU. This is * a bug and supposed to be fixed by the unmanaged/assumed rework. */ return; @@ -6701,7 +7115,7 @@ _commit_mtu (NMDevice *self, const NMIP4Config *config) mtu_desired_orig = mtu_desired; ip6_mtu_orig = ip6_mtu; - mtu_plat = nm_platform_link_get_mtu (NM_PLATFORM_GET, ifindex); + mtu_plat = nm_platform_link_get_mtu (nm_device_get_platform (self), ifindex); if (ip6_mtu) { ip6_mtu = NM_MAX (1280, ip6_mtu); @@ -6743,7 +7157,7 @@ _commit_mtu (NMDevice *self, const NMIP4Config *config) } if (mtu_desired && mtu_desired != mtu_plat) - nm_platform_link_set_mtu (NM_PLATFORM_GET, ifindex, mtu_desired); + nm_platform_link_set_mtu (nm_device_get_platform (self), ifindex, mtu_desired); if (ip6_mtu && ip6_mtu != _IP6_MTU_SYS ()) { nm_device_ipv6_sysctl_set (self, "mtu", @@ -6768,7 +7182,7 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in * addresses as /128. The reason for the /128 is to prevent the kernel * from adding a prefix route for this address. **/ - system_support = nm_platform_check_support_kernel_extended_ifa_flags (NM_PLATFORM_GET); + system_support = nm_platform_check_support_kernel_extended_ifa_flags (nm_device_get_platform (self)); if (system_support) ifa_flags = IFA_F_NOPREFIXROUTE; @@ -6859,14 +7273,13 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in priv->dhcp6.mode = rdata->dhcp_level; if (priv->dhcp6.mode != NM_NDISC_DHCP_LEVEL_NONE) { - NMDeviceStateReason reason; - _LOGD (LOGD_DEVICE | LOGD_DHCP6, "Activation: Stage 3 of 5 (IP Configure Start) starting DHCPv6" " as requested by IPv6 router..."); - if (!dhcp6_start (self, FALSE, &reason)) { + if (!dhcp6_start (self, FALSE)) { if (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_MANAGED) { - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_DHCP_START_FAILED); return; } } @@ -6874,7 +7287,7 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in } if (changed & NM_NDISC_CONFIG_HOP_LIMIT) - nm_platform_sysctl_set_ip6_hop_limit_safe (NM_PLATFORM_GET, nm_device_get_ip_iface (self), rdata->hop_limit); + nm_platform_sysctl_set_ip6_hop_limit_safe (nm_device_get_platform (self), nm_device_get_ip_iface (self), rdata->hop_limit); if (changed & NM_NDISC_CONFIG_MTU) { if (priv->ip6_mtu != rdata->mtu) { @@ -6929,7 +7342,7 @@ addrconf6_start_with_link_ready (NMDevice *self) } /* Apply any manual configuration before starting RA */ - if (!ip6_config_merge_and_apply (self, TRUE, NULL)) + if (!ip6_config_merge_and_apply (self, TRUE)) _LOGW (LOGD_IP6, "failed to apply manual IPv6 configuration"); /* XXX: These sysctls would probably be better set by the lndp ndisc itself. */ @@ -7005,16 +7418,15 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr) g_assert (s_ip6); stable_id = _get_stable_id (self, connection, &stable_type); - if (stable_id) { - priv->ndisc = nm_lndp_ndisc_new (NM_PLATFORM_GET, - nm_device_get_ip_ifindex (self), - nm_device_get_ip_iface (self), - stable_type, - stable_id, - nm_setting_ip6_config_get_addr_gen_mode (s_ip6), - ndisc_node_type (self), - &error); - } + g_assert (stable_id); + priv->ndisc = nm_lndp_ndisc_new (nm_device_get_platform (self), + nm_device_get_ip_ifindex (self), + nm_device_get_ip_iface (self), + stable_type, + stable_id, + nm_setting_ip6_config_get_addr_gen_mode (s_ip6), + ndisc_node_type (self), + &error); if (!priv->ndisc) { _LOGE (LOGD_IP6, "addrconf6: failed to start neighbor discovery: %s", error->message); g_error_free (error); @@ -7024,7 +7436,7 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr) priv->ndisc_use_tempaddr = use_tempaddr; if ( NM_IN_SET (use_tempaddr, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR) - && !nm_platform_check_support_kernel_extended_ifa_flags (NM_PLATFORM_GET)) { + && !nm_platform_check_support_kernel_extended_ifa_flags (nm_device_get_platform (self))) { _LOGW (LOGD_IP6, "The kernel does not support extended IFA_FLAGS needed by NM for " "IPv6 private addresses. This feature is not available"); } @@ -7082,7 +7494,7 @@ save_ip6_properties (NMDevice *self) g_hash_table_remove_all (priv->ip6_saved_properties); for (i = 0; i < G_N_ELEMENTS (ip6_properties_to_save); i++) { - value = nm_platform_sysctl_get (NM_PLATFORM_GET, NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_ip6_property_path (ifname, ip6_properties_to_save[i]))); + value = nm_platform_sysctl_get (nm_device_get_platform (self), NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_ip6_property_path (ifname, ip6_properties_to_save[i]))); if (value) { g_hash_table_insert (priv->ip6_saved_properties, (char *) ip6_properties_to_save[i], @@ -7122,7 +7534,7 @@ set_nm_ipv6ll (NMDevice *self, gboolean enable) int ifindex = nm_device_get_ip_ifindex (self); char *value; - if (!nm_platform_check_support_user_ipv6ll (NM_PLATFORM_GET)) + if (!nm_platform_check_support_user_ipv6ll (nm_device_get_platform (self))) return; priv->nm_ipv6ll = enable; @@ -7131,7 +7543,7 @@ set_nm_ipv6ll (NMDevice *self, gboolean enable) const char *detail = enable ? "enable" : "disable"; _LOGD (LOGD_IP6, "will %s userland IPv6LL", detail); - plerr = nm_platform_link_set_user_ipv6ll_enabled (NM_PLATFORM_GET, ifindex, enable); + plerr = nm_platform_link_set_user_ipv6ll_enabled (nm_device_get_platform (self), ifindex, enable); if (plerr != NM_PLATFORM_ERROR_SUCCESS) { _NMLOG (plerr == NM_PLATFORM_ERROR_NOT_FOUND ? LOGL_DEBUG : LOGL_WARN, LOGD_IP6, @@ -7142,7 +7554,7 @@ set_nm_ipv6ll (NMDevice *self, gboolean enable) if (enable) { /* Bounce IPv6 to ensure the kernel stops IPv6LL address generation */ - value = nm_platform_sysctl_get (NM_PLATFORM_GET, + value = nm_platform_sysctl_get (nm_device_get_platform (self), NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_ip6_property_path (nm_device_get_ip_iface (self), "disable_ipv6"))); if (g_strcmp0 (value, "0") == 0) nm_device_ipv6_sysctl_set (self, "disable_ipv6", "1"); @@ -7209,7 +7621,7 @@ _ip6_privacy_get (NMDevice *self) * Instead of reading static config files in /etc, just read the current sysctl value. * This works as NM only writes to "/proc/sys/net/ipv6/conf/IFNAME/use_tempaddr", but leaves * the "default" entry untouched. */ - ip6_privacy = nm_platform_sysctl_get_int32 (NM_PLATFORM_GET, NMP_SYSCTL_PATHID_ABSOLUTE ("/proc/sys/net/ipv6/conf/default/use_tempaddr"), NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); + ip6_privacy = nm_platform_sysctl_get_int32 (nm_device_get_platform (self), NMP_SYSCTL_PATHID_ABSOLUTE ("/proc/sys/net/ipv6/conf/default/use_tempaddr"), NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); return _ip6_privacy_clamp (ip6_privacy); } @@ -7232,7 +7644,7 @@ ip6_requires_slaves (NMConnection *connection) static NMActStageReturn act_stage3_ip6_config_start (NMDevice *self, NMIP6Config **out_config, - NMDeviceStateReason *reason) + NMDeviceStateReason *out_failure_reason) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; @@ -7243,10 +7655,8 @@ act_stage3_ip6_config_start (NMDevice *self, GSList *slaves; gboolean ready_slaves; - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - connection = nm_device_get_applied_connection (self); - g_assert (connection); + g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); if ( connection_ip6_method_requires_carrier (connection, NULL) && priv->is_master @@ -7302,12 +7712,23 @@ act_stage3_ip6_config_start (NMDevice *self, * IPv6LL if this is not an assumed connection, since assumed connections * will already have IPv6 set up. */ - if (!nm_device_uses_assumed_connection (self)) + if (!nm_device_sys_iface_state_is_external_or_assume (self)) set_nm_ipv6ll (self, TRUE); /* Re-enable IPv6 on the interface */ set_disable_ipv6 (self, "0"); + /* Synchronize external IPv6 configuration with kernel, since + * linklocal6_start() uses the information there to determine if we can + * proceed with the selected method (SLAAC, DHCP, link-local). + */ + nm_platform_process_events (nm_device_get_platform (self)); + g_clear_object (&priv->ext_ip6_config_captured); + priv->ext_ip6_config_captured = nm_ip6_config_capture (nm_device_get_platform (self), + nm_device_get_ifindex (self), + FALSE, + NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); + ip6_privacy = _ip6_privacy_get (self); if ( strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0 @@ -7321,7 +7742,7 @@ act_stage3_ip6_config_start (NMDevice *self, ret = linklocal6_start (self); } else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0) { priv->dhcp6.mode = NM_NDISC_DHCP_LEVEL_MANAGED; - if (!dhcp6_start (self, TRUE, reason)) { + if (!dhcp6_start (self, TRUE)) { /* IPv6 might be disabled; allow IPv4 to proceed */ ret = NM_ACT_STAGE_RETURN_IP_FAIL; } else @@ -7332,7 +7753,7 @@ act_stage3_ip6_config_start (NMDevice *self, _LOGW (LOGD_IP6, "unhandled IPv6 config method '%s'; will fail", method); if ( ret != NM_ACT_STAGE_RETURN_FAILURE - && !nm_device_uses_assumed_connection (self)) { + && !nm_device_sys_iface_state_is_external_or_assume (self)) { switch (ip6_privacy) { case NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN: case NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED: @@ -7362,13 +7783,19 @@ nm_device_activate_stage3_ip4_start (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMActStageReturn ret; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; + NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE; NMIP4Config *ip4_config = NULL; g_assert (priv->ip4_state == IP_WAIT); + /* Slaves stay in IP_CONFIG state until master is ready, and then + * they go directly to SECONDARIES without configuring IPv4. + */ + if (nm_active_connection_get_master (NM_ACTIVE_CONNECTION (priv->act_request))) + return TRUE; + _set_ip_state (self, AF_INET, IP_CONF); - ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip4_config_start (self, &ip4_config, &reason); + ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip4_config_start (self, &ip4_config, &failure_reason); if (ret == NM_ACT_STAGE_RETURN_SUCCESS) { if (!ip4_config) ip4_config = nm_ip4_config_new (nm_device_get_ip_ifindex (self)); @@ -7378,7 +7805,7 @@ nm_device_activate_stage3_ip4_start (NMDevice *self) _set_ip_state (self, AF_INET, IP_DONE); check_ip_state (self, FALSE); } else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, failure_reason); return FALSE; } else if (ret == NM_ACT_STAGE_RETURN_IP_FAIL) { /* Activation not wanted */ @@ -7403,13 +7830,19 @@ nm_device_activate_stage3_ip6_start (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMActStageReturn ret; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; + NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE; NMIP6Config *ip6_config = NULL; g_assert (priv->ip6_state == IP_WAIT); + /* Slaves stay in IP_CONFIG state until master is ready, and then + * they go directly to SECONDARIES without configuring IPv6. + */ + if (nm_active_connection_get_master (NM_ACTIVE_CONNECTION (priv->act_request))) + return TRUE; + _set_ip_state (self, AF_INET6, IP_CONF); - ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip6_config_start (self, &ip6_config, &reason); + ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip6_config_start (self, &ip6_config, &failure_reason); if (ret == NM_ACT_STAGE_RETURN_SUCCESS) { if (!ip6_config) ip6_config = nm_ip6_config_new (nm_device_get_ip_ifindex (self)); @@ -7423,7 +7856,7 @@ nm_device_activate_stage3_ip6_start (NMDevice *self) _set_ip_state (self, AF_INET6, IP_DONE); check_ip_state (self, FALSE); } else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, failure_reason); return FALSE; } else if (ret == NM_ACT_STAGE_RETURN_IP_FAIL) { /* Activation not wanted */ @@ -7456,7 +7889,7 @@ activate_stage3_ip_config_start (NMDevice *self) nm_device_state_changed (self, NM_DEVICE_STATE_IP_CONFIG, NM_DEVICE_STATE_REASON_NONE); /* Device should be up before we can do anything with it */ - if (!nm_platform_link_is_up (NM_PLATFORM_GET, nm_device_get_ip_ifindex (self))) + if (!nm_platform_link_is_up (nm_device_get_platform (self), nm_device_get_ip_ifindex (self))) _LOGW (LOGD_DEVICE, "interface %s not up for IP configuration", nm_device_get_ip_iface (self)); /* If the device is a slave, then we don't do any IP configuration but we @@ -7495,60 +7928,72 @@ activate_stage3_ip_config_start (NMDevice *self) check_ip_state (self, TRUE); } -static gboolean -fw_change_zone_handle (NMDevice *self, - NMFirewallManagerCallId call_id, - GError *error) +static void +fw_change_zone_cb (NMFirewallManager *firewall_manager, + NMFirewallManagerCallId call_id, + GError *error, + gpointer user_data) { + NMDevice *self = user_data; NMDevicePrivate *priv; - g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + g_return_if_fail (NM_IS_DEVICE (self)); priv = NM_DEVICE_GET_PRIVATE (self); - g_return_val_if_fail (priv->fw_call == call_id, FALSE); + if (priv->fw_call != call_id) + g_return_if_reached (); priv->fw_call = NULL; - return !nm_utils_error_is_cancelled (error, FALSE); + if (nm_utils_error_is_cancelled (error, FALSE)) + return; + + switch (priv->fw_state) { + case FIREWALL_STATE_WAIT_STAGE_3: + priv->fw_state = FIREWALL_STATE_INITIALIZED; + nm_device_activate_schedule_stage3_ip_config_start (self); + break; + case FIREWALL_STATE_WAIT_IP_CONFIG: + priv->fw_state = FIREWALL_STATE_INITIALIZED; + if (priv->ip4_state == IP_DONE || priv->ip6_state == IP_DONE) + nm_device_start_ip_check (self); + break; + case FIREWALL_STATE_INITIALIZED: + break; + default: + g_return_if_reached (); + } } static void -fw_change_zone_cb_stage2 (NMFirewallManager *firewall_manager, - NMFirewallManagerCallId call_id, - GError *error, - gpointer user_data) +fw_change_zone (NMDevice *self) { - NMDevice *self = user_data; - NMDevicePrivate *priv; - - if (!fw_change_zone_handle (self, call_id, error)) - return; - - /* FIXME: fail the device on error? */ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMConnection *applied_connection; + NMSettingConnection *s_con; - priv = NM_DEVICE_GET_PRIVATE (self); - priv->fw_ready = TRUE; + nm_assert (priv->fw_state >= FIREWALL_STATE_INITIALIZED); - nm_device_activate_schedule_stage3_ip_config_start (self); -} + applied_connection = nm_device_get_applied_connection (self); + nm_assert (applied_connection); -static void -fw_change_zone_cb_ip_check (NMFirewallManager *firewall_manager, - NMFirewallManagerCallId call_id, - GError *error, - gpointer user_data) -{ - NMDevice *self = user_data; - NMDevicePrivate *priv; + s_con = nm_connection_get_setting_connection (applied_connection); + nm_assert (s_con); - if (!fw_change_zone_handle (self, call_id, error)) - return; + if (priv->fw_call) { + nm_firewall_manager_cancel_call (priv->fw_call); + nm_assert (!priv->fw_call); + } - /* FIXME: fail the device on error? */ + if (G_UNLIKELY (!priv->fw_mgr)) + priv->fw_mgr = g_object_ref (nm_firewall_manager_get ()); - priv = NM_DEVICE_GET_PRIVATE (self); - if (priv->ip4_state == IP_DONE || priv->ip6_state == IP_DONE) - nm_device_start_ip_check (self); + priv->fw_call = nm_firewall_manager_add_or_change_zone (priv->fw_mgr, + nm_device_get_ip_iface (self), + nm_setting_connection_get_zone (s_con), + FALSE, /* change zone */ + fw_change_zone_cb, + self); } /* @@ -7560,9 +8005,6 @@ void nm_device_activate_schedule_stage3_ip_config_start (NMDevice *self) { NMDevicePrivate *priv; - NMConnection *connection; - NMSettingConnection *s_con = NULL; - const char *zone; g_return_if_fail (NM_IS_DEVICE (self)); @@ -7570,37 +8012,30 @@ nm_device_activate_schedule_stage3_ip_config_start (NMDevice *self) g_return_if_fail (priv->act_request); /* Add the interface to the specified firewall zone */ - connection = nm_device_get_applied_connection (self); - g_assert (connection); - s_con = nm_connection_get_setting_connection (connection); - - if (!priv->fw_ready) { - if (nm_device_uses_generated_assumed_connection (self)) - priv->fw_ready = TRUE; - else { - if (!priv->fw_call) { - zone = nm_setting_connection_get_zone (s_con); - - _LOGD (LOGD_DEVICE, "Activation: setting firewall zone '%s'", zone ? zone : "default"); - priv->fw_call = nm_firewall_manager_add_or_change_zone (nm_firewall_manager_get (), - nm_device_get_ip_iface (self), - zone, - FALSE, - fw_change_zone_cb_stage2, - self); - } + if (priv->fw_state == FIREWALL_STATE_UNMANAGED) { + if (!nm_device_sys_iface_state_is_external (self)) { + priv->fw_state = FIREWALL_STATE_WAIT_STAGE_3; + fw_change_zone (self); return; } + + /* fake success. */ + priv->fw_state = FIREWALL_STATE_INITIALIZED; + } else if (priv->fw_state == FIREWALL_STATE_WAIT_STAGE_3) { + /* a firewall call for stage3 is pending. Return and wait. */ + return; } + nm_assert (priv->fw_state == FIREWALL_STATE_INITIALIZED); + activation_source_schedule (self, activate_stage3_ip_config_start, AF_INET); } static NMActStageReturn -act_stage4_ip4_config_timeout (NMDevice *self, NMDeviceStateReason *reason) +act_stage4_ip4_config_timeout (NMDevice *self, NMDeviceStateReason *out_failure_reason) { if (!get_ip_config_may_fail (self, AF_INET)) { - *reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE; + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); return NM_ACT_STAGE_RETURN_FAILURE; } return NM_ACT_STAGE_RETURN_SUCCESS; @@ -7616,13 +8051,13 @@ static void activate_stage4_ip4_config_timeout (NMDevice *self) { NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; + NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE; - ret = NM_DEVICE_GET_CLASS (self)->act_stage4_ip4_config_timeout (self, &reason); + ret = NM_DEVICE_GET_CLASS (self)->act_stage4_ip4_config_timeout (self, &failure_reason); if (ret == NM_ACT_STAGE_RETURN_POSTPONE) return; else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, failure_reason); return; } g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); @@ -7652,10 +8087,10 @@ nm_device_activate_schedule_ip4_config_timeout (NMDevice *self) } static NMActStageReturn -act_stage4_ip6_config_timeout (NMDevice *self, NMDeviceStateReason *reason) +act_stage4_ip6_config_timeout (NMDevice *self, NMDeviceStateReason *out_failure_reason) { if (!get_ip_config_may_fail (self, AF_INET6)) { - *reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE; + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); return NM_ACT_STAGE_RETURN_FAILURE; } @@ -7672,13 +8107,13 @@ static void activate_stage4_ip6_config_timeout (NMDevice *self) { NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; + NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE; - ret = NM_DEVICE_GET_CLASS (self)->act_stage4_ip6_config_timeout (self, &reason); + ret = NM_DEVICE_GET_CLASS (self)->act_stage4_ip6_config_timeout (self, &failure_reason); if (ret == NM_ACT_STAGE_RETURN_POSTPONE) return; if (ret == NM_ACT_STAGE_RETURN_FAILURE) { - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, failure_reason); return; } g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); @@ -7708,7 +8143,7 @@ nm_device_activate_schedule_ip6_config_timeout (NMDevice *self) } static gboolean -share_init (void) +share_init (NMDevice *self) { char *modules[] = { "ip_tables", "iptable_nat", "nf_nat_ftp", "nf_nat_irc", "nf_nat_sip", "nf_nat_tftp", "nf_nat_pptp", "nf_nat_h323", @@ -7716,14 +8151,14 @@ share_init (void) char **iter; int errsv; - if (!nm_platform_sysctl_set (NM_PLATFORM_GET, NMP_SYSCTL_PATHID_ABSOLUTE ("/proc/sys/net/ipv4/ip_forward"), "1")) { + if (!nm_platform_sysctl_set (nm_device_get_platform (self), NMP_SYSCTL_PATHID_ABSOLUTE ("/proc/sys/net/ipv4/ip_forward"), "1")) { errsv = errno; nm_log_err (LOGD_SHARING, "share: error enabling IPv4 forwarding: (%d) %s", errsv, strerror (errsv)); return FALSE; } - if (!nm_platform_sysctl_set (NM_PLATFORM_GET, NMP_SYSCTL_PATHID_ABSOLUTE ("/proc/sys/net/ipv4/ip_dynaddr"), "1")) { + if (!nm_platform_sysctl_set (nm_device_get_platform (self), NMP_SYSCTL_PATHID_ABSOLUTE ("/proc/sys/net/ipv4/ip_dynaddr"), "1")) { errsv = errno; nm_log_err (LOGD_SHARING, "share: error enabling dynamic addresses: (%d) %s", errsv, strerror (errsv)); @@ -7770,7 +8205,7 @@ start_sharing (NMDevice *self, NMIP4Config *config) if (!inet_ntop (AF_INET, &network, str_addr, sizeof (str_addr))) return FALSE; - if (!share_init ()) + if (!share_init (self)) return FALSE; req = nm_device_get_act_request (self); @@ -7826,7 +8261,7 @@ arp_announce (NMDevice *self) arp_cleanup (self); - hw_addr = nm_platform_link_get_address (NM_PLATFORM_GET, + hw_addr = nm_platform_link_get_address (nm_device_get_platform (self), nm_device_get_ip_ifindex (self), &hw_addr_len); @@ -7868,7 +8303,6 @@ activate_stage5_ip4_config_commit (NMDevice *self) NMActRequest *req; const char *method; NMConnection *connection; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; int ip_ifindex; req = nm_device_get_act_request (self); @@ -7878,16 +8312,16 @@ 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)) { - nm_platform_link_set_up (NM_PLATFORM_GET, ip_ifindex, NULL); - if (!nm_platform_link_is_up (NM_PLATFORM_GET, ip_ifindex)) + if (!nm_platform_link_is_up (nm_device_get_platform (self), ip_ifindex) && !nm_device_sys_iface_state_is_external_or_assume (self)) { + nm_platform_link_set_up (nm_device_get_platform (self), ip_ifindex, NULL); + if (!nm_platform_link_is_up (nm_device_get_platform (self), ip_ifindex)) _LOGW (LOGD_DEVICE, "interface %s not up for IP configuration", nm_device_get_ip_iface (self)); } /* NULL to use the existing priv->dev_ip4_config */ - if (!ip4_config_merge_and_apply (self, NULL, TRUE, &reason)) { + if (!ip4_config_merge_and_apply (self, NULL, TRUE)) { _LOGD (LOGD_DEVICE | LOGD_IP4, "Activation: Stage 5 of 5 (IPv4 Commit) failed"); - nm_device_ip_method_failed (self, AF_INET, reason); + nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_CONFIG_FAILED); return; } @@ -7908,14 +8342,10 @@ activate_stage5_ip4_config_commit (NMDevice *self) if ( priv->dhcp4.client && nm_device_activate_ip4_state_in_conf (self) && (nm_device_get_state (self) > NM_DEVICE_STATE_IP_CONFIG)) { - /* Notify dispatcher scripts of new DHCP4 config */ - nm_dispatcher_call (DISPATCHER_ACTION_DHCP4_CHANGE, - nm_device_get_settings_connection (self), - nm_device_get_applied_connection (self), - self, - NULL, - NULL, - NULL); + nm_dispatcher_call_device (NM_DISPATCHER_ACTION_DHCP4_CHANGE, + self, + NULL, + NULL, NULL, NULL); } arp_announce (self); @@ -7991,7 +8421,7 @@ dad6_get_pending_addresses (NMDevice *self) num = nm_ip6_config_get_num_addresses (confs[i]); for (j = 0; j < num; j++) { addr = nm_ip6_config_get_address (confs[i], j); - pl_addr = nm_platform_ip6_address_get (NM_PLATFORM_GET, + pl_addr = nm_platform_ip6_address_get (nm_device_get_platform (self), ifindex, addr->address, addr->plen); @@ -8021,7 +8451,6 @@ activate_stage5_ip6_config_commit (NMDevice *self) NMActRequest *req; const char *method; NMConnection *connection; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; int ip_ifindex; int errsv; @@ -8032,26 +8461,23 @@ 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)) { - nm_platform_link_set_up (NM_PLATFORM_GET, ip_ifindex, NULL); - if (!nm_platform_link_is_up (NM_PLATFORM_GET, ip_ifindex)) + if (!nm_platform_link_is_up (nm_device_get_platform (self), ip_ifindex) && !nm_device_sys_iface_state_is_external_or_assume (self)) { + nm_platform_link_set_up (nm_device_get_platform (self), ip_ifindex, NULL); + if (!nm_platform_link_is_up (nm_device_get_platform (self), ip_ifindex)) _LOGW (LOGD_DEVICE, "interface %s not up for IP configuration", nm_device_get_ip_iface (self)); } - if (ip6_config_merge_and_apply (self, TRUE, &reason)) { + if (ip6_config_merge_and_apply (self, TRUE)) { if ( priv->dhcp6.mode != NM_NDISC_DHCP_LEVEL_NONE && priv->ip6_state == IP_CONF) { if (priv->dhcp6.ip6_config) { /* If IPv6 wasn't the first IP to complete, and DHCP was used, * then ensure dispatcher scripts get the DHCP lease information. */ - nm_dispatcher_call (DISPATCHER_ACTION_DHCP6_CHANGE, - nm_device_get_settings_connection (self), - nm_device_get_applied_connection (self), - self, - NULL, - NULL, - NULL); + nm_dispatcher_call_device (NM_DISPATCHER_ACTION_DHCP6_CHANGE, + self, + NULL, + NULL, NULL, NULL); } else { /* still waiting for first dhcp6 lease. */ return; @@ -8064,7 +8490,7 @@ activate_stage5_ip6_config_commit (NMDevice *self) method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG); if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_SHARED) == 0) { - if (!nm_platform_sysctl_set (NM_PLATFORM_GET, NMP_SYSCTL_PATHID_ABSOLUTE ("/proc/sys/net/ipv6/conf/all/forwarding"), "1")) { + if (!nm_platform_sysctl_set (nm_device_get_platform (self), NMP_SYSCTL_PATHID_ABSOLUTE ("/proc/sys/net/ipv6/conf/all/forwarding"), "1")) { errsv = errno; _LOGE (LOGD_SHARING, "share: error enabling IPv6 forwarding: (%d) %s", errsv, strerror (errsv)); nm_device_ip_method_failed (self, AF_INET6, NM_DEVICE_STATE_REASON_SHARED_START_FAILED); @@ -8073,18 +8499,21 @@ activate_stage5_ip6_config_commit (NMDevice *self) /* Check if we have to wait for DAD */ if (priv->ip6_state == IP_CONF && !priv->dad6_ip6_config) { - priv->dad6_ip6_config = dad6_get_pending_addresses (self); + if (!priv->carrier && priv->ignore_carrier && get_ip_config_may_fail (self, AF_INET6)) + _LOGI (LOGD_DEVICE | LOGD_IP6, "IPv6 DAD: carrier missing and ignored, not delaying activation"); + else + priv->dad6_ip6_config = dad6_get_pending_addresses (self); + if (priv->dad6_ip6_config) { - _LOGD (LOGD_DEVICE | LOGD_IP6, "IPv6 DAD: waiting termination"); + _LOGD (LOGD_DEVICE | LOGD_IP6, "IPv6 DAD: awaiting termination"); } else { - /* No tentative addresses, proceed right away */ _set_ip_state (self, AF_INET6, IP_DONE); check_ip_state (self, FALSE); } } } else { _LOGW (LOGD_DEVICE | LOGD_IP6, "Activation: Stage 5 of 5 (IPv6 Commit) failed"); - nm_device_ip_method_failed (self, AF_INET6, reason); + nm_device_ip_method_failed (self, AF_INET6, NM_DEVICE_STATE_REASON_CONFIG_FAILED); } } @@ -8164,7 +8593,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); } @@ -8234,7 +8680,7 @@ delete_on_deactivate_link_delete (gpointer user_data) if (!nm_device_unrealize (data->device, TRUE, &error)) _LOGD (LOGD_DEVICE, "delete_on_deactivate: unrealizing %d failed (%s)", data->ifindex, error->message); } else - nm_platform_link_delete (NM_PLATFORM_GET, data->ifindex); + nm_platform_link_delete (nm_device_get_platform (self), data->ifindex); g_free (data); return FALSE; @@ -8323,12 +8769,14 @@ _cleanup_ip6_pre (NMDevice *self, CleanupType cleanup_type) addrconf6_cleanup (self); } -static gboolean -_hash_check_invalid_keys_impl (GHashTable *hash, const char *setting_name, GError **error, const char **argv) +gboolean +_nm_device_hash_check_invalid_keys (GHashTable *hash, const char *setting_name, + GError **error, const char **argv) { guint found_keys = 0; guint i; + nm_assert (hash && g_hash_table_size (hash) > 0); nm_assert (argv && argv[0]); #if NM_MORE_ASSERTS > 10 @@ -8344,9 +8792,6 @@ _hash_check_invalid_keys_impl (GHashTable *hash, const char *setting_name, GErro } #endif - if (!hash || g_hash_table_size (hash) == 0) - return TRUE; - for (i = 0; argv[i]; i++) { if (g_hash_table_contains (hash, argv[i])) found_keys++; @@ -8362,7 +8807,7 @@ _hash_check_invalid_keys_impl (GHashTable *hash, const char *setting_name, GErro g_hash_table_iter_init (&iter, hash); while (g_hash_table_iter_next (&iter, (gpointer *) &k, NULL)) { - if (_nm_utils_strv_find_first ((char **) argv, -1, k) < 0) { + if (nm_utils_strv_find_first ((char **) argv, -1, k) < 0) { first_invalid_key = k; break; } @@ -8387,12 +8832,12 @@ _hash_check_invalid_keys_impl (GHashTable *hash, const char *setting_name, GErro return TRUE; } -#define _hash_check_invalid_keys(hash, setting_name, error, ...) _hash_check_invalid_keys_impl (hash, setting_name, error, ((const char *[]) { __VA_ARGS__, NULL })) void nm_device_reactivate_ip4_config (NMDevice *self, NMSettingIPConfig *s_ip4_old, - NMSettingIPConfig *s_ip4_new) + NMSettingIPConfig *s_ip4_new, + gboolean force_restart) { NMDevicePrivate *priv; const char *method_old, *method_new; @@ -8408,20 +8853,23 @@ nm_device_reactivate_ip4_config (NMDevice *self, s_ip4_new, nm_device_get_ip4_route_metric (self)); - method_old = s_ip4_old ? - nm_setting_ip_config_get_method (s_ip4_old) : - NM_SETTING_IP4_CONFIG_METHOD_DISABLED; - method_new = s_ip4_new ? - nm_setting_ip_config_get_method (s_ip4_new) : - NM_SETTING_IP4_CONFIG_METHOD_DISABLED; + if (!force_restart) { + method_old = s_ip4_old + ? nm_setting_ip_config_get_method (s_ip4_old) + : NM_SETTING_IP4_CONFIG_METHOD_DISABLED; + method_new = s_ip4_new + ? nm_setting_ip_config_get_method (s_ip4_new) + : NM_SETTING_IP4_CONFIG_METHOD_DISABLED; + force_restart = !nm_streq0 (method_old, method_new); + } - if (!nm_streq0 (method_old, method_new)) { + if (force_restart) { _cleanup_ip4_pre (self, CLEANUP_TYPE_DECONFIGURE); _set_ip_state (self, AF_INET, IP_WAIT); if (!nm_device_activate_stage3_ip4_start (self)) _LOGW (LOGD_IP4, "Failed to apply IPv4 configuration"); } else { - if (!ip4_config_merge_and_apply (self, NULL, TRUE, NULL)) + if (!ip4_config_merge_and_apply (self, NULL, TRUE)) _LOGW (LOGD_IP4, "Failed to reapply IPv4 configuration"); } } @@ -8430,7 +8878,8 @@ nm_device_reactivate_ip4_config (NMDevice *self, void nm_device_reactivate_ip6_config (NMDevice *self, NMSettingIPConfig *s_ip6_old, - NMSettingIPConfig *s_ip6_new) + NMSettingIPConfig *s_ip6_new, + gboolean force_restart) { NMDevicePrivate *priv; const char *method_old, *method_new; @@ -8446,31 +8895,108 @@ nm_device_reactivate_ip6_config (NMDevice *self, s_ip6_new, nm_device_get_ip6_route_metric (self)); - method_old = s_ip6_old ? - nm_setting_ip_config_get_method (s_ip6_old) : - NM_SETTING_IP6_CONFIG_METHOD_IGNORE; - method_new = s_ip6_new ? - nm_setting_ip_config_get_method (s_ip6_new) : - NM_SETTING_IP6_CONFIG_METHOD_IGNORE; + if (!force_restart) { + method_old = s_ip6_old + ? nm_setting_ip_config_get_method (s_ip6_old) + : NM_SETTING_IP6_CONFIG_METHOD_IGNORE; + method_new = s_ip6_new + ? nm_setting_ip_config_get_method (s_ip6_new) + : NM_SETTING_IP6_CONFIG_METHOD_IGNORE; + force_restart = !nm_streq0 (method_old, method_new); + } - if (!nm_streq0 (method_old, method_new)) { + if (force_restart) { _cleanup_ip6_pre (self, CLEANUP_TYPE_DECONFIGURE); _set_ip_state (self, AF_INET6, IP_WAIT); if (!nm_device_activate_stage3_ip6_start (self)) _LOGW (LOGD_IP6, "Failed to apply IPv6 configuration"); } else { - if (!ip6_config_merge_and_apply (self, TRUE, NULL)) + if (!ip6_config_merge_and_apply (self, TRUE)) _LOGW (LOGD_IP4, "Failed to reapply IPv6 configuration"); } } } +static void +_pacrunner_manager_send (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + nm_pacrunner_manager_remove_clear (priv->pacrunner_manager, + &priv->pacrunner_call_id); + + if (!priv->pacrunner_manager) + priv->pacrunner_manager = g_object_ref (nm_pacrunner_manager_get ()); + + priv->pacrunner_call_id = nm_pacrunner_manager_send (priv->pacrunner_manager, + nm_device_get_ip_iface (self), + priv->proxy_config, + NULL, + NULL); +} + +static void +reactivate_proxy_config (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (!priv->pacrunner_call_id) + return; + nm_device_set_proxy_config (self, priv->dhcp4.pac_url); + _pacrunner_manager_send (self); +} + +static gboolean +can_reapply_change (NMDevice *self, const char *setting_name, + NMSetting *s_old, NMSetting *s_new, + GHashTable *diffs, GError **error) +{ + if (nm_streq (setting_name, NM_SETTING_CONNECTION_SETTING_NAME)) { + /* Whitelist allowed properties from "connection" setting which are + * allowed to differ. + * + * This includes UUID, there is no principal problem with reapplying a + * connection and changing it's UUID. In fact, disallowing it makes it + * cumbersome for the user to reapply any connection but the original + * settings-connection. */ + return nm_device_hash_check_invalid_keys (diffs, + NM_SETTING_CONNECTION_SETTING_NAME, + error, + NM_SETTING_CONNECTION_ID, + NM_SETTING_CONNECTION_UUID, + NM_SETTING_CONNECTION_STABLE_ID, + NM_SETTING_CONNECTION_AUTOCONNECT, + NM_SETTING_CONNECTION_ZONE, + NM_SETTING_CONNECTION_METERED, + NM_SETTING_CONNECTION_LLDP); + } else if (NM_IN_STRSET (setting_name, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_PROXY_SETTING_NAME)) { + /* accept all */ + return TRUE; + } else { + g_set_error (error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + "Can't reapply any changes to '%s' setting", + setting_name); + return FALSE; + } +} + +static void +reapply_connection (NMDevice *self, NMConnection *con_old, NMConnection *con_new) +{ + +} -/* reapply_connection: +/* check_and_reapply_connection: * @connection: the new connection settings to be applied or %NULL to reapply * the current settings connection * @version_id: either zero, or the current version id for the applied * connection. + * @audit_args: on return, a string representing the changes * @error: the error if %FALSE is returned * * Change configuration of an already configured device if possible. @@ -8479,11 +9005,13 @@ nm_device_reactivate_ip6_config (NMDevice *self, * Return: %FALSE if the new configuration can not be reapplied. */ static gboolean -reapply_connection (NMDevice *self, - NMConnection *connection, - guint64 version_id, - GError **error) +check_and_reapply_connection (NMDevice *self, + NMConnection *connection, + guint64 version_id, + char **audit_args, + GError **error) { + NMDeviceClass *klass = NM_DEVICE_GET_CLASS (self); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMConnection *applied = nm_device_get_applied_connection (self); gs_unref_object NMConnection *applied_clone = NULL; @@ -8491,6 +9019,7 @@ reapply_connection (NMDevice *self, NMConnection *con_old, *con_new; NMSettingIPConfig *s_ip4_old, *s_ip4_new; NMSettingIPConfig *s_ip6_old, *s_ip6_new; + GHashTableIter iter; if (priv->state != NM_DEVICE_STATE_ACTIVATED) { g_set_error_literal (error, @@ -8506,30 +9035,29 @@ reapply_connection (NMDevice *self, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS, &diffs); + if (diffs && nm_audit_manager_audit_enabled (nm_audit_manager_get ())) + *audit_args = nm_utils_format_con_diff_for_audit (diffs); + else + *audit_args = NULL; + /************************************************************************** * check for unsupported changes and reject to reapply *************************************************************************/ - if (!_hash_check_invalid_keys (diffs, NULL, error, - NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_CONNECTION_SETTING_NAME)) - return FALSE; - - /* whitelist allowed properties from "connection" setting which are allowed to differ. - * - * This includes UUID, there is no principal problem with reapplying a connection - * and changing it's UUID. In fact, disallowing it makes it cumbersome for the user - * to reapply any connection but the original settings-connection. */ - if (!_hash_check_invalid_keys (diffs ? g_hash_table_lookup (diffs, NM_SETTING_CONNECTION_SETTING_NAME) : NULL, - NM_SETTING_CONNECTION_SETTING_NAME, - error, - NM_SETTING_CONNECTION_ID, - NM_SETTING_CONNECTION_UUID, - NM_SETTING_CONNECTION_STABLE_ID, - NM_SETTING_CONNECTION_AUTOCONNECT, - NM_SETTING_CONNECTION_ZONE, - NM_SETTING_CONNECTION_METERED)) - return FALSE; + if (diffs) { + char *setting_name; + GHashTable *setting_diff; + + g_hash_table_iter_init (&iter, diffs); + while (g_hash_table_iter_next (&iter, (gpointer *) &setting_name, (gpointer *) &setting_diff)) { + if (!klass->can_reapply_change (self, + setting_name, + nm_connection_get_setting_by_name (applied, setting_name), + nm_connection_get_setting_by_name (connection, setting_name), + setting_diff, + error)) + return FALSE; + } + } if ( version_id != 0 && version_id != nm_active_connection_version_id_get ((NMActiveConnection *) priv->act_request)) { @@ -8548,7 +9076,7 @@ reapply_connection (NMDevice *self, nm_active_connection_version_id_bump ((NMActiveConnection *) priv->act_request); _LOGD (LOGD_DEVICE, "reapply (version-id %llu%s)", - (long long unsigned) nm_active_connection_version_id_get (((NMActiveConnection *) priv->act_request)), + (unsigned long long) nm_active_connection_version_id_get (((NMActiveConnection *) priv->act_request)), diffs ? "" : " (unmodified)"); if (diffs) { @@ -8559,7 +9087,7 @@ reapply_connection (NMDevice *self, NMSettingConnection *s_con_a, *s_con_n; /* we allow re-applying a connection with differing ID, UUID, STABLE_ID and AUTOCONNECT. - * This is for convenience but these values are not actually changable. So, check + * This is for convenience but these values are not actually changeable. So, check * if they changed, and if the did revert to the original values. */ s_con_a = nm_connection_get_setting_connection (applied); s_con_n = nm_connection_get_setting_connection (connection); @@ -8587,20 +9115,27 @@ reapply_connection (NMDevice *self, } else con_old = con_new = applied; - s_ip4_new = nm_connection_get_setting_ip4_config (con_new); - s_ip4_old = nm_connection_get_setting_ip4_config (con_old); - s_ip6_new = nm_connection_get_setting_ip6_config (con_new); - s_ip6_old = nm_connection_get_setting_ip6_config (con_old); + priv->v4_commit_first_time = TRUE; + priv->v6_commit_first_time = TRUE; /************************************************************************** * Reapply changes *************************************************************************/ + klass->reapply_connection (self, con_old, con_new); nm_device_update_firewall_zone (self); nm_device_update_metered (self); + lldp_init (self, FALSE); + + s_ip4_old = nm_connection_get_setting_ip4_config (con_old); + s_ip4_new = nm_connection_get_setting_ip4_config (con_new); + s_ip6_old = nm_connection_get_setting_ip6_config (con_old); + s_ip6_new = nm_connection_get_setting_ip6_config (con_new); - nm_device_reactivate_ip4_config (self, s_ip4_old, s_ip4_new); - nm_device_reactivate_ip6_config (self, s_ip6_old, s_ip6_new); + nm_device_reactivate_ip4_config (self, s_ip4_old, s_ip4_new, TRUE); + nm_device_reactivate_ip6_config (self, s_ip6_old, s_ip6_new, TRUE); + + reactivate_proxy_config (self); return TRUE; } @@ -8621,6 +9156,7 @@ reapply_cb (NMDevice *self, guint64 version_id = 0; gs_unref_object NMConnection *connection = NULL; GError *local = NULL; + gs_free char *audit_args = NULL; if (reapply_data) { connection = reapply_data->connection; @@ -8629,20 +9165,21 @@ reapply_cb (NMDevice *self, } if (error) { - nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, subject, error->message); + nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, NULL, subject, error->message); g_dbus_method_invocation_return_gerror (context, error); return; } - if (!reapply_connection (self, - connection ? : (NMConnection *) nm_device_get_settings_connection (self), - version_id, - &local)) { - nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, subject, local->message); + if (!check_and_reapply_connection (self, + connection ? : (NMConnection *) nm_device_get_settings_connection (self), + version_id, + &audit_args, + &local)) { + nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, audit_args, subject, local->message); g_dbus_method_invocation_take_error (context, local); local = NULL; } else { - nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, TRUE, subject, NULL); + nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, TRUE, audit_args, subject, NULL); g_dbus_method_invocation_return_value (context, NULL); } } @@ -8665,7 +9202,7 @@ impl_device_reapply (NMDevice *self, error = g_error_new_literal (NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "Invalid flags specified"); - nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, context, error->message); + nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, NULL, context, error->message); g_dbus_method_invocation_take_error (context, error); return; } @@ -8674,7 +9211,7 @@ impl_device_reapply (NMDevice *self, error = g_error_new_literal (NM_DEVICE_ERROR, NM_DEVICE_ERROR_NOT_ACTIVE, "Device is not activated"); - nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, context, error->message); + nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, NULL, context, error->message); g_dbus_method_invocation_take_error (context, error); return; } @@ -8690,7 +9227,7 @@ impl_device_reapply (NMDevice *self, &error); if (!connection) { g_prefix_error (&error, "The settings specified are invalid: "); - nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, context, error->message); + nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, NULL, context, error->message); g_dbus_method_invocation_take_error (context, error); return; } @@ -8820,7 +9357,7 @@ disconnect_cb (NMDevice *self, if (error) { g_dbus_method_invocation_return_gerror (context, error); - nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DISCONNECT, self, FALSE, subject, error->message); + nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DISCONNECT, self, FALSE, NULL, subject, error->message); return; } @@ -8829,16 +9366,16 @@ disconnect_cb (NMDevice *self, local = g_error_new_literal (NM_DEVICE_ERROR, NM_DEVICE_ERROR_NOT_ACTIVE, "Device is not active"); - nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DISCONNECT, self, FALSE, subject, local->message); + nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DISCONNECT, self, FALSE, NULL, subject, local->message); g_dbus_method_invocation_take_error (context, local); } else { - nm_device_set_autoconnect (self, FALSE); + nm_device_set_autoconnect_intern (self, FALSE); nm_device_state_changed (self, NM_DEVICE_STATE_DEACTIVATING, NM_DEVICE_STATE_REASON_USER_REQUESTED); g_dbus_method_invocation_return_value (context, NULL); - nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DISCONNECT, self, TRUE, subject, NULL); + nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DISCONNECT, self, TRUE, NULL, subject, NULL); } } @@ -8846,7 +9383,9 @@ 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_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); } } @@ -8889,12 +9428,12 @@ delete_cb (NMDevice *self, if (error) { g_dbus_method_invocation_return_gerror (context, error); - nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DELETE, self, FALSE, subject, error->message); + nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DELETE, self, FALSE, NULL, subject, error->message); return; } /* Authorized */ - nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DELETE, self, TRUE, subject, NULL); + nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DELETE, self, TRUE, NULL, subject, NULL); if (nm_device_unrealize (self, TRUE, &local)) g_dbus_method_invocation_return_value (context, NULL); else @@ -9108,12 +9647,11 @@ nm_device_get_proxy_config (NMDevice *self) } static void -nm_device_set_proxy_config (NMDevice *self, GHashTable *options) +nm_device_set_proxy_config (NMDevice *self, const char *pac_url) { NMDevicePrivate *priv; NMConnection *connection; NMSettingProxy *s_proxy = NULL; - char *pac = NULL; g_return_if_fail (NM_IS_DEVICE (self)); @@ -9122,17 +9660,12 @@ nm_device_set_proxy_config (NMDevice *self, GHashTable *options) g_clear_object (&priv->proxy_config); priv->proxy_config = nm_proxy_config_new (); - if (options) { - pac = g_hash_table_lookup (options, "wpad"); - if (pac) { - nm_proxy_config_set_method (priv->proxy_config, NM_PROXY_CONFIG_METHOD_AUTO); - nm_proxy_config_set_pac_url (priv->proxy_config, pac); - _LOGD (LOGD_PROXY, "proxy: PAC url \"%s\"", pac); - } else { - nm_proxy_config_set_method (priv->proxy_config, NM_PROXY_CONFIG_METHOD_NONE); - _LOGD (LOGD_PROXY, "proxy: PAC url not obtained from DHCP server"); - } - } + if (pac_url) { + nm_proxy_config_set_method (priv->proxy_config, NM_PROXY_CONFIG_METHOD_AUTO); + nm_proxy_config_set_pac_url (priv->proxy_config, pac_url); + _LOGD (LOGD_PROXY, "proxy: PAC url \"%s\"", pac_url); + } else + nm_proxy_config_set_method (priv->proxy_config, NM_PROXY_CONFIG_METHOD_NONE); connection = nm_device_get_applied_connection (self); if (connection) @@ -9165,14 +9698,13 @@ nm_device_set_ip4_config (NMDevice *self, NMIP4Config *new_config, guint32 default_route_metric, gboolean commit, - gboolean routes_full_sync, - NMDeviceStateReason *reason) + gboolean routes_full_sync) { NMDevicePrivate *priv; NMIP4Config *old_config = NULL; gboolean has_changes = FALSE; gboolean success = TRUE; - NMDeviceStateReason reason_local = NM_DEVICE_STATE_REASON_NONE; + gboolean def_route_changed; int ip_ifindex, config_ifindex; g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); @@ -9193,17 +9725,18 @@ nm_device_set_ip4_config (NMDevice *self, /* Always commit to nm-platform to update lifetimes */ if (commit && new_config) { - gboolean assumed = nm_device_uses_assumed_connection (self); + gboolean assumed = nm_device_sys_iface_state_is_external_or_assume (self); _commit_mtu (self, new_config); /* For assumed devices we must not touch the kernel-routes, such as the device-route. * FIXME: this is wrong in case where "assumed" means "take-over-seamlessly". In this * case, we should manage the device route, for example on new DHCP lease. */ - success = nm_ip4_config_commit (new_config, ip_ifindex, + success = nm_ip4_config_commit (new_config, + nm_device_get_platform (self), + nm_netns_get_route_manager (priv->netns), + ip_ifindex, routes_full_sync, assumed ? (gint64) -1 : (gint64) default_route_metric); - if (!success) - reason_local = NM_DEVICE_STATE_REASON_CONFIG_FAILED; } if (new_config) { @@ -9234,9 +9767,15 @@ nm_device_set_ip4_config (NMDevice *self, g_clear_object (&priv->dev_ip4_config); } - nm_default_route_manager_ip4_update_default_route (nm_default_route_manager_get (), self); + def_route_changed = nm_default_route_manager_ip4_update_default_route (nm_netns_get_default_route_manager (priv->netns), self); + concheck_periodic_update (self); + + if (!nm_device_sys_iface_state_is_external_or_assume (self)) + ip4_rp_filter_update (self); if (has_changes) { + NMSettingsConnection *settings_connection; + _update_ip4_address (self); if (old_config != priv->ip4_config) @@ -9246,25 +9785,27 @@ nm_device_set_ip4_config (NMDevice *self, if (old_config != priv->ip4_config) nm_exported_object_clear_and_unexport (&old_config); - if (nm_device_uses_generated_assumed_connection (self)) { - NMConnection *settings_connection = NM_CONNECTION (nm_device_get_settings_connection (self)); + if ( nm_device_sys_iface_state_is_external (self) + && (settings_connection = nm_device_get_settings_connection (self)) + && nm_settings_connection_get_nm_generated (settings_connection) + && nm_active_connection_get_activation_type (NM_ACTIVE_CONNECTION (priv->act_request)) == NM_ACTIVATION_TYPE_EXTERNAL) { NMSetting *s_ip4; g_object_freeze_notify (G_OBJECT (settings_connection)); - nm_connection_remove_setting (settings_connection, NM_TYPE_SETTING_IP4_CONFIG); + nm_connection_remove_setting (NM_CONNECTION (settings_connection), NM_TYPE_SETTING_IP4_CONFIG); s_ip4 = nm_ip4_config_create_setting (priv->ip4_config); - nm_connection_add_setting (settings_connection, s_ip4); + nm_connection_add_setting (NM_CONNECTION (settings_connection), s_ip4); g_object_thaw_notify (G_OBJECT (settings_connection)); } nm_device_queue_recheck_assume (self); + } else if (def_route_changed) { + _LOGD (LOGD_IP4, "ip4-config: default route changed"); + g_signal_emit (self, signals[IP4_CONFIG_CHANGED], 0, priv->ip4_config, priv->ip4_config); } - if (reason) - *reason = reason_local; - return success; } @@ -9310,7 +9851,7 @@ nm_device_replace_vpn4_config (NMDevice *self, NMIP4Config *old, NMIP4Config *co return; /* NULL to use existing configs */ - if (!ip4_config_merge_and_apply (self, NULL, TRUE, NULL)) + if (!ip4_config_merge_and_apply (self, NULL, TRUE)) _LOGW (LOGD_IP4, "failed to set VPN routes for device"); } @@ -9327,7 +9868,7 @@ nm_device_set_wwan_ip4_config (NMDevice *self, NMIP4Config *config) priv->wwan_ip4_config = g_object_ref (config); /* NULL to use existing configs */ - if (!ip4_config_merge_and_apply (self, NULL, TRUE, NULL)) + if (!ip4_config_merge_and_apply (self, NULL, TRUE)) _LOGW (LOGD_IP4, "failed to set WWAN IPv4 configuration"); } @@ -9335,14 +9876,13 @@ static gboolean nm_device_set_ip6_config (NMDevice *self, NMIP6Config *new_config, gboolean commit, - gboolean routes_full_sync, - NMDeviceStateReason *reason) + gboolean routes_full_sync) { NMDevicePrivate *priv; NMIP6Config *old_config = NULL; gboolean has_changes = FALSE; gboolean success = TRUE; - NMDeviceStateReason reason_local = NM_DEVICE_STATE_REASON_NONE; + gboolean def_route_changed; int ip_ifindex, config_ifindex; g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); @@ -9365,10 +9905,10 @@ nm_device_set_ip6_config (NMDevice *self, if (commit && new_config) { _commit_mtu (self, priv->ip4_config); success = nm_ip6_config_commit (new_config, + nm_device_get_platform (self), + nm_netns_get_route_manager (priv->netns), ip_ifindex, routes_full_sync); - if (!success) - reason_local = NM_DEVICE_STATE_REASON_CONFIG_FAILED; } if (new_config) { @@ -9393,13 +9933,16 @@ nm_device_set_ip6_config (NMDevice *self, } else if (old_config) { has_changes = TRUE; priv->ip6_config = NULL; + priv->needs_ip6_subnet = FALSE; _LOGD (LOGD_IP6, "ip6-config: clear IP6Config instance (%s)", nm_exported_object_get_path (NM_EXPORTED_OBJECT (old_config))); } - nm_default_route_manager_ip6_update_default_route (nm_default_route_manager_get (), self); + def_route_changed = nm_default_route_manager_ip6_update_default_route (nm_netns_get_default_route_manager (priv->netns), 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); @@ -9407,15 +9950,17 @@ nm_device_set_ip6_config (NMDevice *self, if (old_config != priv->ip6_config) nm_exported_object_clear_and_unexport (&old_config); - if (nm_device_uses_generated_assumed_connection (self)) { - NMConnection *settings_connection = NM_CONNECTION (nm_device_get_settings_connection (self)); + if ( nm_device_sys_iface_state_is_external (self) + && (settings_connection = nm_device_get_settings_connection (self)) + && nm_settings_connection_get_nm_generated (settings_connection) + && nm_active_connection_get_activation_type (NM_ACTIVE_CONNECTION (priv->act_request)) == NM_ACTIVATION_TYPE_EXTERNAL) { NMSetting *s_ip6; g_object_freeze_notify (G_OBJECT (settings_connection)); - nm_connection_remove_setting (settings_connection, NM_TYPE_SETTING_IP6_CONFIG); + nm_connection_remove_setting (NM_CONNECTION (settings_connection), NM_TYPE_SETTING_IP6_CONFIG); s_ip6 = nm_ip6_config_create_setting (priv->ip6_config); - nm_connection_add_setting (settings_connection, s_ip6); + nm_connection_add_setting (NM_CONNECTION (settings_connection), s_ip6); g_object_thaw_notify (G_OBJECT (settings_connection)); } @@ -9424,11 +9969,11 @@ nm_device_set_ip6_config (NMDevice *self, if (priv->ndisc) ndisc_set_router_config (priv->ndisc, self); + } else if (def_route_changed) { + _LOGD (LOGD_IP6, "ip6-config: default route changed"); + g_signal_emit (self, signals[IP6_CONFIG_CHANGED], 0, priv->ip6_config, priv->ip6_config); } - if (reason) - *reason = reason_local; - return success; } @@ -9441,7 +9986,7 @@ nm_device_replace_vpn6_config (NMDevice *self, NMIP6Config *old, NMIP6Config *co return; /* NULL to use existing configs */ - if (!ip6_config_merge_and_apply (self, TRUE, NULL)) + if (!ip6_config_merge_and_apply (self, TRUE)) _LOGW (LOGD_IP6, "failed to set VPN routes for device"); } @@ -9458,7 +10003,7 @@ nm_device_set_wwan_ip6_config (NMDevice *self, NMIP6Config *config) priv->wwan_ip6_config = g_object_ref (config); /* NULL to use existing configs */ - if (!ip6_config_merge_and_apply (self, TRUE, NULL)) + if (!ip6_config_merge_and_apply (self, TRUE)) _LOGW (LOGD_IP6, "failed to set WWAN IPv6 configuration"); } @@ -9522,13 +10067,12 @@ ip_check_pre_up (NMDevice *self) priv->dispatcher.post_state = NM_DEVICE_STATE_SECONDARIES; priv->dispatcher.post_state_reason = NM_DEVICE_STATE_REASON_NONE; - if (!nm_dispatcher_call (DISPATCHER_ACTION_PRE_UP, - nm_device_get_settings_connection (self), - nm_device_get_applied_connection (self), - self, - dispatcher_complete_proceed_state, - self, - &priv->dispatcher.call_id)) { + if (!nm_dispatcher_call_device (NM_DISPATCHER_ACTION_PRE_UP, + self, + NULL, + dispatcher_complete_proceed_state, + self, + &priv->dispatcher.call_id)) { /* Just proceed on errors */ dispatcher_complete_proceed_state (0, self); } @@ -9759,7 +10303,7 @@ nm_device_is_up (NMDevice *self) g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); ifindex = nm_device_get_ip_ifindex (self); - return ifindex > 0 ? nm_platform_link_is_up (NM_PLATFORM_GET, ifindex) : TRUE; + return ifindex > 0 ? nm_platform_link_is_up (nm_device_get_platform (self), ifindex) : TRUE; } gboolean @@ -9784,7 +10328,7 @@ nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware) if (ifindex <= 0) { /* assume success. */ } else { - if (!nm_platform_link_set_up (NM_PLATFORM_GET, ifindex, no_firmware)) + if (!nm_platform_link_set_up (nm_device_get_platform (self), ifindex, no_firmware)) return FALSE; } @@ -9798,7 +10342,7 @@ nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware) do { g_usleep (200); - if (!nm_platform_link_refresh (NM_PLATFORM_GET, ifindex)) + if (!nm_platform_link_refresh (nm_device_get_platform (self), ifindex)) return FALSE; device_is_up = nm_device_is_up (self); } while (!device_is_up && nm_utils_get_monotonic_timestamp_us () < wait_until); @@ -9837,11 +10381,11 @@ nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware) /* when the link comes up, we must restore IP configuration if necessary. */ if (priv->ip4_state == IP_DONE) { - if (!ip4_config_merge_and_apply (self, NULL, TRUE, NULL)) + if (!ip4_config_merge_and_apply (self, NULL, TRUE)) _LOGW (LOGD_IP4, "failed applying IP4 config after bringing link up"); } if (priv->ip6_state == IP_DONE) { - if (!ip6_config_merge_and_apply (self, TRUE, NULL)) + if (!ip6_config_merge_and_apply (self, TRUE)) _LOGW (LOGD_IP6, "failed applying IP6 config after bringing link up"); } @@ -9863,7 +10407,7 @@ nm_device_take_down (NMDevice *self, gboolean block) return; } - if (!nm_platform_link_set_down (NM_PLATFORM_GET, ifindex)) + if (!nm_platform_link_set_down (nm_device_get_platform (self), ifindex)) return; device_is_up = nm_device_is_up (self); @@ -9872,7 +10416,7 @@ nm_device_take_down (NMDevice *self, gboolean block) do { g_usleep (200); - if (!nm_platform_link_refresh (NM_PLATFORM_GET, ifindex)) + if (!nm_platform_link_refresh (nm_device_get_platform (self), ifindex)) return; device_is_up = nm_device_is_up (self); } while (device_is_up && nm_utils_get_monotonic_timestamp_us () < wait_until); @@ -10055,7 +10599,9 @@ update_ip4_config (NMDevice *self, gboolean initial) /* IPv4 */ g_clear_object (&priv->ext_ip4_config); - priv->ext_ip4_config = nm_ip4_config_capture (ifindex, capture_resolv_conf); + priv->ext_ip4_config = nm_ip4_config_capture (nm_device_get_platform (self), + ifindex, + capture_resolv_conf); if (priv->ext_ip4_config) { if (initial) { g_clear_object (&priv->dev_ip4_config); @@ -10094,7 +10640,7 @@ update_ip4_config (NMDevice *self, gboolean initial) if (priv->wwan_ip4_config) nm_ip4_config_subtract (priv->ext_ip4_config, priv->wwan_ip4_config); - ip4_config_merge_and_apply (self, NULL, FALSE, NULL); + ip4_config_merge_and_apply (self, NULL, FALSE); } } @@ -10147,7 +10693,7 @@ update_ip6_config (NMDevice *self, gboolean initial) /* IPv6 */ g_clear_object (&priv->ext_ip6_config); g_clear_object (&priv->ext_ip6_config_captured); - priv->ext_ip6_config_captured = nm_ip6_config_capture (ifindex, capture_resolv_conf, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); + priv->ext_ip6_config_captured = nm_ip6_config_capture (nm_device_get_platform (self), ifindex, capture_resolv_conf, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); if (priv->ext_ip6_config_captured) { priv->ext_ip6_config = nm_ip6_config_new_cloned (priv->ext_ip6_config_captured); @@ -10179,7 +10725,7 @@ update_ip6_config (NMDevice *self, gboolean initial) nm_ip6_config_subtract (priv->ext_ip6_config, priv->wwan_ip6_config); g_slist_foreach (priv->vpn6_configs, _ip6_config_subtract, priv->ext_ip6_config); - ip6_config_merge_and_apply (self, FALSE, NULL); + ip6_config_merge_and_apply (self, FALSE); } if ( priv->linklocal6_timeout_id @@ -10245,7 +10791,7 @@ queued_ip6_config_change (gpointer user_data) update_ip6_config (self, FALSE); if (priv->state < NM_DEVICE_STATE_DEACTIVATING - && nm_platform_link_get (NM_PLATFORM_GET, priv->ifindex)) { + && nm_platform_link_get (nm_device_get_platform (self), priv->ifindex)) { /* Handle DAD failures */ for (iter = priv->dad6_failed_addrs; iter; iter = g_slist_next (iter)) { NMPlatformIP6Address *addr = iter->data; @@ -10573,6 +11119,8 @@ _set_unmanaged_flags (NMDevice *self, const char *operation = NULL; char str1[512]; char str2[512]; + gboolean do_notify_has_pending_actions = FALSE; + gboolean had_pending_actions = FALSE; g_return_if_fail (NM_IS_DEVICE (self)); g_return_if_fail (flags); @@ -10608,6 +11156,11 @@ _set_unmanaged_flags (NMDevice *self, nm_assert_se (!nm_clear_g_source (&priv->queued_ip6_config_id)); priv->queued_ip6_config_id = g_idle_add (queued_ip6_config_change, self); } + + if (!priv->pending_actions) { + do_notify_has_pending_actions = TRUE; + had_pending_actions = nm_device_has_pending_action (self); + } } old_flags = priv->unmanaged_flags; @@ -10643,19 +11196,16 @@ _set_unmanaged_flags (NMDevice *self, || ( !was_managed && nm_device_get_state (self) == NM_DEVICE_STATE_UNMANAGED)); -#define _FMTX "[%s%s0x%0x/0x%x/%s" -#define _FMT(flags, mask, str) \ - _unmanaged_flags2str ((flags), (mask), str, sizeof (str)), \ - ((flags) | (mask)) ? "=" : "", \ - (flags), \ - (mask), \ - (_get_managed_by_flags (flags, mask, FALSE) \ - ? "managed" \ - : (_get_managed_by_flags (flags, mask, TRUE) \ - ? "manageable" \ - : "unmanaged")) - _LOGD (LOGD_DEVICE, "unmanaged: flags set to "_FMTX"%s, %s [%s=0x%0x]%s%s%s)", - _FMT (priv->unmanaged_flags, priv->unmanaged_mask, str1), + _LOGD (LOGD_DEVICE, "unmanaged: flags set to [%s%s0x%0x/0x%x/%s%s], %s [%s=0x%0x]%s%s%s)", + _unmanaged_flags2str (priv->unmanaged_flags, priv->unmanaged_mask, str1, sizeof (str1)), \ + (priv->unmanaged_flags | priv->unmanaged_mask) ? "=" : "", \ + (guint) priv->unmanaged_flags, \ + (guint) priv->unmanaged_mask, \ + (_get_managed_by_flags (priv->unmanaged_flags, priv->unmanaged_mask, FALSE) \ + ? "managed" \ + : (_get_managed_by_flags (priv->unmanaged_flags, priv->unmanaged_mask, TRUE) \ + ? "manageable" \ + : "unmanaged")), priv->real ? "" : "/unrealized", operation, nm_unmanaged_flags2str (flags, str2, sizeof (str2)), @@ -10665,7 +11215,10 @@ _set_unmanaged_flags (NMDevice *self, reason_to_string (reason), transition_state ? ", transition-state" : "", "")); -#undef _FMT + + if ( do_notify_has_pending_actions + && had_pending_actions != nm_device_has_pending_action (self)) + _notify (self, PROP_HAS_PENDING_ACTION); if (transition_state) { new_state = was_managed ? NM_DEVICE_STATE_UNMANAGED : NM_DEVICE_STATE_UNAVAILABLE; @@ -10762,7 +11315,7 @@ nm_device_set_unmanaged_by_user_udev (NMDevice *self) ifindex = self->_priv->ifindex; if ( ifindex <= 0 - || !nm_platform_link_get_unmanaged (NM_PLATFORM_GET, ifindex, &platform_unmanaged)) + || !nm_platform_link_get_unmanaged (nm_device_get_platform (self), ifindex, &platform_unmanaged)) return; nm_device_set_unmanaged_by_flags (self, @@ -10847,7 +11400,7 @@ nm_device_reapply_settings_immediately (NMDevice *self) nm_setting_connection_get_zone (s_con_applied)) != 0) { version_id = nm_active_connection_version_id_bump ((NMActiveConnection *) self->_priv->act_request); - _LOGD (LOGD_DEVICE, "reapply setting: zone = %s%s%s (version-id %llu)", NM_PRINT_FMT_QUOTE_STRING (zone), (long long unsigned) version_id); + _LOGD (LOGD_DEVICE, "reapply setting: zone = %s%s%s (version-id %llu)", NM_PRINT_FMT_QUOTE_STRING (zone), (unsigned long long) version_id); g_object_set (G_OBJECT (s_con_applied), NM_SETTING_CONNECTION_ZONE, zone, @@ -10859,7 +11412,7 @@ nm_device_reapply_settings_immediately (NMDevice *self) if ((metered = nm_setting_connection_get_metered (s_con_settings)) != nm_setting_connection_get_metered (s_con_applied)) { version_id = nm_active_connection_version_id_bump ((NMActiveConnection *) self->_priv->act_request); - _LOGD (LOGD_DEVICE, "reapply setting: metered = %d (version-id %llu)", (int) metered, (long long unsigned) version_id); + _LOGD (LOGD_DEVICE, "reapply setting: metered = %d (version-id %llu)", (int) metered, (unsigned long long) version_id); g_object_set (G_OBJECT (s_con_applied), NM_SETTING_CONNECTION_METERED, metered, @@ -10872,25 +11425,15 @@ nm_device_reapply_settings_immediately (NMDevice *self) void nm_device_update_firewall_zone (NMDevice *self) { - NMConnection *applied_connection; - NMSettingConnection *s_con; + NMDevicePrivate *priv; g_return_if_fail (NM_IS_DEVICE (self)); - applied_connection = nm_device_get_applied_connection (self); - if (!applied_connection) - return; + priv = NM_DEVICE_GET_PRIVATE (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_firewall_manager_add_or_change_zone (nm_firewall_manager_get (), - nm_device_get_ip_iface (self), - nm_setting_connection_get_zone (s_con), - FALSE, /* change zone */ - NULL, - NULL); - } + if ( priv->fw_state >= FIREWALL_STATE_INITIALIZED + && !nm_device_sys_iface_state_is_external (self)) + fw_change_zone (self); } void @@ -11234,7 +11777,7 @@ cp_connection_removed (NMConnectionProvider *cp, NMConnection *connection, gpoin gboolean nm_device_supports_vlans (NMDevice *self) { - return nm_platform_link_supports_vlans (NM_PLATFORM_GET, nm_device_get_ifindex (self)); + return nm_platform_link_supports_vlans (nm_device_get_platform (self), nm_device_get_ifindex (self)); } /** @@ -11340,7 +11883,16 @@ nm_device_has_pending_action (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - return !!priv->pending_actions; + if (priv->pending_actions) + return TRUE; + + if (nm_device_get_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT)) { + /* as long as the platform link is not yet initialized, we have a pending + * action. */ + return TRUE; + } + + return FALSE; } /*****************************************************************************/ @@ -11350,13 +11902,12 @@ _cancel_activation (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - /* Clean up when device was deactivated during call to firewall */ if (priv->fw_call) { nm_firewall_manager_cancel_call (priv->fw_call); - g_warn_if_fail (!priv->fw_call); + nm_assert (!priv->fw_call); priv->fw_call = NULL; + priv->fw_state = FIREWALL_STATE_INITIALIZED; } - priv->fw_ready = FALSE; ip_check_gw_ping_cleanup (self); @@ -11368,20 +11919,22 @@ _cancel_activation (NMDevice *self) static void _cleanup_generic_pre (NMDevice *self, CleanupType cleanup_type) { - NMConnection *connection; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); _cancel_activation (self); - connection = nm_device_get_applied_connection (self); if ( cleanup_type == CLEANUP_TYPE_DECONFIGURE - && connection - && !nm_device_uses_generated_assumed_connection (self)) { - nm_firewall_manager_remove_from_zone (nm_firewall_manager_get (), + && priv->fw_state >= FIREWALL_STATE_INITIALIZED + && priv->fw_mgr + && !nm_device_sys_iface_state_is_external (self)) { + nm_firewall_manager_remove_from_zone (priv->fw_mgr, nm_device_get_ip_iface (self), NULL, NULL, NULL); } + priv->fw_state = FIREWALL_STATE_UNMANAGED; + g_clear_object (&priv->fw_mgr); queued_state_clear (self); @@ -11412,8 +11965,8 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type) /* Clean up IP configs; this does not actually deconfigure the * interface; the caller must flush routes and addresses explicitly. */ - nm_device_set_ip4_config (self, NULL, 0, TRUE, TRUE, NULL); - nm_device_set_ip6_config (self, NULL, TRUE, TRUE, NULL); + nm_device_set_ip4_config (self, NULL, 0, TRUE, TRUE); + nm_device_set_ip6_config (self, NULL, TRUE, TRUE); g_clear_object (&priv->proxy_config); g_clear_object (&priv->con_ip4_config); g_clear_object (&priv->dev_ip4_config); @@ -11433,7 +11986,9 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type) g_slist_free_full (priv->vpn6_configs, g_object_unref); priv->vpn6_configs = NULL; - priv->needs_ip6_subnet = FALSE; + /* We no longer accept the delegations. nm_device_set_ip6_config(NULL) + * above disables them. */ + nm_assert (priv->needs_ip6_subnet == FALSE); if (priv->act_request) { nm_active_connection_set_default (NM_ACTIVE_CONNECTION (priv->act_request), FALSE); @@ -11499,20 +12054,20 @@ nm_device_cleanup (NMDevice *self, NMDeviceStateReason reason, CleanupType clean if (NM_DEVICE_GET_CLASS (self)->deactivate) NM_DEVICE_GET_CLASS (self)->deactivate (self); - if (cleanup_type != CLEANUP_TYPE_KEEP) { + if (cleanup_type == CLEANUP_TYPE_DECONFIGURE) { /* master: release slaves */ nm_device_master_release_slaves (self); /* slave: mark no longer enslaved */ if ( priv->master - && nm_platform_link_get_master (NM_PLATFORM_GET, priv->ifindex) <= 0) + && nm_platform_link_get_master (nm_device_get_platform (self), priv->ifindex) <= 0) nm_device_master_release_one_slave (priv->master, self, FALSE, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); /* Take out any entries in the routing table and any IP address the device had. */ ifindex = nm_device_get_ip_ifindex (self); if (ifindex > 0) { - nm_route_manager_route_flush (nm_route_manager_get (), ifindex); - nm_platform_address_flush (NM_PLATFORM_GET, ifindex); + nm_route_manager_route_flush (nm_netns_get_route_manager (priv->netns), ifindex); + nm_platform_address_flush (nm_device_get_platform (self), ifindex); } } @@ -11543,7 +12098,7 @@ nm_device_cleanup (NMDevice *self, NMDeviceStateReason reason, CleanupType clean _LOGT (LOGD_DEVICE, "mtu: reset device-mtu: %u, ipv6-mtu: %u, ifindex: %d", (guint) priv->mtu_initial, (guint) priv->ip6_mtu_initial, ifindex); if (priv->mtu_initial) - nm_platform_link_set_mtu (NM_PLATFORM_GET, ifindex, priv->mtu_initial); + nm_platform_link_set_mtu (nm_device_get_platform (self), ifindex, priv->mtu_initial); if (priv->ip6_mtu_initial) { char sbuf[64]; @@ -11655,7 +12210,7 @@ nm_device_spawn_iface_helper (NMDevice *self) g_ptr_array_add (argv, g_strdup ("--dhcp4-required")); if (priv->dhcp4.client) { - const char *hostname, *fqdn; + const char *hostname; GBytes *client_id; client_id = nm_dhcp_client_get_client_id (priv->dhcp4.client); @@ -11669,15 +12224,12 @@ nm_device_spawn_iface_helper (NMDevice *self) hostname = nm_dhcp_client_get_hostname (priv->dhcp4.client); if (hostname) { - g_ptr_array_add (argv, g_strdup ("--dhcp4-hostname")); + if (nm_dhcp_client_get_use_fqdn (priv->dhcp4.client)) + g_ptr_array_add (argv, g_strdup ("--dhcp4-fqdn")); + else + g_ptr_array_add (argv, g_strdup ("--dhcp4-hostname")); g_ptr_array_add (argv, g_strdup (hostname)); } - - fqdn = nm_dhcp_client_get_fqdn (priv->dhcp4.client); - if (fqdn) { - g_ptr_array_add (argv, g_strdup ("--dhcp4-fqdn")); - g_ptr_array_add (argv, g_strdup (fqdn)); - } } configured = TRUE; @@ -11788,9 +12340,8 @@ deactivate_async_ready (NMDevice *self, if ( g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) || (priv->deactivating_cancellable && g_cancellable_is_cancelled (priv->deactivating_cancellable))) { _LOGW (LOGD_DEVICE, "Deactivation cancelled"); - } - /* In every other case, transition to the DISCONNECTED state */ - else { + } else { + /* In every other case, transition to the DISCONNECTED state */ if (error) { _LOGW (LOGD_DEVICE, "Deactivation failed: %s", error->message); @@ -11818,11 +12369,8 @@ deactivate_dispatcher_complete (guint call_id, gpointer user_data) priv->dispatcher.post_state = NM_DEVICE_STATE_UNKNOWN; priv->dispatcher.post_state_reason = NM_DEVICE_STATE_REASON_NONE; - if (priv->deactivating_cancellable) { + if (nm_clear_g_cancellable (&priv->deactivating_cancellable)) g_warn_if_reached (); - g_cancellable_cancel (priv->deactivating_cancellable); - g_clear_object (&priv->deactivating_cancellable); - } if ( NM_DEVICE_GET_CLASS (self)->deactivate_async && NM_DEVICE_GET_CLASS (self)->deactivate_async_finish) { @@ -11846,7 +12394,6 @@ _set_state_full (NMDevice *self, NMActRequest *req; gboolean no_firmware = FALSE; NMSettingsConnection *connection; - NMConnection *applied_connection; g_return_if_fail (NM_IS_DEVICE (self)); @@ -11897,6 +12444,15 @@ _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 + && state <= NM_DEVICE_STATE_ACTIVATED + && 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); @@ -11920,10 +12476,11 @@ _set_state_full (NMDevice *self, case NM_DEVICE_STATE_UNMANAGED: nm_device_set_firmware_missing (self, FALSE); if (old_state > NM_DEVICE_STATE_UNMANAGED) { - if (reason == NM_DEVICE_STATE_REASON_REMOVED) { - nm_device_cleanup (self, reason, CLEANUP_TYPE_REMOVED); - } else if (reason == NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED) { - nm_device_cleanup (self, reason, CLEANUP_TYPE_KEEP); + 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)) @@ -11932,17 +12489,18 @@ _set_state_full (NMDevice *self, nm_device_hw_addr_reset (self, "unmanage"); set_nm_ipv6ll (self, FALSE); restore_ip6_properties (self); + break; } } break; case NM_DEVICE_STATE_UNAVAILABLE: if (old_state == NM_DEVICE_STATE_UNMANAGED) { save_ip6_properties (self); - if (reason != NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED) + if (priv->sys_iface_state == NM_DEVICE_SYS_IFACE_STATE_MANAGED) ip6_managed_setup (self); } - if (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."); @@ -11969,7 +12527,7 @@ _set_state_full (NMDevice *self, nm_device_cleanup (self, reason, CLEANUP_TYPE_DECONFIGURE); } else if (old_state < NM_DEVICE_STATE_DISCONNECTED) { - if (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. */ @@ -11996,11 +12554,11 @@ _set_state_full (NMDevice *self, /* Reset autoconnect flag when the device is activating or connected. */ if ( state >= NM_DEVICE_STATE_PREPARE && state <= NM_DEVICE_STATE_ACTIVATED) - nm_device_set_autoconnect (self, TRUE); + nm_device_set_autoconnect_intern (self, TRUE); _notify (self, PROP_STATE); _notify (self, PROP_STATE_REASON); - g_signal_emit (self, signals[STATE_CHANGED], 0, state, old_state, reason); + g_signal_emit (self, signals[STATE_CHANGED], 0, (guint) state, (guint) old_state, (guint) reason); /* Post-process the event after internal notification */ @@ -12028,27 +12586,24 @@ _set_state_full (NMDevice *self, priv->ignore_carrier = nm_config_data_get_ignore_carrier (NM_CONFIG_GET_DATA, self); if (quitting) { - nm_dispatcher_call_sync (DISPATCHER_ACTION_PRE_DOWN, - nm_act_request_get_settings_connection (req), - nm_act_request_get_applied_connection (req), - self); + nm_dispatcher_call_device_sync (NM_DISPATCHER_ACTION_PRE_DOWN, + self, req); } else { priv->dispatcher.post_state = NM_DEVICE_STATE_DISCONNECTED; priv->dispatcher.post_state_reason = reason; - if (!nm_dispatcher_call (DISPATCHER_ACTION_PRE_DOWN, - nm_act_request_get_settings_connection (req), - nm_act_request_get_applied_connection (req), - self, - deactivate_dispatcher_complete, - self, - &priv->dispatcher.call_id)) { + if (!nm_dispatcher_call_device (NM_DISPATCHER_ACTION_PRE_DOWN, + self, + req, + deactivate_dispatcher_complete, + self, + &priv->dispatcher.call_id)) { /* Just proceed on errors */ deactivate_dispatcher_complete (0, self); } } - /* Remove config from PacRunner */ - nm_pacrunner_manager_remove (priv->pacrunner_manager, nm_device_get_ip_iface (self)); + nm_pacrunner_manager_remove_clear (priv->pacrunner_manager, + &priv->pacrunner_call_id); break; case NM_DEVICE_STATE_DISCONNECTED: if ( priv->queued_act_request @@ -12068,18 +12623,13 @@ _set_state_full (NMDevice *self, case NM_DEVICE_STATE_ACTIVATED: _LOGI (LOGD_DEVICE, "Activation: successful, device activated."); nm_device_update_metered (self); - nm_dispatcher_call (DISPATCHER_ACTION_UP, - nm_act_request_get_settings_connection (req), - nm_act_request_get_applied_connection (req), - self, NULL, NULL, NULL); - - if (priv->proxy_config) { - nm_pacrunner_manager_send (priv->pacrunner_manager, - nm_device_get_ip_iface (self), - priv->proxy_config, - priv->ip4_config, - priv->ip6_config); - } + nm_dispatcher_call_device (NM_DISPATCHER_ACTION_UP, + self, + req, + NULL, NULL, NULL); + + if (priv->proxy_config) + _pacrunner_manager_send (self); break; case NM_DEVICE_STATE_FAILED: /* Usually upon failure the activation chain is interrupted in @@ -12090,7 +12640,7 @@ _set_state_full (NMDevice *self, */ _cancel_activation (self); - if (nm_device_uses_assumed_connection (self)) { + if (nm_device_sys_iface_state_is_external_or_assume (self)) { /* Avoid tearing down assumed connection, assume it's connected */ nm_device_queue_state (self, NM_DEVICE_STATE_ACTIVATED, @@ -12121,26 +12671,11 @@ _set_state_full (NMDevice *self, nm_device_queue_state (self, NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_NONE); break; case NM_DEVICE_STATE_IP_CHECK: - /* Now that IP config has completed, check if the firewall - * zone must be set again for the IP interface. - */ - applied_connection = nm_device_get_applied_connection (self); - - if ( applied_connection - && priv->ifindex != priv->ip_ifindex - && !nm_device_uses_generated_assumed_connection (self)) { - NMSettingConnection *s_con; - const char *zone; - - s_con = nm_connection_get_setting_connection (applied_connection); - zone = nm_setting_connection_get_zone (s_con); - g_assert (!priv->fw_call); - priv->fw_call = nm_firewall_manager_add_or_change_zone (nm_firewall_manager_get (), - nm_device_get_ip_iface (self), - zone, - FALSE, - fw_change_zone_cb_ip_check, - self); + if ( priv->fw_state >= FIREWALL_STATE_INITIALIZED + && priv->ip_iface + && !nm_device_sys_iface_state_is_external (self)) { + priv->fw_state = FIREWALL_STATE_WAIT_IP_CONFIG; + fw_change_zone (self); } else nm_device_start_ip_check (self); @@ -12163,15 +12698,13 @@ _set_state_full (NMDevice *self, if ( (old_state == NM_DEVICE_STATE_ACTIVATED || old_state == NM_DEVICE_STATE_DEACTIVATING) && (state != NM_DEVICE_STATE_DEACTIVATING)) { if (quitting) { - nm_dispatcher_call_sync (DISPATCHER_ACTION_DOWN, - nm_act_request_get_settings_connection (req), - nm_act_request_get_applied_connection (req), - self); + nm_dispatcher_call_device_sync (NM_DISPATCHER_ACTION_DOWN, + self, req); } else { - nm_dispatcher_call (DISPATCHER_ACTION_DOWN, - nm_act_request_get_settings_connection (req), - nm_act_request_get_applied_connection (req), - self, NULL, NULL, NULL); + nm_dispatcher_call_device (NM_DISPATCHER_ACTION_DOWN, + self, + req, + NULL, NULL, NULL); } } @@ -12181,6 +12714,8 @@ _set_state_full (NMDevice *self, if (ip_config_valid (old_state) && !ip_config_valid (state)) notify_ip_properties (self); + concheck_periodic_update (self); + /* Dispose of the cached activation request */ if (req) g_object_unref (req); @@ -12334,7 +12869,7 @@ nm_device_update_hw_address (NMDevice *self) if (priv->ifindex <= 0) return FALSE; - hwaddr = nm_platform_link_get_address (NM_PLATFORM_GET, priv->ifindex, &hwaddrlen); + hwaddr = nm_platform_link_get_address (nm_device_get_platform (self), priv->ifindex, &hwaddrlen); if ( priv->type == NM_DEVICE_TYPE_ETHERNET && hwaddr @@ -12428,7 +12963,7 @@ nm_device_update_permanent_hw_address (NMDevice *self, gboolean force_freeze) /* the user is advised to configure stable MAC addresses for software devices via * UDEV. Thus, check whether the link is fully initialized. */ - pllink = nm_platform_link_get (NM_PLATFORM_GET, ifindex); + pllink = nm_platform_link_get (nm_device_get_platform (self), ifindex); if ( !pllink || !pllink->initialized) { if (!force_freeze) { @@ -12437,7 +12972,7 @@ nm_device_update_permanent_hw_address (NMDevice *self, gboolean force_freeze) return; } /* try to refresh the link just to give UDEV a bit more time... */ - nm_platform_link_refresh (NM_PLATFORM_GET, ifindex); + nm_platform_link_refresh (nm_device_get_platform (self), ifindex); /* maybe the MAC address changed... */ nm_device_update_hw_address (self); } else if (!priv->hw_addr_len) @@ -12451,7 +12986,7 @@ nm_device_update_permanent_hw_address (NMDevice *self, gboolean force_freeze) return; } - success_read = nm_platform_link_get_permanent_address (NM_PLATFORM_GET, ifindex, buf, &len); + success_read = nm_platform_link_get_permanent_address (nm_device_get_platform (self), ifindex, buf, &len); if (success_read && priv->hw_addr_len == len) { priv->hw_addr_perm_fake = FALSE; priv->hw_addr_perm = nm_utils_hwaddr_ntoa (buf, len); @@ -12474,7 +13009,7 @@ nm_device_update_permanent_hw_address (NMDevice *self, gboolean force_freeze) { gs_free NMConfigDeviceStateData *dev_state = NULL; - dev_state = nm_config_device_state_load (nm_config_get (), ifindex); + dev_state = nm_config_device_state_load (ifindex); if ( dev_state && dev_state->perm_hw_addr_fake && nm_utils_hwaddr_aton (dev_state->perm_hw_addr_fake, buf, priv->hw_addr_len) @@ -12639,7 +13174,7 @@ _hw_addr_set (NMDevice *self, nm_device_take_down (self, FALSE); } - plerr = nm_platform_link_set_address (NM_PLATFORM_GET, nm_device_get_ip_ifindex (self), addr_bytes, addr_len); + plerr = nm_platform_link_set_address (nm_device_get_platform (self), nm_device_get_ip_ifindex (self), addr_bytes, addr_len); success = (plerr == NM_PLATFORM_ERROR_SUCCESS); if (success) { /* MAC address succesfully changed; update the current MAC to match */ @@ -12670,7 +13205,7 @@ _hw_addr_set (NMDevice *self, poll_end = nm_utils_get_monotonic_timestamp_us () + (100 * 1000); for (;;) { - if (!nm_platform_link_refresh (NM_PLATFORM_GET, nm_device_get_ip_ifindex (self))) + if (!nm_platform_link_refresh (nm_device_get_platform (self), nm_device_get_ip_ifindex (self))) goto handle_fail; if (!nm_device_update_hw_address (self)) goto handle_wait; @@ -12739,49 +13274,92 @@ nm_device_hw_addr_set (NMDevice *self, return _hw_addr_set (self, addr, "set", detail); } -gboolean -nm_device_hw_addr_set_cloned (NMDevice *self, NMConnection *connection, gboolean is_wifi) +/* + * _hw_addr_get_cloned: + * @self: a #NMDevice + * @connection: a #NMConnection + * @is_wifi: whether the device is Wi-Fi + * @preserve: (out): whether the address must be reset to initial one + * @hwaddr: (out): the cloned MAC address to set on interface + * @hwaddr_type: (out): the type of address to set + * @hwaddr_detail: (out): the detail (origin) of address to set + * @error: (out): on return, an error or %NULL + * + * Computes the MAC to be set on a interface. On success, one of the + * following exclusive conditions are verified: + * + * - @preserve is %TRUE: the address must be reset to the initial one + * - @hwaddr is not %NULL: the given address must be set on the device + * - @hwaddr is %NULL and @preserve is %FALSE: no action needed + * + * Returns: %FALSE in case of error in determining the cloned MAC address, + * %TRUE otherwise + */ +static gboolean +_hw_addr_get_cloned (NMDevice *self, NMConnection *connection, gboolean is_wifi, + gboolean *preserve, char **hwaddr, HwAddrType *hwaddr_type, + char **hwaddr_detail, GError **error) { NMDevicePrivate *priv; - gs_free char *hw_addr_tmp = NULL; + gs_free char *addr_setting_free = NULL; gs_free char *hw_addr_generated = NULL; gs_free char *generate_mac_address_mask_tmp = NULL; const char *addr, *addr_setting; + char *addr_out; + HwAddrType type_out; g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); + g_return_val_if_fail (!error || !*error, FALSE); priv = NM_DEVICE_GET_PRIVATE (self); if (!connection) g_return_val_if_reached (FALSE); - addr = addr_setting = _get_cloned_mac_address_setting (self, connection, is_wifi, &hw_addr_tmp); + addr = addr_setting = _get_cloned_mac_address_setting (self, connection, is_wifi, &addr_setting_free); if (nm_streq (addr, NM_CLONED_MAC_PRESERVE)) { /* "preserve" means to reset the initial MAC address. */ - return nm_device_hw_addr_reset (self, addr_setting); + NM_SET_OUT (preserve, TRUE); + NM_SET_OUT (hwaddr, NULL); + NM_SET_OUT (hwaddr_type, HW_ADDR_TYPE_UNSET); + NM_SET_OUT (hwaddr_detail, g_steal_pointer (&addr_setting_free) ?: g_strdup (addr_setting)); + return TRUE; } if (nm_streq (addr, NM_CLONED_MAC_PERMANENT)) { addr = nm_device_get_permanent_hw_address (self); - if (!addr) + if (!addr) { + g_set_error_literal (error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_FAILED, + "failed to retrieve permanent address"); return FALSE; - priv->hw_addr_type = HW_ADDR_TYPE_PERMANENT; + } + addr_out = g_strdup (addr); + type_out = HW_ADDR_TYPE_PERMANENT; } else if (NM_IN_STRSET (addr, NM_CLONED_MAC_RANDOM)) { if (priv->hw_addr_type == HW_ADDR_TYPE_GENERATED) { /* hm, we already use a generate MAC address. Most certainly, that is from the same * activation request, so we should not create a new random address, instead keep * the current. */ - return TRUE; + goto out_no_action; } hw_addr_generated = nm_utils_hw_addr_gen_random_eth (nm_device_get_initial_hw_address (self), - _get_generate_mac_address_mask_setting (self, connection, is_wifi, &generate_mac_address_mask_tmp)); + _get_generate_mac_address_mask_setting (self, connection, + is_wifi, + &generate_mac_address_mask_tmp)); if (!hw_addr_generated) { - _LOGW (LOGD_DEVICE, "set-hw-addr: failed to generate %s MAC address", "random"); + g_set_error (error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_FAILED, + "failed to generate %s MAC address", "random"); return FALSE; } - priv->hw_addr_type = HW_ADDR_TYPE_GENERATED; - addr = hw_addr_generated; + + addr_out = g_steal_pointer (&hw_addr_generated); + type_out = HW_ADDR_TYPE_GENERATED; } else if (NM_IN_STRSET (addr, NM_CLONED_MAC_STABLE)) { NMUtilsStableType stable_type; const char *stable_id; @@ -12789,7 +13367,7 @@ nm_device_hw_addr_set_cloned (NMDevice *self, NMConnection *connection, gboolean if (priv->hw_addr_type == HW_ADDR_TYPE_GENERATED) { /* hm, we already use a generate MAC address. Most certainly, that is from the same * activation request, so let's skip creating the stable address anew. */ - return TRUE; + goto out_no_action; } stable_id = _get_stable_id (self, connection, &stable_type); @@ -12800,19 +13378,74 @@ nm_device_hw_addr_set_cloned (NMDevice *self, NMConnection *connection, gboolean _get_generate_mac_address_mask_setting (self, connection, is_wifi, &generate_mac_address_mask_tmp)); } if (!hw_addr_generated) { - _LOGW (LOGD_DEVICE, "set-hw-addr: failed to generate %s MAC address", "stable"); + g_set_error (error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_FAILED, + "failed to generate %s MAC address", "stable"); return FALSE; } - priv->hw_addr_type = HW_ADDR_TYPE_GENERATED; - addr = hw_addr_generated; + + addr_out = g_steal_pointer (&hw_addr_generated); + type_out = HW_ADDR_TYPE_GENERATED; } else { /* this must be a valid address. Otherwise, we shouldn't come here. */ if (!nm_utils_hwaddr_valid (addr, -1)) g_return_val_if_reached (FALSE); - priv->hw_addr_type = HW_ADDR_TYPE_EXPLICIT; + + addr_out = g_strdup (addr); + type_out = HW_ADDR_TYPE_EXPLICIT; + } + + NM_SET_OUT (preserve, FALSE); + NM_SET_OUT (hwaddr, addr_out); + NM_SET_OUT (hwaddr_type, type_out); + NM_SET_OUT (hwaddr_detail, g_steal_pointer (&addr_setting_free) ?: g_strdup (addr_setting)); + return TRUE; +out_no_action: + NM_SET_OUT (preserve, FALSE); + NM_SET_OUT (hwaddr, NULL); + NM_SET_OUT (hwaddr_type, HW_ADDR_TYPE_UNSET); + NM_SET_OUT (hwaddr_detail, NULL); + return TRUE; +} + +gboolean +nm_device_hw_addr_get_cloned (NMDevice *self, NMConnection *connection, gboolean is_wifi, + char **hwaddr, gboolean *preserve, GError **error) +{ + if (!_hw_addr_get_cloned (self, connection, is_wifi, preserve, hwaddr, NULL, NULL, error)) + return FALSE; + + return TRUE; +} + +gboolean +nm_device_hw_addr_set_cloned (NMDevice *self, NMConnection *connection, gboolean is_wifi) +{ + NMDevicePrivate *priv; + gboolean preserve = FALSE; + gs_free char *hwaddr = NULL; + gs_free char *detail = NULL; + HwAddrType type = HW_ADDR_TYPE_UNSET; + gs_free_error GError *error = NULL; + + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + priv = NM_DEVICE_GET_PRIVATE (self); + + if (!_hw_addr_get_cloned (self, connection, is_wifi, &preserve, &hwaddr, &type, &detail, &error)) { + _LOGW (LOGD_DEVICE, "set-hw-addr: %s", error->message); + return FALSE; + } + + if (preserve) + return nm_device_hw_addr_reset (self, detail); + + if (hwaddr) { + priv->hw_addr_type = type; + return _hw_addr_set (self, hwaddr, "set-cloned", detail); } - return _hw_addr_set (self, addr, "set-cloned", addr_setting); + return TRUE; } gboolean @@ -12908,11 +13541,40 @@ nm_device_spec_match_list (NMDevice *self, const GSList *specs) m = nm_match_spec_device (specs, nm_device_get_iface (self), nm_device_get_type_description (self), + nm_device_get_driver (self), + nm_device_get_driver_version (self), nm_device_get_permanent_hw_address (self), klass->get_s390_subchannels ? klass->get_s390_subchannels (self) : NULL); return m == NM_MATCH_SPEC_MATCH; } +guint +nm_device_get_supplicant_timeout (NMDevice *self) +{ + NMConnection *connection; + NMSetting8021x *s_8021x; + gs_free char *value = NULL; + gint timeout; +#define SUPPLICANT_DEFAULT_TIMEOUT 25 + + g_return_val_if_fail (NM_IS_DEVICE (self), SUPPLICANT_DEFAULT_TIMEOUT); + + connection = nm_device_get_applied_connection (self); + g_return_val_if_fail (connection, SUPPLICANT_DEFAULT_TIMEOUT); + s_8021x = nm_connection_get_setting_802_1x (connection); + if (s_8021x) { + timeout = nm_setting_802_1x_get_auth_timeout (s_8021x); + if (timeout > 0) + return timeout; + } + + value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA, + "802-1x.auth-timeout", + self); + return _nm_utils_ascii_str_to_int64 (value, 10, 1, G_MAXINT32, + SUPPLICANT_DEFAULT_TIMEOUT); +} + /*****************************************************************************/ static const char * @@ -12944,19 +13606,19 @@ nm_device_init (NMDevice *self) self->_priv = priv; + priv->netns = g_object_ref (NM_NETNS_GET); + priv->type = NM_DEVICE_TYPE_UNKNOWN; priv->capabilities = NM_DEVICE_CAP_NM_SUPPORTED; priv->state = NM_DEVICE_STATE_UNMANAGED; priv->state_reason = NM_DEVICE_STATE_REASON_NONE; priv->dhcp_timeout = 0; priv->rfkill_type = RFKILL_TYPE_UNKNOWN; - priv->autoconnect = DEFAULT_AUTOCONNECT; priv->unmanaged_flags = NM_UNMANAGED_PLATFORM_INIT; 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->pacrunner_manager = g_object_ref (nm_pacrunner_manager_get ()); + priv->sys_iface_state = NM_DEVICE_SYS_IFACE_STATE_EXTERNAL; priv->default_route.v4_is_assumed = TRUE; priv->default_route.v6_is_assumed = TRUE; @@ -12986,7 +13648,7 @@ constructor (GType type, if ( priv->iface && G_LIKELY (!nm_utils_get_testing ())) { - pllink = nm_platform_link_get_by_ifname (NM_PLATFORM_GET, priv->iface); + pllink = nm_platform_link_get_by_ifname (nm_device_get_platform (self), priv->iface); if (pllink && link_type_compatible (self, pllink->type, NULL, NULL)) { priv->ifindex = pllink->ifindex; @@ -13022,13 +13684,16 @@ constructed (GObject *object) priv->capabilities |= NM_DEVICE_GET_CLASS (self)->get_generic_capabilities (self); /* Watch for external IP config changes */ - platform = NM_PLATFORM_GET; + platform = nm_device_get_platform (self); g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, G_CALLBACK (device_ipx_changed), self); g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, G_CALLBACK (device_ipx_changed), self); g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, G_CALLBACK (device_ipx_changed), self); g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, G_CALLBACK (device_ipx_changed), self); g_signal_connect (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, G_CALLBACK (link_changed_cb), self); + g_signal_connect (nm_netns_get_route_manager (priv->netns), NM_ROUTE_MANAGER_IP4_ROUTES_CHANGED, + G_CALLBACK (ip4_routes_changed_changed_cb), self); + priv->settings = g_object_ref (NM_SETTINGS_GET); g_assert (priv->settings); @@ -13059,21 +13724,28 @@ dispose (GObject *object) _LOGD (LOGD_DEVICE, "disposing"); + nm_clear_g_cancellable (&priv->deactivating_cancellable); + _parent_set_ifindex (self, 0, FALSE); - platform = NM_PLATFORM_GET; + platform = nm_device_get_platform (self); g_signal_handlers_disconnect_by_func (platform, G_CALLBACK (device_ipx_changed), self); g_signal_handlers_disconnect_by_func (platform, G_CALLBACK (link_changed_cb), self); + g_signal_handlers_disconnect_by_func (nm_netns_get_route_manager (priv->netns), + G_CALLBACK (ip4_routes_changed_changed_cb), self); + g_slist_free_full (priv->arping.dad_list, (GDestroyNotify) nm_arping_manager_destroy); priv->arping.dad_list = NULL; arp_cleanup (self); - nm_clear_g_signal_handler (nm_config_get (), &priv->ignore_carrier_id); + nm_clear_g_signal_handler (nm_config_get (), &priv->config_changed_id); dispatcher_cleanup (self); + nm_pacrunner_manager_remove_clear (priv->pacrunner_manager, + &priv->pacrunner_call_id); g_clear_object (&priv->pacrunner_manager); _cleanup_generic_pre (self, CLEANUP_TYPE_KEEP); @@ -13169,6 +13841,8 @@ finalize (GObject *object) * and thus @settings might be unset. */ if (priv->settings) g_object_unref (priv->settings); + + g_object_unref (priv->netns); } static void @@ -13213,8 +13887,10 @@ set_property (GObject *object, guint prop_id, managed = g_value_get_boolean (value); if (managed) reason = NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED; - else + else { reason = NM_DEVICE_STATE_REASON_REMOVED; + nm_device_sys_iface_state_set (self, NM_DEVICE_SYS_IFACE_STATE_REMOVED); + } nm_device_set_unmanaged_by_flags (self, NM_UNMANAGED_USER_EXPLICIT, !managed, @@ -13222,7 +13898,7 @@ set_property (GObject *object, guint prop_id, } break; case PROP_AUTOCONNECT: - nm_device_set_autoconnect (self, g_value_get_boolean (value)); + nm_device_set_autoconnect_both (self, g_value_get_boolean (value)); break; case PROP_FIRMWARE_MISSING: /* construct-only */ @@ -13348,7 +14024,7 @@ get_property (GObject *object, guint prop_id, g_value_set_boolean (value, nm_device_get_state (self) > NM_DEVICE_STATE_UNMANAGED); break; case PROP_AUTOCONNECT: - g_value_set_boolean (value, priv->autoconnect); + g_value_set_boolean (value, nm_device_get_autoconnect (self)); break; case PROP_FIRMWARE_MISSING: g_value_set_boolean (value, priv->firmware_missing); @@ -13440,6 +14116,9 @@ get_property (GObject *object, guint prop_id, case PROP_RX_BYTES: g_value_set_uint64 (value, priv->stats.rx_bytes); break; + case PROP_CONNECTIVITY: + g_value_set_uint (value, priv->connectivity_state); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -13475,6 +14154,7 @@ nm_device_class_init (NMDeviceClass *klass) klass->have_any_ready_slaves = have_any_ready_slaves; klass->get_type_description = get_type_description; + klass->get_autoconnect_allowed = get_autoconnect_allowed; klass->can_auto_connect = can_auto_connect; klass->check_connection_compatible = check_connection_compatible; klass->check_connection_available = check_connection_available; @@ -13486,6 +14166,8 @@ nm_device_class_init (NMDeviceClass *klass) klass->unmanaged_on_quit = unmanaged_on_quit; klass->deactivate_reset_hw_addr = deactivate_reset_hw_addr; klass->parent_changed_notify = parent_changed_notify; + klass->can_reapply_change = can_reapply_change; + klass->reapply_connection = reapply_connection; obj_properties[PROP_UDI] = g_param_spec_string (NM_DEVICE_UDI, "", "", @@ -13707,6 +14389,13 @@ nm_device_class_init (NMDeviceClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + /* Connectivity */ + obj_properties[PROP_CONNECTIVITY] = + g_param_spec_uint (NM_DEVICE_CONNECTIVITY, "", "", + NM_CONNECTIVITY_UNKNOWN, NM_CONNECTIVITY_FULL, NM_CONNECTIVITY_UNKNOWN, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); signals[STATE_CHANGED] = diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index e512f2ca..be328eb6 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2005 - 2013 Red Hat, Inc. + * Copyright (C) 2005 - 2017 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ @@ -30,6 +30,34 @@ #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, + + /* the REMOVED state applies when the device is manually set to unmanaged + * or the link was externally removed. In both cases, we move the device + * to UNMANAGED state, without touching the link -- be it, because the link + * is already gone or because we want to release it (give it up). + */ + NM_DEVICE_SYS_IFACE_STATE_REMOVED, +} NMDeviceSysIfaceState; + +static inline NMDeviceStateReason +nm_device_state_reason_check (NMDeviceStateReason reason) +{ + /* the device-state-reason serves mostly informational purpse during a state + * change. In some cases however, decisions are made based on the reason. + * I tend to think that interpreting the state reason to derive some behaviors + * is confusing, because the cause and effect are so far apart. + * + * This function is here to mark source that inspects the reason to make + * a decision -- contrary to places that set the reason. Thus, by grepping + * for nm_device_state_reason_check() you can find the "effect" to a certain + * reason. + */ + return reason; +} #define NM_PENDING_ACTION_AUTOACTIVATE "autoactivate" #define NM_PENDING_ACTION_DHCP4 "dhcp4" @@ -113,6 +141,8 @@ #define NM_DEVICE_STATISTICS_TX_BYTES "tx-bytes" #define NM_DEVICE_STATISTICS_RX_BYTES "rx-bytes" +#define NM_DEVICE_CONNECTIVITY "connectivity" + #define NM_TYPE_DEVICE (nm_device_get_type ()) #define NM_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE, NMDevice)) #define NM_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE, NMDeviceClass)) @@ -243,6 +273,11 @@ typedef struct { void (* set_enabled) (NMDevice *self, gboolean enabled); + /* allow derived classes to override the result of nm_device_autoconnect_allowed(). + * If the value changes, the class should call nm_device_emit_recheck_auto_activate(), + * which emits NM_DEVICE_RECHECK_AUTO_ACTIVATE signal. */ + gboolean (* get_autoconnect_allowed) (NMDevice *self); + gboolean (* can_auto_connect) (NMDevice *self, NMConnection *connection, char **specific_object); @@ -278,19 +313,19 @@ typedef struct { GError **error); NMActStageReturn (* act_stage1_prepare) (NMDevice *self, - NMDeviceStateReason *reason); + NMDeviceStateReason *out_failure_reason); NMActStageReturn (* act_stage2_config) (NMDevice *self, - NMDeviceStateReason *reason); + NMDeviceStateReason *out_failure_reason); NMActStageReturn (* act_stage3_ip4_config_start) (NMDevice *self, NMIP4Config **out_config, - NMDeviceStateReason *reason); + NMDeviceStateReason *out_failure_reason); NMActStageReturn (* act_stage3_ip6_config_start) (NMDevice *self, NMIP6Config **out_config, - NMDeviceStateReason *reason); + NMDeviceStateReason *out_failure_reason); NMActStageReturn (* act_stage4_ip4_config_timeout) (NMDevice *self, - NMDeviceStateReason *reason); + NMDeviceStateReason *out_failure_reason); NMActStageReturn (* act_stage4_ip6_config_timeout) (NMDevice *self, - NMDeviceStateReason *reason); + NMDeviceStateReason *out_failure_reason); void (* ip4_config_pre_commit) (NMDevice *self, NMIP4Config *config); @@ -360,6 +395,17 @@ typedef struct { NMConnection * (* new_default_connection) (NMDevice *self); gboolean (* unmanaged_on_quit) (NMDevice *self); + + gboolean (* can_reapply_change) (NMDevice *self, + const char *setting_name, + NMSetting *s_old, + NMSetting *s_new, + GHashTable *diffs, + GError **error); + + void (* reapply_connection) (NMDevice *self, + NMConnection *con_old, + NMConnection *con_new); } NMDeviceClass; typedef void (*NMDeviceAuthRequestFunc) (NMDevice *device, @@ -370,6 +416,9 @@ typedef void (*NMDeviceAuthRequestFunc) (NMDevice *device, GType nm_device_get_type (void); +NMNetns *nm_device_get_netns (NMDevice *self); +NMPlatform *nm_device_get_platform (NMDevice *self); + const char * nm_device_get_udi (NMDevice *dev); const char * nm_device_get_iface (NMDevice *dev); int nm_device_get_ifindex (NMDevice *dev); @@ -458,8 +507,6 @@ gboolean nm_device_complete_connection (NMDevice *device, gboolean nm_device_check_connection_compatible (NMDevice *device, NMConnection *connection); gboolean nm_device_check_slave_connection_compatible (NMDevice *device, NMConnection *connection); -gboolean nm_device_uses_assumed_connection (NMDevice *device); - gboolean nm_device_unmanage_on_quit (NMDevice *self); gboolean nm_device_spec_match_list (NMDevice *device, const GSList *specs); @@ -564,6 +611,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, @@ -577,9 +625,16 @@ gboolean nm_device_unrealize (NMDevice *device, GError **error); gboolean nm_device_get_autoconnect (NMDevice *device); -void nm_device_set_autoconnect (NMDevice *device, gboolean autoconnect); +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); @@ -626,14 +681,31 @@ void nm_device_update_firewall_zone (NMDevice *self); void nm_device_update_metered (NMDevice *self); void nm_device_reactivate_ip4_config (NMDevice *device, NMSettingIPConfig *s_ip4_old, - NMSettingIPConfig *s_ip4_new); + NMSettingIPConfig *s_ip4_new, + gboolean force_restart); void nm_device_reactivate_ip6_config (NMDevice *device, NMSettingIPConfig *s_ip6_old, - NMSettingIPConfig *s_ip6_new); + NMSettingIPConfig *s_ip6_new, + gboolean force_restart); gboolean nm_device_update_hw_address (NMDevice *self); void nm_device_update_initial_hw_address (NMDevice *self); void nm_device_update_permanent_hw_address (NMDevice *self, gboolean force_freeze); void nm_device_update_dynamic_ip_setup (NMDevice *self); +guint nm_device_get_supplicant_timeout (NMDevice *self); +gboolean nm_device_hw_addr_get_cloned (NMDevice *self, + NMConnection *connection, + gboolean is_wifi, + char **hwaddr, + gboolean *preserve, + GError **error); + +typedef void (*NMDeviceConnectivityCallback) (NMDevice *self, + NMConnectivityState state, + gpointer user_data); +void nm_device_check_connectivity (NMDevice *self, + NMDeviceConnectivityCallback callback, + gpointer user_data); +NMConnectivityState nm_device_get_connectivity_state (NMDevice *self); #endif /* __NETWORKMANAGER_DEVICE_H__ */ diff --git a/src/devices/nm-lldp-listener.c b/src/devices/nm-lldp-listener.c index ceec6063..bfd631f0 100644 --- a/src/devices/nm-lldp-listener.c +++ b/src/devices/nm-lldp-listener.c @@ -128,6 +128,8 @@ typedef struct { int _ifindex = (self) ? NM_LLDP_LISTENER_GET_PRIVATE (self)->ifindex : 0; \ \ _nm_log (_level, _NMLOG_DOMAIN, 0, \ + nm_platform_link_get_name (NM_PLATFORM_GET, _ifindex), \ + NULL, \ "%s%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ _NMLOG_PREFIX_NAME, \ ((_ifindex > 0) \ @@ -695,7 +697,7 @@ process_lldp_neighbor (NMLldpListener *self, sd_lldp_neighbor *neighbor_sd, gboo return; } - /* ensure that we have at most MAX_NEIGHBORS entires */ + /* ensure that we have at most MAX_NEIGHBORS entries */ if ( !neigh_old /* only matters in the "add" case. */ && (g_hash_table_size (priv->lldp_neighbors) + 1 > MAX_NEIGHBORS)) { _LOGT ("process: ignore neighbor due to overall limit of %d", MAX_NEIGHBORS); diff --git a/src/devices/team/nm-device-team.c b/src/devices/team/nm-device-team.c index 28d91ab3..1c4d2ef6 100644 --- a/src/devices/team/nm-device-team.c +++ b/src/devices/team/nm-device-team.c @@ -28,6 +28,7 @@ #include <sys/wait.h> #include <teamdctl.h> #include <stdlib.h> +#include <jansson.h> #include "NetworkManagerUtils.h" #include "devices/nm-device-private.h" @@ -72,7 +73,7 @@ G_DEFINE_TYPE (NMDeviceTeam, nm_device_team, NM_TYPE_DEVICE) /*****************************************************************************/ -static gboolean teamd_start (NMDevice *device, NMSettingTeam *s_team); +static gboolean teamd_start (NMDevice *device, NMConnection *connection); /*****************************************************************************/ @@ -126,7 +127,7 @@ complete_connection (NMDevice *device, { NMSettingTeam *s_team; - nm_utils_complete_generic (NM_PLATFORM_GET, + nm_utils_complete_generic (nm_device_get_platform (device), connection, NM_SETTING_TEAM_SETTING_NAME, existing_connections, @@ -415,7 +416,7 @@ teamd_dbus_appeared (GDBusConnection *connection, success = teamd_read_config (device); if (success) nm_device_activate_schedule_stage2_device_config (device); - else if (!nm_device_uses_assumed_connection (device)) + else if (!nm_device_sys_iface_state_is_external_or_assume (device)) nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED); } } @@ -449,7 +450,7 @@ teamd_dbus_vanished (GDBusConnection *dbus_connection, NMConnection *connection = nm_device_get_applied_connection (device); g_assert (connection); - if (!teamd_start (device, nm_connection_get_setting_team (connection))) + if (!teamd_start (device, connection)) nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED); } } @@ -513,7 +514,7 @@ teamd_kill (NMDeviceTeam *self, const char *teamd_binary, GError **error) } static gboolean -teamd_start (NMDevice *device, NMSettingTeam *s_team) +teamd_start (NMDevice *device, NMConnection *connection) { NMDeviceTeam *self = NM_DEVICE_TEAM (device); NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (self); @@ -523,6 +524,12 @@ teamd_start (NMDevice *device, NMSettingTeam *s_team) gs_free char *tmp_str = NULL; const char *teamd_binary; const char *config; + nm_auto_free const char *config_free = NULL; + NMSettingTeam *s_team; + gs_free char *cloned_mac = NULL; + + s_team = nm_connection_get_setting_team (connection); + g_return_val_if_fail (s_team, FALSE); teamd_binary = nm_utils_find_helper ("teamd", NULL, NULL); if (!teamd_binary) { @@ -548,7 +555,39 @@ teamd_start (NMDevice *device, NMSettingTeam *s_team) g_ptr_array_add (argv, (gpointer) "-t"); g_ptr_array_add (argv, (gpointer) iface); - config = nm_setting_team_get_config(s_team); + config = nm_setting_team_get_config (s_team); + if (!nm_device_hw_addr_get_cloned (device, connection, FALSE, &cloned_mac, NULL, &error)) { + _LOGW (LOGD_DEVICE, "set-hw-addr: %s", error->message); + return FALSE; + } + + if (cloned_mac) { + json_t *json, *hwaddr; + json_error_t jerror; + + /* Inject the hwaddr property into the JSON configuration. + * While doing so, detect potential conflicts */ + + json = json_loads (config ?: "{}", 0, &jerror); + g_return_val_if_fail (json, FALSE); + + hwaddr = json_object_get (json, "hwaddr"); + if (hwaddr) { + if ( !json_is_string (hwaddr) + || !nm_streq0 (json_string_value (hwaddr), cloned_mac)) + _LOGW (LOGD_TEAM, "set-hw-addr: can't set team cloned-mac-address as the JSON configuration already contains \"hwaddr\""); + } else { + hwaddr = json_string (cloned_mac); + json_object_set (json, "hwaddr", hwaddr); + config = config_free = json_dumps (json, JSON_INDENT(0) | + JSON_ENSURE_ASCII | + JSON_SORT_KEYS); + _LOGD (LOGD_TEAM, "set-hw-addr: injected \"hwaddr\" \"%s\" into team configuration", cloned_mac); + json_decref (hwaddr); + } + json_decref (json); + } + if (config) { g_ptr_array_add (argv, (gpointer) "-c"); g_ptr_array_add (argv, (gpointer) config); @@ -580,23 +619,24 @@ teamd_start (NMDevice *device, NMSettingTeam *s_team) } static NMActStageReturn -act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) +act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMDeviceTeam *self = NM_DEVICE_TEAM (device); NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (self); NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; gs_free_error GError *error = NULL; NMSettingTeam *s_team; + NMConnection *connection; const char *cfg; - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - ret = NM_DEVICE_CLASS (nm_device_team_parent_class)->act_stage1_prepare (device, reason); + ret = NM_DEVICE_CLASS (nm_device_team_parent_class)->act_stage1_prepare (device, out_failure_reason); if (ret != NM_ACT_STAGE_RETURN_SUCCESS) return ret; - s_team = (NMSettingTeam *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_TEAM); - g_assert (s_team); + connection = nm_device_get_applied_connection (device); + g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); + s_team = nm_connection_get_setting_team (connection); + g_return_val_if_fail (s_team, NM_ACT_STAGE_RETURN_FAILURE); if (priv->tdc) { /* If the existing teamd config is the same as we're about to use, @@ -614,7 +654,7 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) _LOGD (LOGD_TEAM, "existing teamd config mismatch; killing existing via teamdctl"); if (!teamd_kill (self, NULL, &error)) { _LOGW (LOGD_TEAM, "existing teamd config mismatch; failed to kill existing teamd: %s", error->message); - *reason = NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED; + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED); return NM_ACT_STAGE_RETURN_FAILURE; } } @@ -623,7 +663,7 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) teamd_cleanup (device, TRUE); } - return teamd_start (device, s_team) ? + return teamd_start (device, connection) ? NM_ACT_STAGE_RETURN_POSTPONE : NM_ACT_STAGE_RETURN_FAILURE; } @@ -681,7 +721,7 @@ enslave_slave (NMDevice *device, } } } - success = nm_platform_link_enslave (NM_PLATFORM_GET, + success = nm_platform_link_enslave (nm_device_get_platform (device), nm_device_get_ip_ifindex (device), nm_device_get_ip_ifindex (slave)); nm_device_bring_up (slave, TRUE, &no_firmware); @@ -711,7 +751,7 @@ release_slave (NMDevice *device, gboolean success, no_firmware = FALSE; if (configure) { - success = nm_platform_link_release (NM_PLATFORM_GET, + success = nm_platform_link_release (nm_device_get_platform (device), nm_device_get_ip_ifindex (device), nm_device_get_ip_ifindex (slave)); @@ -746,7 +786,7 @@ create_and_realize (NMDevice *device, const char *iface = nm_device_get_iface (device); NMPlatformError plerr; - plerr = nm_platform_link_team_add (NM_PLATFORM_GET, iface, out_plink); + plerr = nm_platform_link_team_add (nm_device_get_platform (device), iface, out_plink); if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create team master interface '%s' for '%s': %s", diff --git a/src/devices/tests/test-lldp.c b/src/devices/tests/test-lldp.c index 4d25f9a6..1e600cdf 100644 --- a/src/devices/tests/test-lldp.c +++ b/src/devices/tests/test-lldp.c @@ -351,7 +351,11 @@ _test_recv_fixture_setup (TestRecvFixture *fixture, gconstpointer user_data) int fd, s; fd = open ("/dev/net/tun", O_RDWR | O_CLOEXEC); - g_assert (fd >= 0); + if (fd == -1) { + g_test_skip ("Unable to open /dev/net/tun"); + fixture->ifindex = 0; + return; + } ifr.ifr_flags = IFF_TAP | IFF_NO_PI; nm_utils_ifname_cpy (ifr.ifr_name, TEST_IFNAME); @@ -395,6 +399,11 @@ test_recv (TestRecvFixture *fixture, gconstpointer user_data) GError *error = NULL; guint sd_id; + if (fixture->ifindex == 0) { + g_test_skip ("Tun device not available"); + return; + } + listener = nm_lldp_listener_new (); g_assert (listener != NULL); g_assert (nm_lldp_listener_start (listener, fixture->ifindex, &error)); @@ -427,7 +436,8 @@ test_recv (TestRecvFixture *fixture, gconstpointer user_data) static void _test_recv_fixture_teardown (TestRecvFixture *fixture, gconstpointer user_data) { - nm_platform_link_delete (NM_PLATFORM_GET, fixture->ifindex); + if (fixture->ifindex) + nm_platform_link_delete (NM_PLATFORM_GET, fixture->ifindex); } /*****************************************************************************/ diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c index 0fdccb8a..24811931 100644 --- a/src/devices/wifi/nm-device-olpc-mesh.c +++ b/src/devices/wifi/nm-device-olpc-mesh.c @@ -148,7 +148,7 @@ complete_connection (NMDevice *device, } - nm_utils_complete_generic (NM_PLATFORM_GET, + nm_utils_complete_generic (nm_device_get_platform (device), connection, NM_SETTING_OLPC_MESH_SETTING_NAME, existing_connections, @@ -163,14 +163,14 @@ complete_connection (NMDevice *device, /*****************************************************************************/ static NMActStageReturn -act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) +act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (device); NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); NMActStageReturn ret; gboolean scanning; - ret = NM_DEVICE_CLASS (nm_device_olpc_mesh_parent_class)->act_stage1_prepare (device, reason); + ret = NM_DEVICE_CLASS (nm_device_olpc_mesh_parent_class)->act_stage1_prepare (device, out_failure_reason); if (ret != NM_ACT_STAGE_RETURN_SUCCESS) return ret; @@ -200,16 +200,18 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) static void _mesh_set_channel (NMDeviceOlpcMesh *self, guint32 channel) { + NMPlatform *platform; int ifindex = nm_device_get_ifindex (NM_DEVICE (self)); - if (nm_platform_mesh_get_channel (NM_PLATFORM_GET, ifindex) != channel) { - if (nm_platform_mesh_set_channel (NM_PLATFORM_GET, ifindex, channel)) + platform = nm_device_get_platform (NM_DEVICE (self)); + if (nm_platform_mesh_get_channel (platform, ifindex) != channel) { + if (nm_platform_mesh_set_channel (platform, ifindex, channel)) _notify (self, PROP_ACTIVE_CHANNEL); } } static NMActStageReturn -act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) +act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (device); NMConnection *connection; @@ -219,17 +221,17 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) const char *anycast_addr; connection = nm_device_get_applied_connection (device); - g_assert (connection); + g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); s_mesh = nm_connection_get_setting_olpc_mesh (connection); - g_assert (s_mesh); + g_return_val_if_fail (s_mesh, NM_ACT_STAGE_RETURN_FAILURE); channel = nm_setting_olpc_mesh_get_channel (s_mesh); if (channel != 0) _mesh_set_channel (self, channel); ssid = nm_setting_olpc_mesh_get_ssid (s_mesh); - nm_platform_mesh_set_ssid (NM_PLATFORM_GET, + nm_platform_mesh_set_ssid (nm_device_get_platform (device), nm_device_get_ifindex (device), g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid)); @@ -429,15 +431,16 @@ static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMDeviceOlpcMesh *device = NM_DEVICE_OLPC_MESH (object); - NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (device); + NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (object); + NMDevice *device = NM_DEVICE (self); + NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); switch (prop_id) { case PROP_COMPANION: nm_utils_g_value_set_object_path (value, priv->companion); break; case PROP_ACTIVE_CHANNEL: - g_value_set_uint (value, nm_platform_mesh_get_channel (NM_PLATFORM_GET, nm_device_get_ifindex (NM_DEVICE (device)))); + g_value_set_uint (value, nm_platform_mesh_get_channel (nm_device_get_platform (device), nm_device_get_ifindex (device))); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index 188ed54e..7359be96 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -63,7 +63,7 @@ _LOG_DECLARE_SELF(NMDeviceWifi); #define SCAN_RAND_MAC_ADDRESS_EXPIRE_MIN 5 -#define WIRELESS_SECRETS_TRIES "wireless-secrets-tries" +static NM_CACHED_QUARK_FCN ("wireless-secrets-tries", wireless_secrets_tries_quark) /*****************************************************************************/ @@ -119,7 +119,6 @@ typedef struct { NMDeviceWifiCapabilities capabilities; gint32 hw_addr_scan_expire; - char *hw_addr_scan; } NMDeviceWifiPrivate; struct _NMDeviceWifi @@ -152,16 +151,11 @@ static void cleanup_association_attempt (NMDeviceWifi * self, gboolean disconnect); static void supplicant_iface_state_cb (NMSupplicantInterface *iface, - guint32 new_state, - guint32 old_state, + int new_state_i, + int old_state_i, int disconnect_reason, gpointer user_data); -static void supplicant_iface_new_bss_cb (NMSupplicantInterface * iface, - const char *object_path, - GVariant *properties, - NMDeviceWifi * self); - static void supplicant_iface_bss_updated_cb (NMSupplicantInterface *iface, const char *object_path, GVariant *properties, @@ -190,14 +184,13 @@ static void ap_add_remove (NMDeviceWifi *self, NMWifiAP *ap, gboolean recheck_available_connections); -static void remove_supplicant_interface_error_handler (NMDeviceWifi *self); - static void _hw_addr_set_scanning (NMDeviceWifi *self, gboolean do_reset); /*****************************************************************************/ static void _ap_dump (NMDeviceWifi *self, + NMLogLevel log_level, const NMWifiAP *ap, const char *prefix, gint32 now_s) @@ -205,9 +198,9 @@ _ap_dump (NMDeviceWifi *self, char buf[1024]; buf[0] = '\0'; - _LOGD (LOGD_WIFI_SCAN, "wifi-ap: %-7s %s", - prefix, - nm_wifi_ap_to_string (ap, buf, sizeof (buf), now_s)); + _NMLOG (log_level, LOGD_WIFI_SCAN, "wifi-ap: %-7s %s", + prefix, + nm_wifi_ap_to_string (ap, buf, sizeof (buf), now_s)); } static void @@ -263,10 +256,6 @@ supplicant_interface_acquire (NMDeviceWifi *self) G_CALLBACK (supplicant_iface_state_cb), self); g_signal_connect (priv->sup_iface, - NM_SUPPLICANT_INTERFACE_NEW_BSS, - G_CALLBACK (supplicant_iface_new_bss_cb), - self); - g_signal_connect (priv->sup_iface, NM_SUPPLICANT_INTERFACE_BSS_UPDATED, G_CALLBACK (supplicant_iface_bss_updated_cb), self); @@ -306,8 +295,10 @@ _requested_scan_set (NMDeviceWifi *self, gboolean value) priv->requested_scan = value; if (value) nm_device_add_pending_action ((NMDevice *) self, NM_PENDING_ACTION_WIFI_SCAN, TRUE); - else + else { + nm_device_emit_recheck_auto_activate (NM_DEVICE (self)); nm_device_remove_pending_action ((NMDevice *) self, NM_PENDING_ACTION_WIFI_SCAN, TRUE); + } } static void @@ -428,7 +419,7 @@ periodic_update (NMDeviceWifi *self) guint32 new_rate; int percent; NMDeviceState state; - guint32 supplicant_state; + NMSupplicantInterfaceState supplicant_state; /* BSSID and signal strength have meaningful values only if the device * is activated and not scanning. @@ -453,14 +444,18 @@ periodic_update (NMDeviceWifi *self) if (priv->current_ap) { /* Smooth out the strength to work around crappy drivers */ - percent = nm_platform_wifi_get_quality (NM_PLATFORM_GET, ifindex); + percent = nm_platform_wifi_get_quality (nm_device_get_platform (NM_DEVICE (self)), ifindex); if (percent >= 0 || ++priv->invalid_strength_counter > 3) { - nm_wifi_ap_set_strength (priv->current_ap, (gint8) percent); + if (nm_wifi_ap_set_strength (priv->current_ap, (gint8) percent)) { +#ifdef NM_MORE_LOGGING + _ap_dump (self, LOGL_TRACE, priv->current_ap, "updated", 0); +#endif + } priv->invalid_strength_counter = 0; } } - new_rate = nm_platform_wifi_get_rate (NM_PLATFORM_GET, ifindex); + new_rate = nm_platform_wifi_get_rate (nm_device_get_platform (NM_DEVICE (self)), ifindex); if (new_rate != priv->rate) { priv->rate = new_rate; _notify (self, PROP_BITRATE); @@ -488,7 +483,9 @@ ap_add_remove (NMDeviceWifi *self, g_hash_table_insert (priv->aps, (gpointer) nm_exported_object_export ((NMExportedObject *) ap), g_object_ref (ap)); - } + _ap_dump (self, LOGL_DEBUG, ap, "added", 0); + } else + _ap_dump (self, LOGL_DEBUG, ap, "removed", 0); g_signal_emit (self, signals[signum], 0, ap); @@ -544,14 +541,14 @@ deactivate (NMDevice *device) set_current_ap (self, NULL, TRUE); /* Clear any critical protocol notification in the Wi-Fi stack */ - nm_platform_wifi_indicate_addressing_running (NM_PLATFORM_GET, ifindex, FALSE); + nm_platform_wifi_indicate_addressing_running (nm_device_get_platform (device), ifindex, FALSE); /* Ensure we're in infrastructure mode after deactivation; some devices * (usually older ones) don't scan well in adhoc mode. */ - if (nm_platform_wifi_get_mode (NM_PLATFORM_GET, ifindex) != NM_802_11_MODE_INFRA) { + if (nm_platform_wifi_get_mode (nm_device_get_platform (device), ifindex) != NM_802_11_MODE_INFRA) { nm_device_take_down (NM_DEVICE (self), TRUE); - nm_platform_wifi_set_mode (NM_PLATFORM_GET, ifindex, NM_802_11_MODE_INFRA); + nm_platform_wifi_set_mode (nm_device_get_platform (device), ifindex, NM_802_11_MODE_INFRA); nm_device_bring_up (NM_DEVICE (self), TRUE, NULL); } @@ -904,7 +901,7 @@ complete_connection (NMDevice *device, str_ssid = nm_utils_ssid_to_utf8 (ssid->data, ssid->len); - nm_utils_complete_generic (NM_PLATFORM_GET, + nm_utils_complete_generic (nm_device_get_platform (device), connection, NM_SETTING_WIRELESS_SETTING_NAME, existing_connections, @@ -955,7 +952,7 @@ is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags) { NMDeviceWifi *self = NM_DEVICE_WIFI (device); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - guint32 state; + NMSupplicantInterfaceState supplicant_state; if (!priv->enabled) return FALSE; @@ -963,15 +960,27 @@ is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags) if (!priv->sup_iface) return FALSE; - state = nm_supplicant_interface_get_state (priv->sup_iface); - if ( state < NM_SUPPLICANT_INTERFACE_STATE_READY - || state > NM_SUPPLICANT_INTERFACE_STATE_COMPLETED) + supplicant_state = nm_supplicant_interface_get_state (priv->sup_iface); + if ( supplicant_state < NM_SUPPLICANT_INTERFACE_STATE_READY + || supplicant_state > NM_SUPPLICANT_INTERFACE_STATE_COMPLETED) return FALSE; return TRUE; } static gboolean +get_autoconnect_allowed (NMDevice *device) +{ + NMDeviceWifiPrivate *priv; + + if (!NM_DEVICE_CLASS (nm_device_wifi_parent_class)->get_autoconnect_allowed (device)) + return FALSE; + + priv = NM_DEVICE_WIFI_GET_PRIVATE (NM_DEVICE_WIFI (device)); + return !priv->requested_scan; +} + +static gboolean can_auto_connect (NMDevice *device, NMConnection *connection, char **specific_object) @@ -1128,7 +1137,9 @@ _hw_addr_set_scanning (NMDeviceWifi *self, gboolean do_reset) TRUE, TRUE); if (!randomize) { - g_clear_pointer (&priv->hw_addr_scan, g_free); + /* expire the temporary MAC address used during scanning */ + priv->hw_addr_scan_expire = 0; + if (do_reset) nm_device_hw_addr_reset (device, "scanning"); return; @@ -1136,9 +1147,9 @@ _hw_addr_set_scanning (NMDeviceWifi *self, gboolean do_reset) now = nm_utils_get_monotonic_timestamp_s (); - if ( !priv->hw_addr_scan - || now >= priv->hw_addr_scan_expire) { + if (now >= priv->hw_addr_scan_expire) { gs_free char *generate_mac_address_mask = NULL; + gs_free char *hw_addr_scan = NULL; /* the random MAC address for scanning expires after a while. * @@ -1152,12 +1163,10 @@ _hw_addr_set_scanning (NMDeviceWifi *self, gboolean do_reset) device, NULL); - g_free (priv->hw_addr_scan); - priv->hw_addr_scan = nm_utils_hw_addr_gen_random_eth (nm_device_get_initial_hw_address (device), - generate_mac_address_mask); + hw_addr_scan = nm_utils_hw_addr_gen_random_eth (nm_device_get_initial_hw_address (device), + generate_mac_address_mask); + nm_device_hw_addr_set (device, hw_addr_scan, "scanning", TRUE); } - - nm_device_hw_addr_set (device, priv->hw_addr_scan, "scanning", TRUE); } static void @@ -1242,7 +1251,7 @@ static gboolean scanning_allowed (NMDeviceWifi *self) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - guint32 sup_state; + NMSupplicantInterfaceState supplicant_state; NMConnection *connection; g_return_val_if_fail (priv->sup_iface != NULL, FALSE); @@ -1274,11 +1283,11 @@ scanning_allowed (NMDeviceWifi *self) } /* Don't scan if the supplicant is busy */ - sup_state = nm_supplicant_interface_get_state (priv->sup_iface); - if ( sup_state == NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING - || sup_state == NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED - || sup_state == NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE - || sup_state == NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE + supplicant_state = nm_supplicant_interface_get_state (priv->sup_iface); + if ( supplicant_state == NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING + || supplicant_state == NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED + || supplicant_state == NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE + || supplicant_state == NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE || nm_supplicant_interface_get_scanning (priv->sup_iface)) return FALSE; @@ -1338,12 +1347,14 @@ check_scanning_allowed (NMDeviceWifi *self) static gboolean hidden_filter_func (NMSettings *settings, - NMConnection *connection, + NMSettingsConnection *connection, gpointer user_data) { NMSettingWireless *s_wifi; - s_wifi = (NMSettingWireless *) nm_connection_get_setting_wireless (connection); + if (!nm_connection_is_type (NM_CONNECTION (connection), NM_SETTING_WIRELESS_SETTING_NAME)) + return FALSE; + s_wifi = (NMSettingWireless *) nm_connection_get_setting_wireless (NM_CONNECTION (connection)); return s_wifi ? nm_setting_wireless_get_hidden (s_wifi) : FALSE; } @@ -1352,7 +1363,8 @@ build_hidden_probe_list (NMDeviceWifi *self) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); guint max_scan_ssids = nm_supplicant_interface_get_max_scan_ssids (priv->sup_iface); - GSList *connections, *iter; + gs_free NMSettingsConnection **connections = NULL; + guint i, len; GPtrArray *ssids = NULL; static GByteArray *nullssid = NULL; @@ -1360,28 +1372,31 @@ build_hidden_probe_list (NMDeviceWifi *self) if (max_scan_ssids < 2) return NULL; - /* Static wildcard SSID used for every scan */ + connections = nm_settings_get_connections_clone (nm_device_get_settings ((NMDevice *) self), + &len, + hidden_filter_func, + NULL); + if (!connections[0]) + return NULL; + + g_qsort_with_data (connections, len, sizeof (NMSettingsConnection *), nm_settings_connection_cmp_timestamp_p_with_data, NULL); + + ssids = g_ptr_array_new_full (max_scan_ssids, (GDestroyNotify) g_byte_array_unref); + + /* Add wildcard SSID using a static wildcard SSID used for every scan */ if (G_UNLIKELY (nullssid == NULL)) nullssid = g_byte_array_new (); + g_ptr_array_add (ssids, g_byte_array_ref (nullssid)); - connections = nm_settings_get_best_connections (nm_device_get_settings ((NMDevice *) self), - max_scan_ssids - 1, - NM_SETTING_WIRELESS_SETTING_NAME, - NULL, - hidden_filter_func, - NULL); - if (connections && connections->data) { - ssids = g_ptr_array_new_full (max_scan_ssids - 1, (GDestroyNotify) g_byte_array_unref); - g_ptr_array_add (ssids, g_byte_array_ref (nullssid)); /* Add wildcard SSID */ - } - - for (iter = connections; iter; iter = g_slist_next (iter)) { - NMConnection *connection = iter->data; + for (i = 0; connections[i]; i++) { NMSettingWireless *s_wifi; GBytes *ssid; GByteArray *ssid_array; - s_wifi = (NMSettingWireless *) nm_connection_get_setting_wireless (connection); + if (i >= max_scan_ssids - 1) + break; + + s_wifi = (NMSettingWireless *) nm_connection_get_setting_wireless (NM_CONNECTION (connections[i])); g_assert (s_wifi); ssid = nm_setting_wireless_get_ssid (s_wifi); g_assert (ssid); @@ -1391,7 +1406,6 @@ build_hidden_probe_list (NMDeviceWifi *self) g_bytes_get_size (ssid)); g_ptr_array_add (ssids, ssid_array); } - g_slist_free (connections); return ssids; } @@ -1424,9 +1438,7 @@ static void request_wireless_scan (NMDeviceWifi *self, gboolean force_if_scanning, GVariant *scan_options) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - gboolean backoff = FALSE; - GPtrArray *ssids = NULL; - gboolean new_scan_requested = FALSE; + gboolean request_started = FALSE; nm_clear_g_source (&priv->pending_scan_id); @@ -1436,6 +1448,8 @@ request_wireless_scan (NMDeviceWifi *self, gboolean force_if_scanning, GVariant } if (check_scanning_allowed (self)) { + gs_unref_ptrarray GPtrArray *ssids = NULL; + _LOGD (LOGD_WIFI, "wifi-scan: scanning requested"); if (scan_options) { @@ -1473,22 +1487,14 @@ request_wireless_scan (NMDeviceWifi *self, gboolean force_if_scanning, GVariant _hw_addr_set_scanning (self, FALSE); - if (nm_supplicant_interface_request_scan (priv->sup_iface, ssids)) { - /* success */ - backoff = TRUE; - _requested_scan_set (self, TRUE); - new_scan_requested = TRUE; - } - - if (ssids) - g_ptr_array_unref (ssids); + nm_supplicant_interface_request_scan (priv->sup_iface, ssids); + request_started = TRUE; } else _LOGD (LOGD_WIFI, "wifi-scan: scanning requested but not allowed at this time"); - if (!new_scan_requested) - _requested_scan_set (self, FALSE); + _requested_scan_set (self, request_started); - schedule_scan (self, backoff); + schedule_scan (self, request_started); } static gboolean @@ -1589,7 +1595,7 @@ ap_list_dump (gpointer user_data) priv->scheduled_scan_time); list = ap_list_get_sorted (self, TRUE); for (i = 0; list[i]; i++) - _ap_dump (self, list[i], "dump", now_s); + _ap_dump (self, LOGL_DEBUG, list[i], "dump", now_s); } return G_SOURCE_REMOVE; } @@ -1639,14 +1645,13 @@ try_fill_ssid_for_hidden_ap (NMDeviceWifi *self, } static void -supplicant_iface_new_bss_cb (NMSupplicantInterface *iface, - const char *object_path, - GVariant *properties, - NMDeviceWifi *self) +supplicant_iface_bss_updated_cb (NMSupplicantInterface *iface, + const char *object_path, + GVariant *properties, + NMDeviceWifi *self) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); NMDeviceState state; - NMWifiAP *ap; NMWifiAP *found_ap = NULL; const GByteArray *ssid; @@ -1661,41 +1666,41 @@ supplicant_iface_new_bss_cb (NMSupplicantInterface *iface, if (NM_DEVICE_WIFI_GET_PRIVATE (self)->mode == NM_802_11_MODE_AP) return; - ap = nm_wifi_ap_new_from_properties (object_path, properties); - if (!ap) { - _LOGD (LOGD_WIFI, "invalid AP properties received for %s", object_path); - return; - } + found_ap = get_ap_by_supplicant_path (self, object_path); + if (found_ap) { + if (!nm_wifi_ap_update_from_properties (found_ap, object_path, properties)) + return; + _ap_dump (self, LOGL_DEBUG, found_ap, "updated", 0); + } else { + gs_unref_object NMWifiAP *ap = NULL; - /* Let the manager try to fill in the SSID from seen-bssids lists */ - ssid = nm_wifi_ap_get_ssid (ap); - if (!ssid || nm_utils_is_empty_ssid (ssid->data, ssid->len)) { - /* Try to fill the SSID from the AP database */ - try_fill_ssid_for_hidden_ap (self, ap); + ap = nm_wifi_ap_new_from_properties (object_path, properties); + if (!ap) { + _LOGD (LOGD_WIFI, "invalid AP properties received for %s", object_path); + return; + } + /* Let the manager try to fill in the SSID from seen-bssids lists */ ssid = nm_wifi_ap_get_ssid (ap); - if (ssid && (nm_utils_is_empty_ssid (ssid->data, ssid->len) == FALSE)) { - /* Yay, matched it, no longer treat as hidden */ - _LOGD (LOGD_WIFI, "matched hidden AP %s => '%s'", - nm_wifi_ap_get_address (ap), nm_utils_escape_ssid (ssid->data, ssid->len)); - } else { - /* Didn't have an entry for this AP in the database */ - _LOGD (LOGD_WIFI, "failed to match hidden AP %s", - nm_wifi_ap_get_address (ap)); + if (!ssid || nm_utils_is_empty_ssid (ssid->data, ssid->len)) { + /* Try to fill the SSID from the AP database */ + try_fill_ssid_for_hidden_ap (self, ap); + + ssid = nm_wifi_ap_get_ssid (ap); + if (ssid && (nm_utils_is_empty_ssid (ssid->data, ssid->len) == FALSE)) { + /* Yay, matched it, no longer treat as hidden */ + _LOGD (LOGD_WIFI, "matched hidden AP %s => '%s'", + nm_wifi_ap_get_address (ap), nm_utils_escape_ssid (ssid->data, ssid->len)); + } else { + /* Didn't have an entry for this AP in the database */ + _LOGD (LOGD_WIFI, "failed to match hidden AP %s", + nm_wifi_ap_get_address (ap)); + } } - } - found_ap = get_ap_by_supplicant_path (self, object_path); - if (found_ap) { - _ap_dump (self, ap, "updated", 0); - nm_wifi_ap_update_from_properties (found_ap, object_path, properties); - } else { - _ap_dump (self, ap, "added", 0); ap_add_remove (self, ACCESS_POINT_ADDED, ap, TRUE); } - g_object_unref (ap); - /* Update the current AP if the supplicant notified a current BSS change * before it sent the current BSS's scan result. */ @@ -1706,32 +1711,6 @@ supplicant_iface_new_bss_cb (NMSupplicantInterface *iface, } static void -supplicant_iface_bss_updated_cb (NMSupplicantInterface *iface, - const char *object_path, - GVariant *properties, - NMDeviceWifi *self) -{ - NMDeviceState state; - NMWifiAP *ap; - - g_return_if_fail (self != NULL); - g_return_if_fail (object_path != NULL); - g_return_if_fail (properties != NULL); - - /* Ignore new APs when unavailable or unmanaged */ - state = nm_device_get_state (NM_DEVICE (self)); - if (state <= NM_DEVICE_STATE_UNAVAILABLE) - return; - - ap = get_ap_by_supplicant_path (self, object_path); - if (ap) { - _ap_dump (self, ap, "updated", 0); - nm_wifi_ap_update_from_properties (ap, object_path, properties); - schedule_ap_list_dump (self); - } -} - -static void supplicant_iface_bss_removed_cb (NMSupplicantInterface *iface, const char *object_path, NMDeviceWifi *self) @@ -1744,38 +1723,30 @@ supplicant_iface_bss_removed_cb (NMSupplicantInterface *iface, priv = NM_DEVICE_WIFI_GET_PRIVATE (self); ap = get_ap_by_supplicant_path (self, object_path); - if (ap) { - if (ap == priv->current_ap) { - /* The current AP cannot be removed (to prevent NM indicating that - * it is connected, but to nothing), but it must be removed later - * when the current AP is changed or cleared. Set 'fake' to - * indicate that this AP is now unknown to the supplicant. - */ - nm_wifi_ap_set_fake (ap, TRUE); - } else { - _ap_dump (self, ap, "removed", 0); - ap_add_remove (self, ACCESS_POINT_REMOVED, ap, TRUE); - schedule_ap_list_dump (self); - } + if (!ap) + return; + + if (ap == priv->current_ap) { + /* The current AP cannot be removed (to prevent NM indicating that + * it is connected, but to nothing), but it must be removed later + * when the current AP is changed or cleared. Set 'fake' to + * indicate that this AP is now unknown to the supplicant. + */ + if (nm_wifi_ap_set_fake (ap, TRUE)) + _ap_dump (self, LOGL_DEBUG, ap, "updated", 0); + } else { + ap_add_remove (self, ACCESS_POINT_REMOVED, ap, TRUE); + schedule_ap_list_dump (self); } } static void -remove_supplicant_timeouts (NMDeviceWifi *self) +cleanup_association_attempt (NMDeviceWifi *self, gboolean disconnect) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); nm_clear_g_source (&priv->sup_timeout_id); nm_clear_g_source (&priv->link_timeout_id); -} - -static void -cleanup_association_attempt (NMDeviceWifi *self, gboolean disconnect) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - remove_supplicant_interface_error_handler (self); - remove_supplicant_timeouts (self); if (disconnect && priv->sup_iface) nm_supplicant_interface_disconnect (priv->sup_iface); } @@ -1893,7 +1864,7 @@ link_timeout_cb (gpointer user_data) static gboolean need_new_8021x_secrets (NMDeviceWifi *self, - guint32 old_state, + NMSupplicantInterfaceState old_state, const char **setting_name) { NMSetting8021x *s_8021x; @@ -1947,7 +1918,7 @@ need_new_8021x_secrets (NMDeviceWifi *self, static gboolean need_new_wpa_psk (NMDeviceWifi *self, - guint32 old_state, + NMSupplicantInterfaceState old_state, gint disconnect_reason, const char **setting_name) { @@ -1988,8 +1959,8 @@ need_new_wpa_psk (NMDeviceWifi *self, static gboolean handle_8021x_or_psk_auth_fail (NMDeviceWifi *self, - guint32 new_state, - guint32 old_state, + NMSupplicantInterfaceState new_state, + NMSupplicantInterfaceState old_state, int disconnect_reason) { NMDevice *device = NM_DEVICE (self); @@ -2042,8 +2013,8 @@ reacquire_interface_cb (gpointer user_data) static void supplicant_iface_state_cb (NMSupplicantInterface *iface, - guint32 new_state, - guint32 old_state, + int new_state_i, + int old_state_i, int disconnect_reason, gpointer user_data) { @@ -2052,6 +2023,8 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface, NMDevice *device = NM_DEVICE (self); NMDeviceState devstate; gboolean scanning; + NMSupplicantInterfaceState new_state = new_state_i; + NMSupplicantInterfaceState old_state = old_state_i; if (new_state == old_state) return; @@ -2080,8 +2053,8 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface, nm_device_remove_pending_action (device, NM_PENDING_ACTION_WAITING_FOR_SUPPLICANT, TRUE); break; case NM_SUPPLICANT_INTERFACE_STATE_COMPLETED: - remove_supplicant_interface_error_handler (self); - remove_supplicant_timeouts (self); + nm_clear_g_source (&priv->sup_timeout_id); + nm_clear_g_source (&priv->link_timeout_id); /* If this is the initial association during device activation, * schedule the next activation stage. @@ -2171,36 +2144,21 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface, } static void -supplicant_iface_connection_error_cb (NMSupplicantInterface *iface, - const char *name, - const char *message, - NMDeviceWifi *self) +supplicant_iface_assoc_cb (NMSupplicantInterface *iface, + GError *error, + gpointer user_data) { + NMDeviceWifi *self = NM_DEVICE_WIFI (user_data); NMDevice *device = NM_DEVICE (self); - if (nm_device_is_activating (device)) { - _LOGW (LOGD_DEVICE | LOGD_WIFI, - "Activation: (wifi) supplicant association failed: %s - %s", - name, message); - + if ( error && !nm_utils_error_is_cancelled (error, TRUE) + && nm_device_is_activating (device)) { cleanup_association_attempt (self, TRUE); nm_device_queue_state (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); } } static void -remove_supplicant_interface_error_handler (NMDeviceWifi *self) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - if (priv->sup_iface) { - g_signal_handlers_disconnect_by_func (priv->sup_iface, - supplicant_iface_connection_error_cb, - self); - } -} - -static void supplicant_iface_notify_scanning_cb (NMSupplicantInterface *iface, GParamSpec *pspec, NMDeviceWifi *self) @@ -2259,7 +2217,7 @@ supplicant_iface_notify_current_bss (NMSupplicantInterface *iface, } } -static NMActStageReturn +static gboolean handle_auth_or_fail (NMDeviceWifi *self, NMActRequest *req, gboolean new_secrets) @@ -2267,35 +2225,34 @@ handle_auth_or_fail (NMDeviceWifi *self, const char *setting_name; guint32 tries; NMConnection *applied_connection; - NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; - g_return_val_if_fail (NM_IS_DEVICE_WIFI (self), NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (NM_IS_DEVICE_WIFI (self), FALSE); if (!req) { req = nm_device_get_act_request (NM_DEVICE (self)); - g_return_val_if_fail (req, NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (req, FALSE); } applied_connection = nm_act_request_get_applied_connection (req); - tries = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (applied_connection), WIRELESS_SECRETS_TRIES)); + tries = GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (applied_connection), wireless_secrets_tries_quark ())); if (tries > 3) - return NM_ACT_STAGE_RETURN_FAILURE; + return FALSE; nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE); nm_act_request_clear_secrets (req); setting_name = nm_connection_need_secrets (applied_connection, NULL); - if (setting_name) { - wifi_secrets_get_secrets (self, setting_name, - NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION - | (new_secrets ? NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW : 0)); - g_object_set_data (G_OBJECT (applied_connection), WIRELESS_SECRETS_TRIES, GUINT_TO_POINTER (++tries)); - ret = NM_ACT_STAGE_RETURN_POSTPONE; - } else + if (!setting_name) { _LOGW (LOGD_DEVICE, "Cleared secrets, but setting didn't need any secrets."); + return FALSE; + } - return ret; + wifi_secrets_get_secrets (self, setting_name, + NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION + | (new_secrets ? NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW : 0)); + g_object_set_qdata (G_OBJECT (applied_connection), wireless_secrets_tries_quark (), GUINT_TO_POINTER (++tries)); + return TRUE; } /* @@ -2364,7 +2321,7 @@ supplicant_connection_timeout_cb (gpointer user_data) if (nm_settings_connection_get_timestamp (nm_act_request_get_settings_connection (req), ×tamp)) new_secrets = !timestamp; - if (handle_auth_or_fail (self, req, new_secrets) == NM_ACT_STAGE_RETURN_POSTPONE) + if (handle_auth_or_fail (self, req, new_secrets)) _LOGW (LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi) asking for new secrets"); else { nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, @@ -2417,7 +2374,7 @@ build_supplicant_config (NMDeviceWifi *self, if (s_wireless_sec) { NMSetting8021x *s_8021x; const char *con_uuid = nm_connection_get_uuid (connection); - guint32 mtu = nm_platform_link_get_mtu (NM_PLATFORM_GET, + guint32 mtu = nm_platform_link_get_mtu (nm_device_get_platform (NM_DEVICE (self)), nm_device_get_ifindex (NM_DEVICE (self))); g_assert (con_uuid); @@ -2448,7 +2405,7 @@ error: /*****************************************************************************/ static NMActStageReturn -act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) +act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMDeviceWifi *self = NM_DEVICE_WIFI (device); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); @@ -2460,18 +2417,18 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) const char *mode; const char *ap_path; - ret = NM_DEVICE_CLASS (nm_device_wifi_parent_class)->act_stage1_prepare (device, reason); + ret = NM_DEVICE_CLASS (nm_device_wifi_parent_class)->act_stage1_prepare (device, out_failure_reason); if (ret != NM_ACT_STAGE_RETURN_SUCCESS) return ret; req = nm_device_get_act_request (NM_DEVICE (self)); - g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (req, NM_ACT_STAGE_RETURN_FAILURE); connection = nm_act_request_get_applied_connection (req); - g_return_val_if_fail (connection != NULL, NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); s_wireless = nm_connection_get_setting_wireless (connection); - g_assert (s_wireless); + g_return_val_if_fail (s_wireless, NM_ACT_STAGE_RETURN_FAILURE); mode = nm_setting_wireless_get_mode (s_wireless); if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_INFRA) == 0) @@ -2492,12 +2449,12 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) */ if (is_adhoc_wpa (connection)) { _LOGW (LOGD_WIFI, "Ad-Hoc WPA disabled due to kernel bugs"); - *reason = NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED; + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED); return NM_ACT_STAGE_RETURN_FAILURE; } - /* forget the temporary MAC address used during scanning */ - g_clear_pointer (&priv->hw_addr_scan, g_free); + /* expire the temporary MAC address used during scanning */ + priv->hw_addr_scan_expire = 0; /* Set spoof MAC to the interface */ if (!nm_device_hw_addr_set_cloned (device, connection, TRUE)) @@ -2549,6 +2506,7 @@ ensure_hotspot_frequency (NMDeviceWifi *self, NMSettingWireless *s_wifi, NMWifiAP *ap) { + NMDevice *device = NM_DEVICE (self); const char *band = nm_setting_wireless_get_band (s_wifi); const guint32 a_freqs[] = { 5180, 5200, 5220, 5745, 5765, 5785, 5805, 0 }; const guint32 bg_freqs[] = { 2412, 2437, 2462, 2472, 0 }; @@ -2560,14 +2518,15 @@ ensure_hotspot_frequency (NMDeviceWifi *self, return; if (g_strcmp0 (band, "a") == 0) - freq = nm_platform_wifi_find_frequency (NM_PLATFORM_GET, nm_device_get_ifindex (NM_DEVICE (self)), a_freqs); + freq = nm_platform_wifi_find_frequency (nm_device_get_platform (device), nm_device_get_ifindex (device), a_freqs); else - freq = nm_platform_wifi_find_frequency (NM_PLATFORM_GET, nm_device_get_ifindex (NM_DEVICE (self)), bg_freqs); + freq = nm_platform_wifi_find_frequency (nm_device_get_platform (device), nm_device_get_ifindex (device), bg_freqs); if (!freq) freq = (g_strcmp0 (band, "a") == 0) ? 5180 : 2462; - nm_wifi_ap_set_freq (ap, freq); + if (nm_wifi_ap_set_freq (ap, freq)) + _ap_dump (self, LOGL_DEBUG, ap, "updated", 0); } static void @@ -2592,18 +2551,18 @@ set_powersave (NMDevice *device) NM_SETTING_WIRELESS_POWERSAVE_IGNORE); } - _LOGT (LOGD_WIFI, "powersave is set to %u", (unsigned int) powersave); + _LOGT (LOGD_WIFI, "powersave is set to %u", (unsigned) powersave); if (powersave == NM_SETTING_WIRELESS_POWERSAVE_IGNORE) return; - nm_platform_wifi_set_powersave (NM_PLATFORM_GET, + nm_platform_wifi_set_powersave (nm_device_get_platform (device), nm_device_get_ifindex (device), powersave == NM_SETTING_WIRELESS_POWERSAVE_ENABLE); } static NMActStageReturn -act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) +act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMDeviceWifi *self = NM_DEVICE_WIFI (device); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); @@ -2615,17 +2574,17 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) const char *setting_name; NMSettingWireless *s_wireless; GError *error = NULL; + guint timeout; - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - remove_supplicant_timeouts (self); + nm_clear_g_source (&priv->sup_timeout_id); + nm_clear_g_source (&priv->link_timeout_id); req = nm_device_get_act_request (device); - g_assert (req); + g_return_val_if_fail (req, NM_ACT_STAGE_RETURN_FAILURE); ap = priv->current_ap; if (!ap) { - *reason = NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED; + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); goto out; } @@ -2642,9 +2601,12 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) "Activation: (wifi) access point '%s' has security, but secrets are required.", nm_connection_get_id (connection)); - ret = handle_auth_or_fail (self, req, FALSE); - if (ret == NM_ACT_STAGE_RETURN_FAILURE) - *reason = NM_DEVICE_STATE_REASON_NO_SECRETS; + if (handle_auth_or_fail (self, req, FALSE)) + ret = NM_ACT_STAGE_RETURN_POSTPONE; + else { + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_NO_SECRETS); + ret = NM_ACT_STAGE_RETURN_FAILURE; + } goto out; } @@ -2678,27 +2640,18 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) "Activation: (wifi) couldn't build wireless configuration: %s", error->message); g_clear_error (&error); - *reason = NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED; + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED); goto out; } - /* Hook up error signal handler to capture association errors */ - g_signal_connect (priv->sup_iface, - NM_SUPPLICANT_INTERFACE_CONNECTION_ERROR, - G_CALLBACK (supplicant_iface_connection_error_cb), - self); - - if (!nm_supplicant_interface_set_config (priv->sup_iface, config, &error)) { - _LOGE (LOGD_DEVICE | LOGD_WIFI, - "Activation: (wifi) couldn't send wireless configuration to the supplicant: %s", - error->message); - g_clear_error (&error); - *reason = NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED; - goto out; - } + nm_supplicant_interface_assoc (priv->sup_iface, config, + supplicant_iface_assoc_cb, self); - /* Set up a timeout on the association attempt to fail after 25 seconds */ - priv->sup_timeout_id = g_timeout_add_seconds (25, supplicant_connection_timeout_cb, self); + /* Set up a timeout on the association attempt */ + timeout = nm_device_get_supplicant_timeout (NM_DEVICE (self)); + priv->sup_timeout_id = g_timeout_add_seconds (timeout, + supplicant_connection_timeout_cb, + self); if (!priv->periodic_source_id) priv->periodic_source_id = g_timeout_add_seconds (6, periodic_update_cb, self); @@ -2722,36 +2675,38 @@ out: static NMActStageReturn act_stage3_ip4_config_start (NMDevice *device, NMIP4Config **out_config, - NMDeviceStateReason *reason) + NMDeviceStateReason *out_failure_reason) { NMConnection *connection; NMSettingIPConfig *s_ip4; const char *method = NM_SETTING_IP4_CONFIG_METHOD_AUTO; connection = nm_device_get_applied_connection (device); - g_assert (connection); + g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); + s_ip4 = nm_connection_get_setting_ip4_config (connection); if (s_ip4) method = nm_setting_ip_config_get_method (s_ip4); /* Indicate that a critical protocol is about to start */ if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0) - nm_platform_wifi_indicate_addressing_running (NM_PLATFORM_GET, nm_device_get_ifindex (device), TRUE); + nm_platform_wifi_indicate_addressing_running (nm_device_get_platform (device), nm_device_get_ifindex (device), TRUE); - return NM_DEVICE_CLASS (nm_device_wifi_parent_class)->act_stage3_ip4_config_start (device, out_config, reason); + return NM_DEVICE_CLASS (nm_device_wifi_parent_class)->act_stage3_ip4_config_start (device, out_config, out_failure_reason); } static NMActStageReturn act_stage3_ip6_config_start (NMDevice *device, NMIP6Config **out_config, - NMDeviceStateReason *reason) + NMDeviceStateReason *out_failure_reason) { NMConnection *connection; NMSettingIPConfig *s_ip6; const char *method = NM_SETTING_IP6_CONFIG_METHOD_AUTO; connection = nm_device_get_applied_connection (device); - g_assert (connection); + g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); + s_ip6 = nm_connection_get_setting_ip6_config (connection); if (s_ip6) method = nm_setting_ip_config_get_method (s_ip6); @@ -2759,9 +2714,9 @@ act_stage3_ip6_config_start (NMDevice *device, /* Indicate that a critical protocol is about to start */ if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0 || strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0) - nm_platform_wifi_indicate_addressing_running (NM_PLATFORM_GET, nm_device_get_ifindex (device), TRUE); + nm_platform_wifi_indicate_addressing_running (nm_device_get_platform (device), nm_device_get_ifindex (device), TRUE); - return NM_DEVICE_CLASS (nm_device_wifi_parent_class)->act_stage3_ip6_config_start (device, out_config, reason); + return NM_DEVICE_CLASS (nm_device_wifi_parent_class)->act_stage3_ip6_config_start (device, out_config, out_failure_reason); } static guint32 @@ -2818,7 +2773,7 @@ handle_ip_config_timeout (NMDeviceWifi *self, NMConnection *connection, gboolean may_fail, gboolean *chain_up, - NMDeviceStateReason *reason) + NMDeviceStateReason *out_failure_reason) { NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; @@ -2826,7 +2781,7 @@ handle_ip_config_timeout (NMDeviceWifi *self, if (NM_DEVICE_WIFI_GET_PRIVATE (self)->mode == NM_802_11_MODE_AP) { *chain_up = TRUE; - return ret; + return NM_ACT_STAGE_RETURN_FAILURE; } /* If IP configuration times out and it's a static WEP connection, that @@ -2842,12 +2797,13 @@ handle_ip_config_timeout (NMDeviceWifi *self, "Activation: (wifi) could not get IP configuration for connection '%s'.", nm_connection_get_id (connection)); - ret = handle_auth_or_fail (self, NULL, TRUE); - if (ret == NM_ACT_STAGE_RETURN_POSTPONE) { + if (handle_auth_or_fail (self, NULL, TRUE)) { _LOGI (LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi) asking for new secrets"); + ret = NM_ACT_STAGE_RETURN_POSTPONE; } else { - *reason = NM_DEVICE_STATE_REASON_NO_SECRETS; + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_NO_SECRETS); + ret = NM_ACT_STAGE_RETURN_FAILURE; } } else { /* Not static WEP or failure allowed; let superclass handle it */ @@ -2859,7 +2815,7 @@ handle_ip_config_timeout (NMDeviceWifi *self, static NMActStageReturn -act_stage4_ip4_config_timeout (NMDevice *device, NMDeviceStateReason *reason) +act_stage4_ip4_config_timeout (NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMConnection *connection; NMSettingIPConfig *s_ip4; @@ -2867,20 +2823,20 @@ act_stage4_ip4_config_timeout (NMDevice *device, NMDeviceStateReason *reason) NMActStageReturn ret; connection = nm_device_get_applied_connection (device); - g_assert (connection); + g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); s_ip4 = nm_connection_get_setting_ip4_config (connection); may_fail = nm_setting_ip_config_get_may_fail (s_ip4); - ret = handle_ip_config_timeout (NM_DEVICE_WIFI (device), connection, may_fail, &chain_up, reason); + ret = handle_ip_config_timeout (NM_DEVICE_WIFI (device), connection, may_fail, &chain_up, out_failure_reason); if (chain_up) - ret = NM_DEVICE_CLASS (nm_device_wifi_parent_class)->act_stage4_ip4_config_timeout (device, reason); + ret = NM_DEVICE_CLASS (nm_device_wifi_parent_class)->act_stage4_ip4_config_timeout (device, out_failure_reason); return ret; } static NMActStageReturn -act_stage4_ip6_config_timeout (NMDevice *device, NMDeviceStateReason *reason) +act_stage4_ip6_config_timeout (NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMConnection *connection; NMSettingIPConfig *s_ip6; @@ -2888,14 +2844,14 @@ act_stage4_ip6_config_timeout (NMDevice *device, NMDeviceStateReason *reason) NMActStageReturn ret; connection = nm_device_get_applied_connection (device); - g_assert (connection); + g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); s_ip6 = nm_connection_get_setting_ip6_config (connection); may_fail = nm_setting_ip_config_get_may_fail (s_ip6); - ret = handle_ip_config_timeout (NM_DEVICE_WIFI (device), connection, may_fail, &chain_up, reason); + ret = handle_ip_config_timeout (NM_DEVICE_WIFI (device), connection, may_fail, &chain_up, out_failure_reason); if (chain_up) - ret = NM_DEVICE_CLASS (nm_device_wifi_parent_class)->act_stage4_ip6_config_timeout (device, reason); + ret = NM_DEVICE_CLASS (nm_device_wifi_parent_class)->act_stage4_ip6_config_timeout (device, out_failure_reason); return ret; } @@ -2915,10 +2871,10 @@ activation_success_handler (NMDevice *device) applied_connection = nm_act_request_get_applied_connection (req); /* Clear any critical protocol notification in the wifi stack */ - nm_platform_wifi_indicate_addressing_running (NM_PLATFORM_GET, ifindex, FALSE); + nm_platform_wifi_indicate_addressing_running (nm_device_get_platform (device), ifindex, FALSE); /* Clear wireless secrets tries on success */ - g_object_set_data (G_OBJECT (applied_connection), WIRELESS_SECRETS_TRIES, NULL); + g_object_set_qdata (G_OBJECT (applied_connection), wireless_secrets_tries_quark (), NULL); /* There should always be a current AP, either a fake one because we haven't * seen a scan result for the activated AP yet, or a real one from the @@ -2927,6 +2883,8 @@ activation_success_handler (NMDevice *device) g_warn_if_fail (priv->current_ap); if (priv->current_ap) { if (nm_wifi_ap_get_fake (priv->current_ap)) { + gboolean ap_changed = FALSE; + /* If the activation AP hasn't been seen by the supplicant in a scan * yet, it will be "fake". This usually happens for Ad-Hoc and * AP-mode connections. Fill in the details from the device itself @@ -2936,16 +2894,19 @@ activation_success_handler (NMDevice *device) guint8 bssid[ETH_ALEN] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; gs_free char *bssid_str = NULL; - if ( nm_platform_wifi_get_bssid (NM_PLATFORM_GET, ifindex, bssid) + if ( nm_platform_wifi_get_bssid (nm_device_get_platform (device), ifindex, bssid) && nm_ethernet_address_is_valid (bssid, ETH_ALEN)) { bssid_str = nm_utils_hwaddr_ntoa (bssid, ETH_ALEN); - nm_wifi_ap_set_address (priv->current_ap, bssid_str); + ap_changed |= nm_wifi_ap_set_address (priv->current_ap, bssid_str); } } if (!nm_wifi_ap_get_freq (priv->current_ap)) - nm_wifi_ap_set_freq (priv->current_ap, nm_platform_wifi_get_frequency (NM_PLATFORM_GET, ifindex)); + ap_changed |= nm_wifi_ap_set_freq (priv->current_ap, nm_platform_wifi_get_frequency (nm_device_get_platform (device), ifindex)); if (!nm_wifi_ap_get_max_bitrate (priv->current_ap)) - nm_wifi_ap_set_max_bitrate (priv->current_ap, nm_platform_wifi_get_rate (NM_PLATFORM_GET, ifindex)); + ap_changed |= nm_wifi_ap_set_max_bitrate (priv->current_ap, nm_platform_wifi_get_rate (nm_device_get_platform (device), ifindex)); + + if (ap_changed) + _ap_dump (self, LOGL_DEBUG, priv->current_ap, "updated", 0); } nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req), @@ -2969,10 +2930,10 @@ activation_failure_handler (NMDevice *device) g_assert (applied_connection); /* Clear wireless secrets tries on failure */ - g_object_set_data (G_OBJECT (applied_connection), WIRELESS_SECRETS_TRIES, NULL); + g_object_set_qdata (G_OBJECT (applied_connection), wireless_secrets_tries_quark (), NULL); /* Clear any critical protocol notification in the wifi stack */ - nm_platform_wifi_indicate_addressing_running (NM_PLATFORM_GET, nm_device_get_ifindex (device), FALSE); + nm_platform_wifi_indicate_addressing_running (nm_device_get_platform (device), nm_device_get_ifindex (device), FALSE); } static void @@ -3023,7 +2984,7 @@ device_state_changed (NMDevice *device, break; case NM_DEVICE_STATE_IP_CHECK: /* Clear any critical protocol notification in the wifi stack */ - nm_platform_wifi_indicate_addressing_running (NM_PLATFORM_GET, nm_device_get_ifindex (device), FALSE); + nm_platform_wifi_indicate_addressing_running (nm_device_get_platform (device), nm_device_get_ifindex (device), FALSE); break; case NM_DEVICE_STATE_ACTIVATED: activation_success_handler (device); @@ -3106,6 +3067,33 @@ set_enabled (NMDevice *device, gboolean enabled) } } +static gboolean +can_reapply_change (NMDevice *device, + const char *setting_name, + NMSetting *s_old, + NMSetting *s_new, + GHashTable *diffs, + GError **error) +{ + NMDeviceClass *device_class; + + /* Only handle wireless setting here, delegate other settings to parent class */ + if (nm_streq (setting_name, NM_SETTING_WIRELESS_SETTING_NAME)) { + return nm_device_hash_check_invalid_keys (diffs, + NM_SETTING_WIRELESS_SETTING_NAME, + error, + NM_SETTING_WIRELESS_MTU); /* reapplied with IP config */ + } + + device_class = NM_DEVICE_CLASS (nm_device_wifi_parent_class); + return device_class->can_reapply_change (device, + setting_name, + s_old, + s_new, + diffs, + error); +} + /*****************************************************************************/ static void @@ -3233,8 +3221,6 @@ finalize (GObject *object) g_hash_table_unref (priv->aps); - g_free (priv->hw_addr_scan); - G_OBJECT_CLASS (nm_device_wifi_parent_class)->finalize (object); } @@ -3253,6 +3239,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) object_class->finalize = finalize; parent_class->can_auto_connect = can_auto_connect; + parent_class->get_autoconnect_allowed = get_autoconnect_allowed; parent_class->is_available = is_available; parent_class->check_connection_compatible = check_connection_compatible; parent_class->check_connection_available = check_connection_available; @@ -3270,6 +3257,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) parent_class->deactivate = deactivate; parent_class->deactivate_reset_hw_addr = deactivate_reset_hw_addr; parent_class->unmanaged_on_quit = unmanaged_on_quit; + parent_class->can_reapply_change = can_reapply_change; parent_class->state_changed = device_state_changed; diff --git a/src/devices/wifi/nm-wifi-ap.c b/src/devices/wifi/nm-wifi-ap.c index 96e9d19c..7de0838f 100644 --- a/src/devices/wifi/nm-wifi-ap.c +++ b/src/devices/wifi/nm-wifi-ap.c @@ -29,6 +29,7 @@ #include "NetworkManagerUtils.h" #include "nm-utils.h" #include "nm-core-internal.h" +#include "platform/nm-platform.h" #include "nm-setting-wireless.h" @@ -68,8 +69,8 @@ typedef struct { NM80211ApSecurityFlags rsn_flags; /* RSN (WPA2) -related flags */ /* Non-scanned attributes */ - bool fake; /* Whether or not the AP is from a scan */ - bool hotspot; /* Whether the AP is a local device's hotspot network */ + bool fake:1; /* Whether or not the AP is from a scan */ + bool hotspot:1; /* Whether the AP is a local device's hotspot network */ gint32 last_seen; /* Timestamp when the AP was seen lastly (obtained via nm_utils_get_monotonic_timestamp_s()) */ } NMWifiAPPrivate; @@ -122,20 +123,20 @@ const GByteArray * nm_wifi_ap_get_ssid (const NMWifiAP *ap) return NM_WIFI_AP_GET_PRIVATE (ap)->ssid; } -void +gboolean nm_wifi_ap_set_ssid (NMWifiAP *ap, const guint8 *ssid, gsize len) { NMWifiAPPrivate *priv; - g_return_if_fail (NM_IS_WIFI_AP (ap)); - g_return_if_fail (ssid == NULL || len > 0); + g_return_val_if_fail (NM_IS_WIFI_AP (ap), FALSE); + g_return_val_if_fail (ssid == NULL || len > 0, FALSE); priv = NM_WIFI_AP_GET_PRIVATE (ap); /* same SSID */ if ((ssid && priv->ssid) && (len == priv->ssid->len)) { if (!memcmp (ssid, priv->ssid->data, len)) - return; + return FALSE; } if (priv->ssid) { @@ -149,49 +150,56 @@ nm_wifi_ap_set_ssid (NMWifiAP *ap, const guint8 *ssid, gsize len) } _notify (ap, PROP_SSID); + return TRUE; } -static void +static gboolean nm_wifi_ap_set_flags (NMWifiAP *ap, NM80211ApFlags flags) { NMWifiAPPrivate *priv; - g_return_if_fail (NM_IS_WIFI_AP (ap)); + g_return_val_if_fail (NM_IS_WIFI_AP (ap), FALSE); priv = NM_WIFI_AP_GET_PRIVATE (ap); if (priv->flags != flags) { priv->flags = flags; _notify (ap, PROP_FLAGS); + return TRUE; } + return FALSE; } -static void +static gboolean nm_wifi_ap_set_wpa_flags (NMWifiAP *ap, NM80211ApSecurityFlags flags) { NMWifiAPPrivate *priv; - g_return_if_fail (NM_IS_WIFI_AP (ap)); + g_return_val_if_fail (NM_IS_WIFI_AP (ap), FALSE); priv = NM_WIFI_AP_GET_PRIVATE (ap); if (priv->wpa_flags != flags) { priv->wpa_flags = flags; _notify (ap, PROP_WPA_FLAGS); + return TRUE; } + return FALSE; } -static void +static gboolean nm_wifi_ap_set_rsn_flags (NMWifiAP *ap, NM80211ApSecurityFlags flags) { NMWifiAPPrivate *priv; - g_return_if_fail (NM_IS_WIFI_AP (ap)); + g_return_val_if_fail (NM_IS_WIFI_AP (ap), FALSE); priv = NM_WIFI_AP_GET_PRIVATE (ap); if (priv->rsn_flags != flags) { priv->rsn_flags = flags; _notify (ap, PROP_RSN_FLAGS); + return TRUE; } + return FALSE; } const char * @@ -202,25 +210,34 @@ nm_wifi_ap_get_address (const NMWifiAP *ap) return NM_WIFI_AP_GET_PRIVATE (ap)->address; } -void -nm_wifi_ap_set_address (NMWifiAP *ap, const char *addr) +static gboolean +nm_wifi_ap_set_address_bin (NMWifiAP *ap, const guint8 *addr /* ETH_ALEN bytes */) { NMWifiAPPrivate *priv; - guint8 addr_buf[ETH_ALEN]; - - g_return_if_fail (NM_IS_WIFI_AP (ap)); - if ( !addr - || !nm_utils_hwaddr_aton (addr, addr_buf, sizeof (addr_buf))) - g_return_if_reached (); priv = NM_WIFI_AP_GET_PRIVATE (ap); if ( !priv->address - || !nm_utils_hwaddr_matches (addr_buf, sizeof (addr_buf), priv->address, -1)) { + || !nm_utils_hwaddr_matches (addr, ETH_ALEN, priv->address, -1)) { g_free (priv->address); - priv->address = nm_utils_hwaddr_ntoa (addr_buf, sizeof (addr_buf)); + priv->address = nm_utils_hwaddr_ntoa (addr, ETH_ALEN); _notify (ap, PROP_HW_ADDRESS); + return TRUE; } + return FALSE; +} + +gboolean +nm_wifi_ap_set_address (NMWifiAP *ap, const char *addr) +{ + guint8 addr_buf[ETH_ALEN]; + + g_return_val_if_fail (NM_IS_WIFI_AP (ap), FALSE); + if ( !addr + || !nm_utils_hwaddr_aton (addr, addr_buf, sizeof (addr_buf))) + g_return_val_if_reached (FALSE); + + return nm_wifi_ap_set_address_bin (ap, addr_buf); } NM80211Mode @@ -231,21 +248,23 @@ nm_wifi_ap_get_mode (NMWifiAP *ap) return NM_WIFI_AP_GET_PRIVATE (ap)->mode; } -static void +static gboolean nm_wifi_ap_set_mode (NMWifiAP *ap, const NM80211Mode mode) { NMWifiAPPrivate *priv; - g_return_if_fail (NM_IS_WIFI_AP (ap)); - g_return_if_fail ( mode == NM_802_11_MODE_ADHOC - || mode == NM_802_11_MODE_INFRA); + g_return_val_if_fail (NM_IS_WIFI_AP (ap), FALSE); + g_return_val_if_fail ( mode == NM_802_11_MODE_ADHOC + || mode == NM_802_11_MODE_INFRA, FALSE); priv = NM_WIFI_AP_GET_PRIVATE (ap); if (priv->mode != mode) { priv->mode = mode; _notify (ap, PROP_MODE); + return TRUE; } + return FALSE; } gboolean @@ -264,19 +283,21 @@ nm_wifi_ap_get_strength (NMWifiAP *ap) return NM_WIFI_AP_GET_PRIVATE (ap)->strength; } -void +gboolean nm_wifi_ap_set_strength (NMWifiAP *ap, const gint8 strength) { NMWifiAPPrivate *priv; - g_return_if_fail (NM_IS_WIFI_AP (ap)); + g_return_val_if_fail (NM_IS_WIFI_AP (ap), FALSE); priv = NM_WIFI_AP_GET_PRIVATE (ap); if (priv->strength != strength) { priv->strength = strength; _notify (ap, PROP_STRENGTH); + return TRUE; } + return FALSE; } guint32 @@ -287,20 +308,22 @@ nm_wifi_ap_get_freq (NMWifiAP *ap) return NM_WIFI_AP_GET_PRIVATE (ap)->freq; } -void +gboolean nm_wifi_ap_set_freq (NMWifiAP *ap, const guint32 freq) { NMWifiAPPrivate *priv; - g_return_if_fail (NM_IS_WIFI_AP (ap)); + g_return_val_if_fail (NM_IS_WIFI_AP (ap), FALSE); priv = NM_WIFI_AP_GET_PRIVATE (ap); if (priv->freq != freq) { priv->freq = freq; _notify (ap, PROP_FREQUENCY); + return TRUE; } + return FALSE; } guint32 @@ -312,19 +335,21 @@ nm_wifi_ap_get_max_bitrate (NMWifiAP *ap) return NM_WIFI_AP_GET_PRIVATE (ap)->max_bitrate; } -void +gboolean nm_wifi_ap_set_max_bitrate (NMWifiAP *ap, guint32 bitrate) { NMWifiAPPrivate *priv; - g_return_if_fail (NM_IS_WIFI_AP (ap)); + g_return_val_if_fail (NM_IS_WIFI_AP (ap), FALSE); priv = NM_WIFI_AP_GET_PRIVATE (ap); if (priv->max_bitrate != bitrate) { priv->max_bitrate = bitrate; _notify (ap, PROP_MAX_BITRATE); + return TRUE; } + return FALSE; } gboolean @@ -335,27 +360,37 @@ nm_wifi_ap_get_fake (const NMWifiAP *ap) return NM_WIFI_AP_GET_PRIVATE (ap)->fake; } -void +gboolean nm_wifi_ap_set_fake (NMWifiAP *ap, gboolean fake) { - g_return_if_fail (NM_IS_WIFI_AP (ap)); + NMWifiAPPrivate *priv; + + g_return_val_if_fail (NM_IS_WIFI_AP (ap), FALSE); + + priv = NM_WIFI_AP_GET_PRIVATE (ap); - NM_WIFI_AP_GET_PRIVATE (ap)->fake = fake; + if (priv->fake != !!fake) { + priv->fake = fake; + return TRUE; + } + return FALSE; } -static void +static gboolean nm_wifi_ap_set_last_seen (NMWifiAP *ap, gint32 last_seen) { NMWifiAPPrivate *priv; - g_return_if_fail (NM_IS_WIFI_AP (ap)); + g_return_val_if_fail (NM_IS_WIFI_AP (ap), FALSE); priv = NM_WIFI_AP_GET_PRIVATE (ap); if (priv->last_seen != last_seen) { priv->last_seen = last_seen; _notify (ap, PROP_LAST_SEEN); + return TRUE; } + return FALSE; } /*****************************************************************************/ @@ -400,13 +435,12 @@ security_from_vardict (GVariant *security) return flags; } -void +gboolean nm_wifi_ap_update_from_properties (NMWifiAP *ap, const char *supplicant_path, GVariant *properties) { NMWifiAPPrivate *priv; - char *addr; const guint8 *bytes; GVariant *v; gsize len; @@ -414,28 +448,30 @@ nm_wifi_ap_update_from_properties (NMWifiAP *ap, const char *s; gint16 i16; guint16 u16; + gboolean changed = FALSE; + + g_return_val_if_fail (NM_IS_WIFI_AP (ap), FALSE); + g_return_val_if_fail (properties, FALSE); - g_return_if_fail (ap != NULL); - g_return_if_fail (properties != NULL); priv = NM_WIFI_AP_GET_PRIVATE (ap); g_object_freeze_notify (G_OBJECT (ap)); if (g_variant_lookup (properties, "Privacy", "b", &b) && b) - nm_wifi_ap_set_flags (ap, priv->flags | NM_802_11_AP_FLAGS_PRIVACY); + changed |= nm_wifi_ap_set_flags (ap, priv->flags | NM_802_11_AP_FLAGS_PRIVACY); if (g_variant_lookup (properties, "Mode", "&s", &s)) { if (!g_strcmp0 (s, "infrastructure")) - nm_wifi_ap_set_mode (ap, NM_802_11_MODE_INFRA); + changed |= nm_wifi_ap_set_mode (ap, NM_802_11_MODE_INFRA); else if (!g_strcmp0 (s, "ad-hoc")) - nm_wifi_ap_set_mode (ap, NM_802_11_MODE_ADHOC); + changed |= nm_wifi_ap_set_mode (ap, NM_802_11_MODE_ADHOC); } if (g_variant_lookup (properties, "Signal", "n", &i16)) - nm_wifi_ap_set_strength (ap, nm_wifi_utils_level_to_quality (i16)); + changed |= nm_wifi_ap_set_strength (ap, nm_wifi_utils_level_to_quality (i16)); if (g_variant_lookup (properties, "Frequency", "q", &u16)) - nm_wifi_ap_set_freq (ap, u16); + changed |= nm_wifi_ap_set_freq (ap, u16); v = g_variant_lookup_value (properties, "SSID", G_VARIANT_TYPE_BYTESTRING); if (v) { @@ -446,7 +482,7 @@ nm_wifi_ap_update_from_properties (NMWifiAP *ap, if ( bytes && len && !(((len == 8) || (len == 9)) && !memcmp (bytes, "<hidden>", 8)) && !nm_utils_is_empty_ssid (bytes, len)) - nm_wifi_ap_set_ssid (ap, bytes, len); + changed |= nm_wifi_ap_set_ssid (ap, bytes, len); g_variant_unref (v); } @@ -454,11 +490,10 @@ nm_wifi_ap_update_from_properties (NMWifiAP *ap, v = g_variant_lookup_value (properties, "BSSID", G_VARIANT_TYPE_BYTESTRING); if (v) { bytes = g_variant_get_fixed_array (v, &len, 1); - if (len == ETH_ALEN) { - addr = nm_utils_hwaddr_ntoa (bytes, len); - nm_wifi_ap_set_address (ap, addr); - g_free (addr); - } + if ( len == ETH_ALEN + && memcmp (bytes, nm_ip_addr_zero.addr_eth, ETH_ALEN) != 0 + && memcmp (bytes, (char[ETH_ALEN]) { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, ETH_ALEN) != 0) + changed |= nm_wifi_ap_set_address_bin (ap, bytes); g_variant_unref (v); } @@ -470,33 +505,37 @@ nm_wifi_ap_update_from_properties (NMWifiAP *ap, /* Find the max AP rate */ for (i = 0; i < len; i++) { - if (rates[i] > maxrate) { + if (rates[i] > maxrate) maxrate = rates[i]; - nm_wifi_ap_set_max_bitrate (ap, rates[i] / 1000); - } } + if (maxrate) + changed |= nm_wifi_ap_set_max_bitrate (ap, maxrate / 1000); g_variant_unref (v); } v = g_variant_lookup_value (properties, "WPA", G_VARIANT_TYPE_VARDICT); if (v) { - nm_wifi_ap_set_wpa_flags (ap, priv->wpa_flags | security_from_vardict (v)); + changed |= nm_wifi_ap_set_wpa_flags (ap, priv->wpa_flags | security_from_vardict (v)); g_variant_unref (v); } v = g_variant_lookup_value (properties, "RSN", G_VARIANT_TYPE_VARDICT); if (v) { - nm_wifi_ap_set_rsn_flags (ap, priv->rsn_flags | security_from_vardict (v)); + changed |= nm_wifi_ap_set_rsn_flags (ap, priv->rsn_flags | security_from_vardict (v)); g_variant_unref (v); } - if (!priv->supplicant_path) + if (!priv->supplicant_path) { priv->supplicant_path = g_strdup (supplicant_path); + changed = TRUE; + } - nm_wifi_ap_set_last_seen (ap, nm_utils_get_monotonic_timestamp_s ()); - priv->fake = FALSE; + changed |= nm_wifi_ap_set_last_seen (ap, nm_utils_get_monotonic_timestamp_s ()); + changed |= nm_wifi_ap_set_fake (ap, FALSE); g_object_thaw_notify (G_OBJECT (ap)); + + return changed; } static gboolean @@ -583,6 +622,7 @@ nm_wifi_ap_to_string (const NMWifiAP *self, { const NMWifiAPPrivate *priv; const char *supplicant_id = "-"; + const char *export_path; guint32 chan; char b1[200]; @@ -591,10 +631,16 @@ nm_wifi_ap_to_string (const NMWifiAP *self, priv = NM_WIFI_AP_GET_PRIVATE (self); chan = nm_utils_wifi_freq_to_channel (priv->freq); if (priv->supplicant_path) - supplicant_id = strrchr (priv->supplicant_path, '/'); + supplicant_id = strrchr (priv->supplicant_path, '/') ?: supplicant_id; + + export_path = nm_exported_object_get_path (NM_EXPORTED_OBJECT (self)); + if (export_path) + export_path = strrchr (export_path, '/') ?: export_path; + else + export_path = "/"; g_snprintf (str_buf, buf_len, - "%17s %-32s [ %c %3u %3u%% %c W:%04X R:%04X ] %3us %s", + "%17s %-32s [ %c %3u %3u%% %c W:%04X R:%04X ] %3us sup:%s [nm:%s]", priv->address ?: "(none)", nm_sprintf_buf (b1, "%s%s%s", NM_PRINT_FMT_QUOTED (priv->ssid, "\"", nm_utils_escape_ssid (priv->ssid->data, priv->ssid->len), "\"", "(none)")), @@ -611,7 +657,8 @@ nm_wifi_ap_to_string (const NMWifiAP *self, priv->wpa_flags & 0xFFFF, priv->rsn_flags & 0xFFFF, priv->last_seen > 0 ? ((now_s > 0 ? now_s : nm_utils_get_monotonic_timestamp_s ()) - priv->last_seen) : -1, - supplicant_id); + supplicant_id, + export_path); return str_buf; } @@ -793,10 +840,7 @@ nm_wifi_ap_init (NMWifiAP *ap) NMWifiAP * nm_wifi_ap_new_from_properties (const char *supplicant_path, GVariant *properties) { - const char bad_bssid1[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - const char bad_bssid2[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; NMWifiAP *ap; - const char *addr; g_return_val_if_fail (supplicant_path != NULL, NULL); g_return_val_if_fail (properties != NULL, NULL); @@ -805,10 +849,7 @@ nm_wifi_ap_new_from_properties (const char *supplicant_path, GVariant *propertie nm_wifi_ap_update_from_properties (ap, supplicant_path, properties); /* ignore APs with invalid or missing BSSIDs */ - addr = nm_wifi_ap_get_address (ap); - if ( !addr - || nm_utils_hwaddr_matches (addr, -1, bad_bssid1, ETH_ALEN) - || nm_utils_hwaddr_matches (addr, -1, bad_bssid2, ETH_ALEN)) { + if (!nm_wifi_ap_get_address (ap)) { g_object_unref (ap); return NULL; } diff --git a/src/devices/wifi/nm-wifi-ap.h b/src/devices/wifi/nm-wifi-ap.h index a68aece8..5e64087c 100644 --- a/src/devices/wifi/nm-wifi-ap.h +++ b/src/devices/wifi/nm-wifi-ap.h @@ -53,7 +53,7 @@ NMWifiAP * nm_wifi_ap_new_from_properties (const char *supplicant_path, GVariant *properties); NMWifiAP * nm_wifi_ap_new_fake_from_connection (NMConnection *connection); -void nm_wifi_ap_update_from_properties (NMWifiAP *ap, +gboolean nm_wifi_ap_update_from_properties (NMWifiAP *ap, const char *supplicant_path, GVariant *properties); @@ -68,25 +68,25 @@ gboolean nm_wifi_ap_complete_connection (NMWifiAP *self, const char * nm_wifi_ap_get_supplicant_path (NMWifiAP *ap); guint64 nm_wifi_ap_get_id (NMWifiAP *ap); const GByteArray *nm_wifi_ap_get_ssid (const NMWifiAP *ap); -void nm_wifi_ap_set_ssid (NMWifiAP *ap, +gboolean nm_wifi_ap_set_ssid (NMWifiAP *ap, const guint8 *ssid, gsize len); const char * nm_wifi_ap_get_address (const NMWifiAP *ap); -void nm_wifi_ap_set_address (NMWifiAP *ap, +gboolean nm_wifi_ap_set_address (NMWifiAP *ap, const char *addr); NM80211Mode nm_wifi_ap_get_mode (NMWifiAP *ap); gboolean nm_wifi_ap_is_hotspot (NMWifiAP *ap); gint8 nm_wifi_ap_get_strength (NMWifiAP *ap); -void nm_wifi_ap_set_strength (NMWifiAP *ap, +gboolean nm_wifi_ap_set_strength (NMWifiAP *ap, gint8 strength); guint32 nm_wifi_ap_get_freq (NMWifiAP *ap); -void nm_wifi_ap_set_freq (NMWifiAP *ap, +gboolean nm_wifi_ap_set_freq (NMWifiAP *ap, guint32 freq); guint32 nm_wifi_ap_get_max_bitrate (NMWifiAP *ap); -void nm_wifi_ap_set_max_bitrate (NMWifiAP *ap, +gboolean nm_wifi_ap_set_max_bitrate (NMWifiAP *ap, guint32 bitrate); gboolean nm_wifi_ap_get_fake (const NMWifiAP *ap); -void nm_wifi_ap_set_fake (NMWifiAP *ap, +gboolean nm_wifi_ap_set_fake (NMWifiAP *ap, gboolean fake); const char *nm_wifi_ap_to_string (const NMWifiAP *self, diff --git a/src/devices/wifi/nm-wifi-utils.h b/src/devices/wifi/nm-wifi-utils.h index 39c7fa17..1b6c2f4b 100644 --- a/src/devices/wifi/nm-wifi-utils.h +++ b/src/devices/wifi/nm-wifi-utils.h @@ -21,11 +21,11 @@ #ifndef __NM_WIFI_UTILS_H__ #define __NM_WIFI_UTILS_H__ -#include <nm-dbus-interface.h> -#include <nm-connection.h> -#include <nm-setting-wireless.h> -#include <nm-setting-wireless-security.h> -#include <nm-setting-8021x.h> +#include "nm-dbus-interface.h" +#include "nm-connection.h" +#include "nm-setting-wireless.h" +#include "nm-setting-wireless-security.h" +#include "nm-setting-8021x.h" gboolean nm_wifi_utils_complete_connection (const GByteArray *ssid, const char *bssid, diff --git a/src/devices/wwan/libnm-wwan.ver b/src/devices/wwan/libnm-wwan.ver index 23412de6..eb577aaf 100644 --- a/src/devices/wwan/libnm-wwan.ver +++ b/src/devices/wwan/libnm-wwan.ver @@ -9,6 +9,7 @@ global: nm_modem_deactivate_async_finish; nm_modem_device_state_changed; nm_modem_get_capabilities; + nm_modem_get_configured_mtu; nm_modem_get_control_port; nm_modem_get_data_port; nm_modem_get_driver; diff --git a/src/devices/wwan/nm-device-modem.c b/src/devices/wwan/nm-device-modem.c index 7a70a0bf..4a4d2f2c 100644 --- a/src/devices/wwan/nm-device-modem.c +++ b/src/devices/wwan/nm-device-modem.c @@ -68,10 +68,13 @@ G_DEFINE_TYPE (NMDeviceModem, nm_device_modem, NM_TYPE_DEVICE) /*****************************************************************************/ static void -ppp_failed (NMModem *modem, NMDeviceStateReason reason, gpointer user_data) +ppp_failed (NMModem *modem, + guint i_reason, + gpointer user_data) { NMDevice *device = NM_DEVICE (user_data); NMDeviceModem *self = NM_DEVICE_MODEM (user_data); + NMDeviceStateReason reason = i_reason; switch (nm_device_get_state (device)) { case NM_DEVICE_STATE_PREPARE: @@ -110,12 +113,13 @@ ppp_failed (NMModem *modem, NMDeviceStateReason reason, gpointer user_data) static void modem_prepare_result (NMModem *modem, gboolean success, - NMDeviceStateReason reason, + guint i_reason, gpointer user_data) { NMDeviceModem *self = NM_DEVICE_MODEM (user_data); NMDevice *device = NM_DEVICE (self); NMDeviceState state; + NMDeviceStateReason reason = i_reason; state = nm_device_get_state (device); g_return_if_fail (state == NM_DEVICE_STATE_PREPARE); @@ -123,12 +127,12 @@ modem_prepare_result (NMModem *modem, if (success) nm_device_activate_schedule_stage2_device_config (device); else { - if (reason == NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT) { + if (nm_device_state_reason_check (reason) == NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT) { /* If the connect failed because the SIM PIN was wrong don't allow * the device to be auto-activated anymore, which would risk locking * the SIM if the incorrect PIN continues to be used. */ - nm_device_set_autoconnect (device, FALSE); + nm_device_set_autoconnect_intern (device, FALSE); _LOGI (LOGD_MB, "disabling autoconnect due to failed SIM PIN"); } @@ -201,7 +205,7 @@ modem_ip6_config_result (NMModem *modem, NMDeviceModem *self = NM_DEVICE_MODEM (user_data); NMDevice *device = NM_DEVICE (self); NMActStageReturn ret; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; + NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE; NMIP6Config *ignored = NULL; gboolean got_config = !!config; @@ -235,11 +239,11 @@ modem_ip6_config_result (NMModem *modem, } /* Start SLAAC now that we have a link-local address from the modem */ - ret = NM_DEVICE_CLASS (nm_device_modem_parent_class)->act_stage3_ip6_config_start (device, &ignored, &reason); + ret = NM_DEVICE_CLASS (nm_device_modem_parent_class)->act_stage3_ip6_config_start (device, &ignored, &failure_reason); g_assert (ignored == NULL); switch (ret) { case NM_ACT_STAGE_RETURN_FAILURE: - nm_device_ip_method_failed (device, AF_INET6, reason); + nm_device_ip_method_failed (device, AF_INET6, failure_reason); break; case NM_ACT_STAGE_RETURN_IP_FAIL: /* all done */ @@ -371,9 +375,9 @@ device_state_changed (NMDevice *device, nm_modem_state_to_string (nm_modem_get_state (priv->modem))); } - nm_modem_device_state_changed (priv->modem, new_state, old_state, reason); + nm_modem_device_state_changed (priv->modem, new_state, old_state); - switch (reason) { + switch (nm_device_state_reason_check (reason)) { case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED: case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING: case NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED: @@ -386,8 +390,10 @@ device_state_changed (NMDevice *device, /* Block autoconnect of the just-failed connection for situations * where a retry attempt would just fail again. */ - if (connection) - nm_settings_connection_set_autoconnect_blocked_reason (connection, reason); + if (connection) { + nm_settings_connection_set_autoconnect_blocked_reason (connection, + NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_BLOCKED); + } break; default: break; @@ -509,41 +515,41 @@ deactivate_async (NMDevice *self, /*****************************************************************************/ static NMActStageReturn -act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) +act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMActStageReturn ret; NMActRequest *req; - ret = NM_DEVICE_CLASS (nm_device_modem_parent_class)->act_stage1_prepare (device, reason); + ret = NM_DEVICE_CLASS (nm_device_modem_parent_class)->act_stage1_prepare (device, out_failure_reason); if (ret != NM_ACT_STAGE_RETURN_SUCCESS) return ret; req = nm_device_get_act_request (device); - g_assert (req); + g_return_val_if_fail (req, NM_ACT_STAGE_RETURN_FAILURE); - return nm_modem_act_stage1_prepare (NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device)->modem, req, reason); + return nm_modem_act_stage1_prepare (NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device)->modem, req, out_failure_reason); } static NMActStageReturn -act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) +act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMActRequest *req; req = nm_device_get_act_request (device); - g_assert (req); + g_return_val_if_fail (req, NM_ACT_STAGE_RETURN_FAILURE); - return nm_modem_act_stage2_config (NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device)->modem, req, reason); + return nm_modem_act_stage2_config (NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device)->modem, req, out_failure_reason); } static NMActStageReturn act_stage3_ip4_config_start (NMDevice *device, NMIP4Config **out_config, - NMDeviceStateReason *reason) + NMDeviceStateReason *out_failure_reason) { return nm_modem_stage3_ip4_config_start (NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device)->modem, device, NM_DEVICE_CLASS (nm_device_modem_parent_class), - reason); + out_failure_reason); } static void @@ -555,11 +561,11 @@ ip4_config_pre_commit (NMDevice *device, NMIP4Config *config) static NMActStageReturn act_stage3_ip6_config_start (NMDevice *device, NMIP6Config **out_config, - NMDeviceStateReason *reason) + NMDeviceStateReason *out_failure_reason) { return nm_modem_stage3_ip6_config_start (NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device)->modem, nm_device_get_act_request (device), - reason); + out_failure_reason); } static gboolean @@ -800,6 +806,7 @@ nm_device_modem_class_init (NMDeviceModemClass *mclass) device_class->owns_iface = owns_iface; device_class->is_available = is_available; device_class->get_ip_iface_identifier = get_ip_iface_identifier; + device_class->get_configured_mtu = nm_modem_get_configured_mtu; device_class->state_changed = device_state_changed; diff --git a/src/devices/wwan/nm-modem-broadband.c b/src/devices/wwan/nm-modem-broadband.c index 7dfd38c5..4b16fb14 100644 --- a/src/devices/wwan/nm-modem-broadband.c +++ b/src/devices/wwan/nm-modem-broadband.c @@ -119,7 +119,10 @@ G_DEFINE_TYPE (NMModemBroadband, nm_modem_broadband, NM_TYPE_MODEM) char __prefix_name[128]; \ const char *__uid; \ \ - _nm_log (_level, (_NMLOG_DOMAIN), 0, \ + _nm_log (_level, (_NMLOG_DOMAIN), 0, NULL, \ + ((__self && __self->_priv.ctx) \ + ? nm_connection_get_uuid (__self->_priv.ctx->connection) \ + : NULL), \ "%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ _NMLOG_PREFIX_NAME, \ (__self \ @@ -407,7 +410,7 @@ connect_ready (MMModemSimple *simple_iface, if (ip4_method == NM_MODEM_IP_METHOD_UNKNOWN && ip6_method == NM_MODEM_IP_METHOD_UNKNOWN) { _LOGW ("failed to connect modem: invalid bearer IP configuration"); - g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, NM_DEVICE_STATE_REASON_CONFIG_FAILED); + nm_modem_emit_prepare_result (NM_MODEM (self), FALSE, NM_DEVICE_STATE_REASON_CONFIG_FAILED); connect_context_clear (self); return; } @@ -439,11 +442,10 @@ send_pin_ready (MMSim *sim, GAsyncResult *result, NMModemBroadband *self) if (error) { if (g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_SIM_PIN) || (g_error_matches (error, MM_CORE_ERROR, MM_CORE_ERROR_UNAUTHORIZED) && - mm_modem_get_unlock_required (self->_priv.modem_iface) == MM_MODEM_LOCK_SIM_PIN)) { + mm_modem_get_unlock_required (self->_priv.modem_iface) == MM_MODEM_LOCK_SIM_PIN)) ask_for_pin (self); - } else { - g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, translate_mm_error (self, error)); - } + else + nm_modem_emit_prepare_result (NM_MODEM (self), FALSE, translate_mm_error (self, error)); return; } @@ -506,7 +508,7 @@ connect_context_step (NMModemBroadband *self) _LOGW ("failed to connect '%s': not a mobile broadband modem", nm_connection_get_id (ctx->connection)); - g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED); + nm_modem_emit_prepare_result (NM_MODEM (self), FALSE, NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED); connect_context_clear (self); break; } @@ -520,7 +522,7 @@ connect_context_step (NMModemBroadband *self) error->message); g_clear_error (&error); - g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED); + nm_modem_emit_prepare_result (NM_MODEM (self), FALSE, NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED); connect_context_clear (self); break; } @@ -559,9 +561,9 @@ connect_context_step (NMModemBroadband *self) /* fall through */ case CONNECT_STEP_LAST: - if (self->_priv.ipv4_config || self->_priv.ipv6_config) { - g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, TRUE, NM_DEVICE_STATE_REASON_NONE); - } else { + if (self->_priv.ipv4_config || self->_priv.ipv6_config) + nm_modem_emit_prepare_result (NM_MODEM (self), TRUE, NM_DEVICE_STATE_REASON_NONE); + else { /* If we have a saved error from a previous attempt, use it */ if (!ctx->first_error) ctx->first_error = g_error_new_literal (NM_DEVICE_ERROR, @@ -570,7 +572,7 @@ connect_context_step (NMModemBroadband *self) _LOGW ("failed to connect modem: %s", ctx->first_error->message); - g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, translate_mm_error (self, ctx->first_error)); + nm_modem_emit_prepare_result (NM_MODEM (self), FALSE, translate_mm_error (self, ctx->first_error)); } connect_context_clear (self); @@ -581,7 +583,7 @@ connect_context_step (NMModemBroadband *self) static NMActStageReturn act_stage1_prepare (NMModem *_self, NMConnection *connection, - NMDeviceStateReason *reason) + NMDeviceStateReason *out_failure_reason) { NMModemBroadband *self = NM_MODEM_BROADBAND (_self); @@ -590,7 +592,7 @@ act_stage1_prepare (NMModem *_self, self->_priv.simple_iface = mm_object_get_modem_simple (self->_priv.modem_object); if (!self->_priv.simple_iface) { _LOGW ("cannot access the Simple mobile broadband modem interface"); - *reason = NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED; + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED); return NM_ACT_STAGE_RETURN_FAILURE; } } @@ -944,7 +946,7 @@ out: static NMActStageReturn static_stage3_ip4_config_start (NMModem *_self, NMActRequest *req, - NMDeviceStateReason *reason) + NMDeviceStateReason *out_failure_reason) { NMModemBroadband *self = NM_MODEM_BROADBAND (_self); @@ -1050,7 +1052,7 @@ out: } static NMActStageReturn -stage3_ip6_config_request (NMModem *_self, NMDeviceStateReason *reason) +stage3_ip6_config_request (NMModem *_self, NMDeviceStateReason *out_failure_reason) { NMModemBroadband *self = NM_MODEM_BROADBAND (_self); diff --git a/src/devices/wwan/nm-modem-ofono.c b/src/devices/wwan/nm-modem-ofono.c index 41d422aa..52b335c7 100644 --- a/src/devices/wwan/nm-modem-ofono.c +++ b/src/devices/wwan/nm-modem-ofono.c @@ -83,7 +83,7 @@ G_DEFINE_TYPE (NMModemOfono, nm_modem_ofono, NM_TYPE_MODEM) char __prefix_name[128]; \ const char *__uid; \ \ - _nm_log (_level, (_NMLOG_DOMAIN), 0, \ + _nm_log (_level, (_NMLOG_DOMAIN), 0, NULL, NULL, \ "%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ _NMLOG_PREFIX_NAME, \ (__self \ @@ -724,8 +724,8 @@ stage1_prepare_done (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data if (error) { _LOGW ("connection failed: %s", error->message); - g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, - NM_DEVICE_STATE_REASON_MODEM_BUSY); + nm_modem_emit_prepare_result (NM_MODEM (self), FALSE, + NM_DEVICE_STATE_REASON_MODEM_BUSY); /* * FIXME: add code to check for InProgress so that the * connection doesn't continue to try and activate, @@ -745,7 +745,6 @@ context_property_changed (GDBusProxy *proxy, { NMModemOfono *self = NM_MODEM_OFONO (user_data); NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self); - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; NMPlatformIP4Address addr; gboolean ret = FALSE; GVariant *v_dict; @@ -910,39 +909,40 @@ context_property_changed (GDBusProxy *proxy, out: if (nm_modem_get_state (NM_MODEM (self)) != NM_MODEM_STATE_CONNECTED) { _LOGI ("emitting PREPARE_RESULT: %s", ret ? "TRUE" : "FALSE"); - if (!ret) - reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE; - g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, ret, reason); + nm_modem_emit_prepare_result (NM_MODEM (self), ret, + ret + ? NM_DEVICE_STATE_REASON_NONE + : NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); } else { _LOGW ("MODEM_PPP_FAILED"); - g_signal_emit_by_name (self, NM_MODEM_PPP_FAILED, NM_DEVICE_STATE_REASON_PPP_FAILED); + nm_modem_emit_ppp_failed (NM_MODEM (self), NM_DEVICE_STATE_REASON_PPP_FAILED); } } static NMActStageReturn static_stage3_ip4_config_start (NMModem *modem, NMActRequest *req, - NMDeviceStateReason *reason) + NMDeviceStateReason *out_failure_reason) { NMModemOfono *self = NM_MODEM_OFONO (modem); NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self); - NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; GError *error = NULL; - if (priv->ip4_config) { - _LOGD ("IP4 config is done; setting modem_state -> CONNECTED"); - g_signal_emit_by_name (self, NM_MODEM_IP4_CONFIG_RESULT, priv->ip4_config, error); + if (!priv->ip4_config) { + _LOGD ("IP4 config not ready(?)"); + return NM_ACT_STAGE_RETURN_FAILURE; + } - /* Signal listener takes ownership of the IP4Config */ - priv->ip4_config = NULL; + _LOGD ("IP4 config is done; setting modem_state -> CONNECTED"); + g_signal_emit_by_name (self, NM_MODEM_IP4_CONFIG_RESULT, priv->ip4_config, error); - nm_modem_set_state (NM_MODEM (self), - NM_MODEM_STATE_CONNECTED, - nm_modem_state_to_string (NM_MODEM_STATE_CONNECTED)); - ret = NM_ACT_STAGE_RETURN_POSTPONE; - } + /* Signal listener takes ownership of the IP4Config */ + priv->ip4_config = NULL; - return ret; + nm_modem_set_state (NM_MODEM (self), + NM_MODEM_STATE_CONNECTED, + nm_modem_state_to_string (NM_MODEM_STATE_CONNECTED)); + return NM_ACT_STAGE_RETURN_POSTPONE; } static void @@ -955,14 +955,14 @@ context_proxy_new_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_dat priv->context_proxy = g_dbus_proxy_new_for_bus_finish (result, &error); if (error) { _LOGE ("failed to create ofono ConnectionContext DBus proxy: %s", error->message); - g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, - NM_DEVICE_STATE_REASON_MODEM_BUSY); + nm_modem_emit_prepare_result (NM_MODEM (self), FALSE, + NM_DEVICE_STATE_REASON_MODEM_BUSY); return; } if (!priv->gprs_attached) { - g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, - NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER); + nm_modem_emit_prepare_result (NM_MODEM (self), FALSE, + NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER); return; } @@ -1038,7 +1038,7 @@ create_connect_properties (NMConnection *connection) static NMActStageReturn act_stage1_prepare (NMModem *modem, NMConnection *connection, - NMDeviceStateReason *reason) + NMDeviceStateReason *out_failure_reason) { NMModemOfono *self = NM_MODEM_OFONO (modem); NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self); @@ -1047,7 +1047,7 @@ act_stage1_prepare (NMModem *modem, context_id = nm_connection_get_id (connection); id = g_strsplit (context_id, "/", 0); - g_assert (id[2]); + g_return_val_if_fail (id[2], NM_ACT_STAGE_RETURN_FAILURE); _LOGD ("trying %s %s", id[1], id[2]); @@ -1058,8 +1058,8 @@ act_stage1_prepare (NMModem *modem, g_strfreev (id); if (!priv->context_path) { - *reason = NM_DEVICE_STATE_REASON_GSM_APN_FAILED; - return NM_ACT_STAGE_RETURN_FAILURE; + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_GSM_APN_FAILED); + return NM_ACT_STAGE_RETURN_FAILURE; } if (priv->connect_properties) @@ -1073,7 +1073,7 @@ act_stage1_prepare (NMModem *modem, do_context_activate (self); } else { _LOGW ("could not activate context: modem is not registered."); - *reason = NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER; + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER); return NM_ACT_STAGE_RETURN_FAILURE; } diff --git a/src/devices/wwan/nm-modem.c b/src/devices/wwan/nm-modem.c index 1dec0dd1..6494b849 100644 --- a/src/devices/wwan/nm-modem.c +++ b/src/devices/wwan/nm-modem.c @@ -33,6 +33,7 @@ #include "NetworkManagerUtils.h" #include "devices/nm-device-private.h" #include "nm-route-manager.h" +#include "nm-netns.h" #include "nm-act-request.h" #include "nm-ip4-config.h" #include "nm-ip6-config.h" @@ -158,7 +159,7 @@ nm_modem_set_state (NMModem *self, priv->state = new_state; _notify (self, PROP_STATE); - g_signal_emit (self, signals[STATE_CHANGED], 0, (int) new_state, (int) old_state, reason); + g_signal_emit (self, signals[STATE_CHANGED], 0, (int) new_state, (int) old_state); } } @@ -201,7 +202,7 @@ nm_modem_set_mm_enabled (NMModem *self, /* Try to unlock the modem if it's being enabled */ if (enabled) - g_signal_emit_by_name (self, NM_MODEM_AUTH_REQUESTED, 0); + g_signal_emit (self, signals[AUTH_REQUESTED], 0); return; } @@ -222,6 +223,22 @@ nm_modem_emit_removed (NMModem *self) g_signal_emit (self, signals[REMOVED], 0); } +void +nm_modem_emit_prepare_result (NMModem *self, gboolean success, NMDeviceStateReason reason) +{ + nm_assert (NM_IS_MODEM (self)); + + g_signal_emit (self, signals[PREPARE_RESULT], 0, success, (guint) reason); +} + +void +nm_modem_emit_ppp_failed (NMModem *self, NMDeviceStateReason reason) +{ + nm_assert (NM_IS_MODEM (self)); + + g_signal_emit (self, signals[PPP_FAILED], 0, (guint) reason); +} + NMModemIPType nm_modem_get_supported_ip_types (NMModem *self) { @@ -382,10 +399,10 @@ ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_ { switch (status) { case NM_PPP_STATUS_DISCONNECT: - g_signal_emit (NM_MODEM (user_data), signals[PPP_FAILED], 0, NM_DEVICE_STATE_REASON_PPP_DISCONNECT); + nm_modem_emit_ppp_failed (user_data, NM_DEVICE_STATE_REASON_PPP_DISCONNECT); break; case NM_PPP_STATUS_DEAD: - g_signal_emit (NM_MODEM (user_data), signals[PPP_FAILED], 0, NM_DEVICE_STATE_REASON_PPP_FAILED); + nm_modem_emit_ppp_failed (user_data, NM_DEVICE_STATE_REASON_PPP_FAILED); break; default: break; @@ -479,18 +496,19 @@ ppp_ip6_config (NMPPPManager *ppp_manager, static void ppp_stats (NMPPPManager *ppp_manager, - guint32 in_bytes, - guint32 out_bytes, + guint i_in_bytes, + guint i_out_bytes, gpointer user_data) { NMModem *self = NM_MODEM (user_data); NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + guint32 in_bytes = i_in_bytes; + guint32 out_bytes = i_out_bytes; if (priv->in_bytes != in_bytes || priv->out_bytes != out_bytes) { priv->in_bytes = in_bytes; priv->out_bytes = out_bytes; - - g_signal_emit (self, signals[PPP_STATS], 0, in_bytes, out_bytes); + g_signal_emit (self, signals[PPP_STATS], 0, (guint) in_bytes, (guint) out_bytes); } } @@ -514,18 +532,16 @@ port_speed_is_zero (const char *port) static NMActStageReturn ppp_stage3_ip_config_start (NMModem *self, NMActRequest *req, - NMDeviceStateReason *reason) + NMDeviceStateReason *out_failure_reason) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); const char *ppp_name = NULL; GError *error = NULL; - NMActStageReturn ret; guint ip_timeout = 30; guint baud_override = 0; g_return_val_if_fail (NM_IS_MODEM (self), NM_ACT_STAGE_RETURN_FAILURE); g_return_val_if_fail (NM_IS_ACT_REQUEST (req), NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); /* If we're already running PPP don't restart it; for example, if both * IPv4 and IPv6 are requested, IPv4 gets started first, but we use the @@ -560,24 +576,10 @@ ppp_stage3_ip_config_start (NMModem *self, baud_override = 57600; priv->ppp_manager = nm_ppp_manager_create (priv->data_port, &error); - if ( priv->ppp_manager - && nm_ppp_manager_start (priv->ppp_manager, req, ppp_name, - ip_timeout, baud_override, &error)) { - g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_STATE_CHANGED, - G_CALLBACK (ppp_state_changed), - self); - g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_IP4_CONFIG, - G_CALLBACK (ppp_ip4_config), - self); - g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_IP6_CONFIG, - G_CALLBACK (ppp_ip6_config), - self); - g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_STATS, - G_CALLBACK (ppp_stats), - self); - - ret = NM_ACT_STAGE_RETURN_POSTPONE; - } else { + + if ( !priv->ppp_manager + || !nm_ppp_manager_start (priv->ppp_manager, req, ppp_name, + ip_timeout, baud_override, &error)) { nm_log_err (LOGD_PPP, "(%s): error starting PPP: %s", nm_modem_get_uid (self), error->message); @@ -585,11 +587,24 @@ ppp_stage3_ip_config_start (NMModem *self, g_clear_object (&priv->ppp_manager); - *reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED; - ret = NM_ACT_STAGE_RETURN_FAILURE; + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_PPP_START_FAILED); + return NM_ACT_STAGE_RETURN_FAILURE; } - return ret; + g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_STATE_CHANGED, + G_CALLBACK (ppp_state_changed), + self); + g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_IP4_CONFIG, + G_CALLBACK (ppp_ip4_config), + self); + g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_IP6_CONFIG, + G_CALLBACK (ppp_ip6_config), + self); + g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_STATS, + G_CALLBACK (ppp_stats), + self); + + return NM_ACT_STAGE_RETURN_POSTPONE; } /*****************************************************************************/ @@ -598,7 +613,7 @@ NMActStageReturn nm_modem_stage3_ip4_config_start (NMModem *self, NMDevice *device, NMDeviceClass *device_class, - NMDeviceStateReason *reason) + NMDeviceStateReason *out_failure_reason) { NMModemPrivate *priv; NMActRequest *req; @@ -611,12 +626,13 @@ nm_modem_stage3_ip4_config_start (NMModem *self, g_return_val_if_fail (NM_IS_MODEM (self), NM_ACT_STAGE_RETURN_FAILURE); g_return_val_if_fail (NM_IS_DEVICE (device), NM_ACT_STAGE_RETURN_FAILURE); g_return_val_if_fail (NM_IS_DEVICE_CLASS (device_class), NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); req = nm_device_get_act_request (device); - g_assert (req); + g_return_val_if_fail (req, NM_ACT_STAGE_RETURN_FAILURE); + connection = nm_act_request_get_applied_connection (req); - g_assert (connection); + g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); + method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG); /* Only Disabled and Auto methods make sense for WWAN */ @@ -627,22 +643,22 @@ nm_modem_stage3_ip4_config_start (NMModem *self, nm_log_warn (LOGD_MB | LOGD_IP4, "(%s): unhandled WWAN IPv4 method '%s'; will fail", nm_modem_get_uid (self), method); - *reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE; + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); return NM_ACT_STAGE_RETURN_FAILURE; } priv = NM_MODEM_GET_PRIVATE (self); switch (priv->ip4_method) { case NM_MODEM_IP_METHOD_PPP: - ret = ppp_stage3_ip_config_start (self, req, reason); + ret = ppp_stage3_ip_config_start (self, req, out_failure_reason); break; case NM_MODEM_IP_METHOD_STATIC: nm_log_dbg (LOGD_MB, "MODEM_IP_METHOD_STATIC"); - ret = NM_MODEM_GET_CLASS (self)->static_stage3_ip4_config_start (self, req, reason); + ret = NM_MODEM_GET_CLASS (self)->static_stage3_ip4_config_start (self, req, out_failure_reason); break; case NM_MODEM_IP_METHOD_AUTO: nm_log_dbg (LOGD_MB, "MODEM_IP_METHOD_AUTO"); - ret = device_class->act_stage3_ip4_config_start (device, NULL, reason); + ret = device_class->act_stage3_ip4_config_start (device, NULL, out_failure_reason); break; default: nm_log_info (LOGD_MB, "(%s): IPv4 configuration disabled", nm_modem_get_uid (self)); @@ -670,7 +686,7 @@ nm_modem_ip4_pre_commit (NMModem *modem, g_assert (address); if (address->plen == 32) - nm_platform_link_set_noarp (NM_PLATFORM_GET, nm_device_get_ip_ifindex (device)); + nm_platform_link_set_noarp (nm_device_get_platform (device), nm_device_get_ip_ifindex (device)); } } @@ -712,30 +728,28 @@ nm_modem_emit_ip6_config_result (NMModem *self, } static NMActStageReturn -stage3_ip6_config_request (NMModem *self, NMDeviceStateReason *reason) +stage3_ip6_config_request (NMModem *self, NMDeviceStateReason *out_failure_reason) { - *reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE; + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); return NM_ACT_STAGE_RETURN_FAILURE; } NMActStageReturn nm_modem_stage3_ip6_config_start (NMModem *self, NMActRequest *req, - NMDeviceStateReason *reason) + NMDeviceStateReason *out_failure_reason) { NMModemPrivate *priv; NMActStageReturn ret; NMConnection *connection; const char *method; - g_return_val_if_fail (self != NULL, NM_ACT_STAGE_RETURN_FAILURE); g_return_val_if_fail (NM_IS_MODEM (self), NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE); g_return_val_if_fail (NM_IS_ACT_REQUEST (req), NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); connection = nm_act_request_get_applied_connection (req); - g_assert (connection); + g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); + method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG); /* Only Ignore and Auto methods make sense for WWAN */ @@ -746,14 +760,14 @@ nm_modem_stage3_ip6_config_start (NMModem *self, nm_log_warn (LOGD_MB | LOGD_IP6, "(%s): unhandled WWAN IPv6 method '%s'; will fail", nm_modem_get_uid (self), method); - *reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE; + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); return NM_ACT_STAGE_RETURN_FAILURE; } priv = NM_MODEM_GET_PRIVATE (self); switch (priv->ip6_method) { case NM_MODEM_IP_METHOD_PPP: - ret = ppp_stage3_ip_config_start (self, req, reason); + ret = ppp_stage3_ip_config_start (self, req, out_failure_reason); break; case NM_MODEM_IP_METHOD_STATIC: case NM_MODEM_IP_METHOD_AUTO: @@ -761,7 +775,7 @@ nm_modem_stage3_ip6_config_start (NMModem *self, * which in the static case is the full config, and the DHCP/Auto case * is just the IPv6LL address to use for SLAAC. */ - ret = NM_MODEM_GET_CLASS (self)->stage3_ip6_config_request (self, reason); + ret = NM_MODEM_GET_CLASS (self)->stage3_ip6_config_request (self, out_failure_reason); break; default: nm_log_info (LOGD_MB, "(%s): IPv6 configuration disabled", nm_modem_get_uid (self)); @@ -772,6 +786,45 @@ nm_modem_stage3_ip6_config_start (NMModem *self, return ret; } +guint32 +nm_modem_get_configured_mtu (NMDevice *self, gboolean *out_is_user_config) +{ + NMConnection *connection; + NMSetting *setting; + gint64 mtu_default; + guint mtu = 0; + const char *property_name; + + nm_assert (NM_IS_DEVICE (self)); + nm_assert (out_is_user_config); + + connection = nm_device_get_applied_connection (self); + if (!connection) + g_return_val_if_reached (0); + + setting = (NMSetting *) nm_connection_get_setting_gsm (connection); + if (!setting) + setting = (NMSetting *) nm_connection_get_setting_cdma (connection); + + if (setting) { + g_object_get (setting, "mtu", &mtu, NULL); + if (mtu) { + *out_is_user_config = TRUE; + return mtu; + } + + property_name = NM_IS_SETTING_GSM (setting) ? "gsm.mtu" : "cdma.mtu"; + mtu_default = nm_device_get_configured_mtu_from_connection_default (self, property_name); + if (mtu_default >= 0) { + *out_is_user_config = TRUE; + return (guint32) mtu_default; + } + } + + *out_is_user_config = FALSE; + return 0; +} + /*****************************************************************************/ static void @@ -835,16 +888,16 @@ nm_modem_get_secrets (NMModem *self, static NMActStageReturn act_stage1_prepare (NMModem *modem, NMConnection *connection, - NMDeviceStateReason *reason) + NMDeviceStateReason *out_failure_reason) { - *reason = NM_DEVICE_STATE_REASON_UNKNOWN; + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_UNKNOWN); return NM_ACT_STAGE_RETURN_FAILURE; } NMActStageReturn nm_modem_act_stage1_prepare (NMModem *self, NMActRequest *req, - NMDeviceStateReason *reason) + NMDeviceStateReason *out_failure_reason) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); gs_unref_ptrarray GPtrArray *hints = NULL; @@ -857,13 +910,13 @@ nm_modem_act_stage1_prepare (NMModem *self, priv->act_request = g_object_ref (req); connection = nm_act_request_get_applied_connection (req); - g_assert (connection); + g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); setting_name = nm_connection_need_secrets (connection, &hints); if (!setting_name) { /* Ready to connect */ g_assert (!hints); - return NM_MODEM_GET_CLASS (self)->act_stage1_prepare (self, connection, reason); + return NM_MODEM_GET_CLASS (self)->act_stage1_prepare (self, connection, out_failure_reason); } /* Secrets required... */ @@ -887,7 +940,7 @@ nm_modem_act_stage1_prepare (NMModem *self, NMActStageReturn nm_modem_act_stage2_config (NMModem *self, NMActRequest *req, - NMDeviceStateReason *reason) + NMDeviceStateReason *out_failure_reason) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); @@ -1016,9 +1069,10 @@ deactivate_cleanup (NMModem *self, NMDevice *device) priv->ip6_method == NM_MODEM_IP_METHOD_AUTO) { ifindex = nm_device_get_ip_ifindex (device); if (ifindex > 0) { - nm_route_manager_route_flush (nm_route_manager_get (), ifindex); - nm_platform_address_flush (NM_PLATFORM_GET, ifindex); - nm_platform_link_set_down (NM_PLATFORM_GET, ifindex); + nm_route_manager_route_flush (nm_netns_get_route_manager (nm_device_get_netns (device)), + ifindex); + nm_platform_address_flush (nm_device_get_platform (device), ifindex); + nm_platform_link_set_down (nm_device_get_platform (device), ifindex); } } } @@ -1205,8 +1259,7 @@ nm_modem_deactivate (NMModem *self, NMDevice *device) void nm_modem_device_state_changed (NMModem *self, NMDeviceState new_state, - NMDeviceState old_state, - NMDeviceStateReason reason) + NMDeviceState old_state) { gboolean was_connected = FALSE, warn = TRUE; NMModemPrivate *priv; @@ -1396,15 +1449,15 @@ set_property (GObject *object, guint prop_id, switch (prop_id) { case PROP_PATH: - /* Construct only */ + /* construct-only */ priv->path = g_value_dup_string (value); break; case PROP_DRIVER: - /* Construct only */ + /* construct-only */ priv->driver = g_value_dup_string (value); break; case PROP_CONTROL_PORT: - /* Construct only */ + /* construct-only */ priv->control_port = g_value_dup_string (value); break; case PROP_DATA_PORT: @@ -1412,7 +1465,7 @@ set_property (GObject *object, guint prop_id, priv->data_port = g_value_dup_string (value); break; case PROP_UID: - /* Construct only */ + /* construct-only */ priv->uid = g_value_dup_string (value); break; case PROP_IP4_METHOD: @@ -1628,15 +1681,16 @@ nm_modem_class_init (NMModemClass *klass) g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); signals[PPP_STATS] = - g_signal_new ("ppp-stats", + g_signal_new (NM_MODEM_PPP_STATS, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE, 2, - G_TYPE_UINT, G_TYPE_UINT); + G_TYPE_UINT /*guint32 in_bytes*/, + G_TYPE_UINT /*guint32 out_bytes*/); signals[PPP_FAILED] = - g_signal_new ("ppp-failed", + g_signal_new (NM_MODEM_PPP_FAILED, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, diff --git a/src/devices/wwan/nm-modem.h b/src/devices/wwan/nm-modem.h index c590b9e4..a50727a9 100644 --- a/src/devices/wwan/nm-modem.h +++ b/src/devices/wwan/nm-modem.h @@ -132,17 +132,17 @@ typedef struct { NMActStageReturn (*act_stage1_prepare) (NMModem *modem, NMConnection *connection, - NMDeviceStateReason *reason); + NMDeviceStateReason *out_failure_reason); NMActStageReturn (*static_stage3_ip4_config_start) (NMModem *self, NMActRequest *req, - NMDeviceStateReason *reason); + NMDeviceStateReason *out_failure_reason); /* Request the IP6 config; when the config returns the modem * subclass should emit the ip6_config_result signal. */ NMActStageReturn (*stage3_ip6_config_request) (NMModem *self, - NMDeviceStateReason *reason); + NMDeviceStateReason *out_failure_reason); void (*set_mm_enabled) (NMModem *self, gboolean enabled); @@ -187,20 +187,20 @@ gboolean nm_modem_complete_connection (NMModem *self, NMActStageReturn nm_modem_act_stage1_prepare (NMModem *modem, NMActRequest *req, - NMDeviceStateReason *reason); + NMDeviceStateReason *out_failure_reason); NMActStageReturn nm_modem_act_stage2_config (NMModem *modem, NMActRequest *req, - NMDeviceStateReason *reason); + NMDeviceStateReason *out_failure_reason); NMActStageReturn nm_modem_stage3_ip4_config_start (NMModem *modem, NMDevice *device, NMDeviceClass *device_class, - NMDeviceStateReason *reason); + NMDeviceStateReason *out_failure_reason); NMActStageReturn nm_modem_stage3_ip6_config_start (NMModem *modem, NMActRequest *req, - NMDeviceStateReason *reason); + NMDeviceStateReason *out_failure_reason); void nm_modem_ip4_pre_commit (NMModem *modem, NMDevice *device, NMIP4Config *config); @@ -222,8 +222,7 @@ gboolean nm_modem_deactivate_async_finish (NMModem *self, void nm_modem_device_state_changed (NMModem *modem, NMDeviceState new_state, - NMDeviceState old_state, - NMDeviceStateReason reason); + NMDeviceState old_state); void nm_modem_set_mm_enabled (NMModem *self, gboolean enabled); @@ -239,6 +238,10 @@ NMModemIPType nm_modem_get_supported_ip_types (NMModem *self); /* For the modem-manager only */ void nm_modem_emit_removed (NMModem *self); +void nm_modem_emit_prepare_result (NMModem *self, gboolean success, NMDeviceStateReason reason); + +void nm_modem_emit_ppp_failed (NMModem *self, NMDeviceStateReason reason); + GArray *nm_modem_get_connection_ip_type (NMModem *self, NMConnection *connection, GError **error); @@ -250,4 +253,6 @@ void nm_modem_emit_ip6_config_result (NMModem *self, const gchar *nm_modem_ip_type_to_string (NMModemIPType ip_type); +guint32 nm_modem_get_configured_mtu (NMDevice *self, gboolean *out_is_user_config); + #endif /* __NETWORKMANAGER_MODEM_H__ */ |