diff options
| author | Michael Biebl <biebl@debian.org> | 2020-04-11 21:28:04 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2020-04-11 21:28:04 +0200 |
| commit | 1e5977b62f896e844b548c3007ace9e1dfa7f9ed (patch) | |
| tree | 7a7416ed410e72b6200f3d860fd315ec11cc106b /src/devices/nm-device-macsec.c | |
| parent | b012fa6e1d808e0736c009799c62d835cbfcc1dd (diff) | |
New upstream version 1.23.90 upstream/1.23.90
Diffstat (limited to 'src/devices/nm-device-macsec.c')
| -rw-r--r-- | src/devices/nm-device-macsec.c | 332 |
1 files changed, 200 insertions, 132 deletions
diff --git a/src/devices/nm-device-macsec.c b/src/devices/nm-device-macsec.c index c9592a49..f1878078 100644 --- a/src/devices/nm-device-macsec.c +++ b/src/devices/nm-device-macsec.c @@ -23,16 +23,9 @@ _LOG_DECLARE_SELF(NMDeviceMacsec); /*****************************************************************************/ -typedef struct Supplicant { - NMSupplicantManager *mgr; - NMSupplicantInterface *iface; +#define SUPPLICANT_LNK_TIMEOUT_SEC 15 - /* signal handler ids */ - gulong iface_state_id; - - /* Timeouts and idles */ - guint con_timeout_id; -} Supplicant; +/*****************************************************************************/ NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceMacsec, PROP_SCI, @@ -53,8 +46,20 @@ typedef struct { NMPlatformLnkMacsec props; gulong parent_state_id; gulong parent_mtu_id; - Supplicant supplicant; - guint supplicant_timeout_id; + + struct { + NMSupplicantManager *mgr; + NMSupplMgrCreateIfaceHandle *create_handle; + NMSupplicantInterface *iface; + + gulong iface_state_id; + + guint con_timeout_id; + guint lnk_timeout_id; + + bool is_associated:1; + } supplicant; + NMActRequestGetSecretsCallId *macsec_secrets_id; } NMDeviceMacsecPrivate; @@ -69,7 +74,7 @@ struct _NMDeviceMacsecClass { G_DEFINE_TYPE (NMDeviceMacsec, nm_device_macsec, NM_TYPE_DEVICE) -#define NM_DEVICE_MACSEC_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMDeviceMacsec, NM_IS_DEVICE_MACSEC) +#define NM_DEVICE_MACSEC_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMDeviceMacsec, NM_IS_DEVICE_MACSEC, NMDevice) /******************************************************************/ @@ -77,7 +82,8 @@ static void macsec_secrets_cancel (NMDeviceMacsec *self); /******************************************************************/ -NM_UTILS_LOOKUP_STR_DEFINE_STATIC (validation_mode_to_string, guint8, +static +NM_UTILS_LOOKUP_STR_DEFINE (validation_mode_to_string, guint8, NM_UTILS_LOOKUP_DEFAULT_WARN ("<unknown>"), NM_UTILS_LOOKUP_STR_ITEM (0, "disable"), NM_UTILS_LOOKUP_STR_ITEM (1, "check"), @@ -226,7 +232,7 @@ build_supplicant_config (NMDeviceMacsec *self, GError **error) 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 (FALSE, FALSE, FALSE, FALSE); + config = nm_supplicant_config_new (NM_SUPPL_CAP_MASK_NONE); s_macsec = nm_device_get_applied_setting (NM_DEVICE (self), NM_TYPE_SETTING_MACSEC); @@ -253,7 +259,9 @@ supplicant_interface_release (NMDeviceMacsec *self) { NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE (self); - nm_clear_g_source (&priv->supplicant_timeout_id); + nm_clear_pointer (&priv->supplicant.create_handle, nm_supplicant_manager_create_interface_cancel); + + nm_clear_g_source (&priv->supplicant.lnk_timeout_id); nm_clear_g_source (&priv->supplicant.con_timeout_id); nm_clear_g_signal_handler (priv->supplicant.iface, &priv->supplicant.iface_state_id); @@ -264,21 +272,6 @@ supplicant_interface_release (NMDeviceMacsec *self) } static void -supplicant_iface_assoc_cb (NMSupplicantInterface *iface, - GError *error, - gpointer user_data) -{ - NMDeviceMacsec *self = NM_DEVICE_MACSEC (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 macsec_secrets_cb (NMActRequest *req, NMActRequestGetSecretsCallId *call_id, NMSettingsConnection *connection, @@ -313,7 +306,7 @@ macsec_secrets_cb (NMActRequest *req, return; } - nm_device_activate_schedule_stage1_device_prepare (device); + nm_device_activate_schedule_stage1_device_prepare (device, FALSE); } static void @@ -350,7 +343,7 @@ macsec_secrets_get_secrets (NMDeviceMacsec *self, } static gboolean -link_timeout_cb (gpointer user_data) +supplicant_lnk_timeout_cb (gpointer user_data) { NMDeviceMacsec *self = NM_DEVICE_MACSEC (user_data); NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE (self); @@ -359,7 +352,7 @@ link_timeout_cb (gpointer user_data) NMConnection *applied_connection; const char *setting_name; - priv->supplicant_timeout_id = 0; + priv->supplicant.lnk_timeout_id = 0; req = nm_device_get_act_request (dev); @@ -367,7 +360,7 @@ link_timeout_cb (gpointer user_data) nm_device_state_changed (dev, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT); - return FALSE; + return G_SOURCE_REMOVE; } /* Disconnect event during initial authentication and credentials @@ -391,13 +384,98 @@ link_timeout_cb (gpointer user_data) nm_device_state_changed (dev, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT); macsec_secrets_get_secrets (self, setting_name, NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW); - return FALSE; + return G_SOURCE_REMOVE; time_out: _LOGW (LOGD_DEVICE | LOGD_ETHER, "link timed out."); nm_device_state_changed (dev, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT); - return FALSE; + return G_SOURCE_REMOVE; +} + +static void +supplicant_iface_state_is_completed (NMDeviceMacsec *self, + NMSupplicantInterfaceState state) +{ + NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE (self); + + if (state == NM_SUPPLICANT_INTERFACE_STATE_COMPLETED) { + nm_clear_g_source (&priv->supplicant.lnk_timeout_id); + nm_clear_g_source (&priv->supplicant.con_timeout_id); + + nm_device_bring_up (NM_DEVICE (self), TRUE, NULL); + + /* If this is the initial association during device activation, + * schedule the next activation stage. + */ + if (nm_device_get_state (NM_DEVICE (self)) == NM_DEVICE_STATE_CONFIG) { + _LOGI (LOGD_DEVICE, + "Activation: Stage 2 of 5 (Device Configure) successful."); + nm_device_activate_schedule_stage3_ip_config_start (NM_DEVICE (self)); + } + return; + } + + if ( !priv->supplicant.lnk_timeout_id + && !priv->supplicant.con_timeout_id) + priv->supplicant.lnk_timeout_id = g_timeout_add_seconds (SUPPLICANT_LNK_TIMEOUT_SEC, supplicant_lnk_timeout_cb, self); +} + +static void +supplicant_iface_assoc_cb (NMSupplicantInterface *iface, + GError *error, + gpointer user_data) +{ + NMDeviceMacsec *self; + NMDeviceMacsecPrivate *priv; + + if (nm_utils_error_is_cancelled_or_disposing (error)) + return; + + self = user_data; + priv = NM_DEVICE_MACSEC_GET_PRIVATE (self); + + if (error) { + supplicant_interface_release (self); + nm_device_queue_state (NM_DEVICE (self), + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED); + return; + } + + nm_assert (!priv->supplicant.lnk_timeout_id); + nm_assert (!priv->supplicant.is_associated); + + priv->supplicant.is_associated = TRUE; + supplicant_iface_state_is_completed (self, + nm_supplicant_interface_get_state (priv->supplicant.iface)); +} + +static gboolean +supplicant_iface_start (NMDeviceMacsec *self) +{ + NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE (self); + gs_unref_object NMSupplicantConfig *config = NULL; + gs_free_error GError *error = NULL; + + config = build_supplicant_config (self, &error); + if (!config) { + _LOGE (LOGD_DEVICE, + "Activation: couldn't build security configuration: %s", + error->message); + supplicant_interface_release (self); + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED); + return FALSE; + } + + nm_supplicant_interface_disconnect (priv->supplicant.iface); + nm_supplicant_interface_assoc (priv->supplicant.iface, + config, + supplicant_iface_assoc_cb, + self); + return TRUE; } static void @@ -409,76 +487,31 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface, { NMDeviceMacsec *self = NM_DEVICE_MACSEC (user_data); NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE (self); - NMDevice *device = NM_DEVICE (self); - NMSupplicantConfig *config; - NMDeviceState devstate; - GError *error = NULL; NMSupplicantInterfaceState new_state = new_state_i; NMSupplicantInterfaceState old_state = old_state_i; - if (new_state == old_state) - return; - _LOGI (LOGD_DEVICE, "supplicant interface state: %s -> %s", nm_supplicant_interface_state_to_string (old_state), nm_supplicant_interface_state_to_string (new_state)); - devstate = nm_device_get_state (device); - - switch (new_state) { - case NM_SUPPLICANT_INTERFACE_STATE_READY: - config = build_supplicant_config (self, &error); - if (config) { - nm_supplicant_interface_assoc (priv->supplicant.iface, config, - supplicant_iface_assoc_cb, self); - g_object_unref (config); - } else { - _LOGE (LOGD_DEVICE, - "Activation: couldn't build security configuration: %s", - error->message); - g_clear_error (&error); - - nm_device_state_changed (device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED); - } - break; - case NM_SUPPLICANT_INTERFACE_STATE_COMPLETED: - 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, - * schedule the next activation stage. - */ - if (devstate == NM_DEVICE_STATE_CONFIG) { - _LOGI (LOGD_DEVICE, - "Activation: Stage 2 of 5 (Device Configure) successful."); - nm_device_activate_schedule_stage3_ip_config_start (device); - } - break; - case NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED: - if ((devstate == NM_DEVICE_STATE_ACTIVATED) || nm_device_is_activating (device)) { - /* Start the link timeout so we allow some time for reauthentication */ - if (!priv->supplicant_timeout_id) - priv->supplicant_timeout_id = g_timeout_add_seconds (15, link_timeout_cb, device); - } - break; - case NM_SUPPLICANT_INTERFACE_STATE_DOWN: + if (new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) { supplicant_interface_release (self); + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + return; + } - if ((devstate == NM_DEVICE_STATE_ACTIVATED) || nm_device_is_activating (device)) { - nm_device_state_changed (device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); - } - break; - default: - ; + if (old_state == NM_SUPPLICANT_INTERFACE_STATE_STARTING) { + if (!supplicant_iface_start (self)) + return; } + + if (priv->supplicant.is_associated) + supplicant_iface_state_is_completed (self, new_state); } -static NMActStageReturn +static gboolean handle_auth_or_fail (NMDeviceMacsec *self, NMActRequest *req, gboolean new_secrets) @@ -487,7 +520,7 @@ handle_auth_or_fail (NMDeviceMacsec *self, NMConnection *applied_connection; if (!nm_device_auth_retries_try_next (NM_DEVICE (self))) - 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); @@ -497,13 +530,13 @@ handle_auth_or_fail (NMDeviceMacsec *self, setting_name = nm_connection_need_secrets (applied_connection, NULL); if (!setting_name) { _LOGI (LOGD_DEVICE, "Cleared secrets, but setting didn't need any secrets."); - return NM_ACT_STAGE_RETURN_FAILURE; + return FALSE; } 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)); - return NM_ACT_STAGE_RETURN_POSTPONE; + return TRUE; } static gboolean @@ -526,11 +559,10 @@ supplicant_connection_timeout_cb (gpointer user_data) "Activation: (macsec) association took too long."); supplicant_interface_release (self); - req = nm_device_get_act_request (device); - g_assert (req); + req = nm_device_get_act_request (device); connection = nm_act_request_get_settings_connection (req); - g_assert (connection); + g_return_val_if_fail (connection, G_SOURCE_REMOVE); /* Ask for new secrets only if we've never activated this connection * before. If we've connected before, don't bother the user with dialogs, @@ -539,48 +571,73 @@ supplicant_connection_timeout_cb (gpointer user_data) if (nm_settings_connection_get_timestamp (connection, ×tamp)) new_secrets = !timestamp; - if (handle_auth_or_fail (self, req, new_secrets) == NM_ACT_STAGE_RETURN_POSTPONE) - _LOGW (LOGD_DEVICE, "Activation: (macsec) asking for new secrets"); - else + if (!handle_auth_or_fail (self, req, new_secrets)) { nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NO_SECRETS); + return G_SOURCE_REMOVE; + } + + _LOGW (LOGD_DEVICE, "Activation: (macsec) asking for new secrets"); - return FALSE; + if ( !priv->supplicant.lnk_timeout_id + && priv->supplicant.iface) { + NMSupplicantInterfaceState state; + + state = nm_supplicant_interface_get_state (priv->supplicant.iface); + if (state != NM_SUPPLICANT_INTERFACE_STATE_COMPLETED + && nm_supplicant_interface_state_is_operational (state)) + priv->supplicant.lnk_timeout_id = g_timeout_add_seconds (SUPPLICANT_LNK_TIMEOUT_SEC, supplicant_lnk_timeout_cb, self); + } + + return G_SOURCE_REMOVE; } -static gboolean -supplicant_interface_init (NMDeviceMacsec *self) +static void +supplicant_interface_create_cb (NMSupplicantManager *supplicant_manager, + NMSupplMgrCreateIfaceHandle *handle, + NMSupplicantInterface *iface, + GError *error, + gpointer user_data) { - NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE (self); - NMDevice *parent; + NMDeviceMacsec *self; + NMDeviceMacsecPrivate *priv; guint timeout; - parent = nm_device_parent_get_device (NM_DEVICE (self)); - g_return_val_if_fail (parent, FALSE); + if (nm_utils_error_is_cancelled (error)) + return; - supplicant_interface_release (self); + self = user_data; + priv = NM_DEVICE_MACSEC_GET_PRIVATE (self); - priv->supplicant.iface = nm_supplicant_manager_create_interface (priv->supplicant.mgr, - nm_device_get_iface (parent), - NM_SUPPLICANT_DRIVER_MACSEC); + nm_assert (priv->supplicant.create_handle == handle); - if (!priv->supplicant.iface) { + priv->supplicant.create_handle = NULL; + + if (error) { _LOGE (LOGD_DEVICE, - "Couldn't initialize supplicant interface"); - return FALSE; + "Couldn't initialize supplicant interface: %s", + error->message); + supplicant_interface_release (self); + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + return; } - /* Listen for its state signals */ + priv->supplicant.iface = g_object_ref (iface); + priv->supplicant.is_associated = FALSE; + priv->supplicant.iface_state_id = g_signal_connect (priv->supplicant.iface, NM_SUPPLICANT_INTERFACE_STATE, G_CALLBACK (supplicant_iface_state_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; + + if (nm_supplicant_interface_state_is_operational (nm_supplicant_interface_get_state (iface))) + supplicant_iface_start (self); } static NMActStageReturn @@ -589,8 +646,9 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) NMDeviceMacsec *self = NM_DEVICE_MACSEC (device); NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE (self); NMConnection *connection; - NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; + NMDevice *parent; const char *setting_name; + int ifindex; connection = nm_device_get_applied_connection (NM_DEVICE (self)); @@ -608,21 +666,31 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) "Activation: connection '%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_POSTPONE) + if (!handle_auth_or_fail (self, req, FALSE)) { 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.", - nm_connection_get_id (connection)); + return NM_ACT_STAGE_RETURN_FAILURE; + } - if (supplicant_interface_init (self)) - ret = NM_ACT_STAGE_RETURN_POSTPONE; - else - NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_CONFIG_FAILED); + return NM_ACT_STAGE_RETURN_POSTPONE; } - return ret; + _LOGI (LOGD_DEVICE | LOGD_ETHER, + "Activation: connection '%s' requires no security. No secrets needed.", + nm_connection_get_id (connection)); + + supplicant_interface_release (self); + + parent = nm_device_parent_get_device (NM_DEVICE (self)); + g_return_val_if_fail (parent, NM_ACT_STAGE_RETURN_FAILURE); + ifindex = nm_device_get_ifindex (parent); + g_return_val_if_fail (ifindex > 0, NM_ACT_STAGE_RETURN_FAILURE); + + priv->supplicant.create_handle = nm_supplicant_manager_create_interface (priv->supplicant.mgr, + ifindex, + NM_SUPPLICANT_DRIVER_MACSEC, + supplicant_interface_create_cb, + self); + return NM_ACT_STAGE_RETURN_POSTPONE; } static void |