diff --git a/src/core/vpn/nm-vpn-connection.c b/src/core/vpn/nm-vpn-connection.c index 0b36459cf7..54478c5362 100644 --- a/src/core/vpn/nm-vpn-connection.c +++ b/src/core/vpn/nm-vpn-connection.c @@ -175,6 +175,7 @@ typedef struct { }; GSource *init_fail_on_idle_source; + GSource *check_device_added_idle_source; GSource *connect_timeout_source; GCancellable *main_cancellable; GVariant *connect_hash; @@ -229,6 +230,8 @@ static void _set_vpn_state(NMVpnConnection *self, static void _l3cfg_notify_cb(NML3Cfg *l3cfg, const NML3ConfigNotifyData *notify_data, NMVpnConnection *self); +static void _check_complete(NMVpnConnection *self, gboolean success); + /*****************************************************************************/ #define _NMLOG_DOMAIN LOGD_VPN @@ -1405,6 +1408,18 @@ fw_change_zone_cb(NMFirewalldManager *firewalld_manager, _apply_config(self); } +static gboolean +_check_device_added_idle_cb(gpointer user_data) +{ + NMVpnConnection *self = user_data; + NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE(self); + + _check_complete(self, TRUE); + nm_clear_g_source_inst(&priv->check_device_added_idle_source); + + return G_SOURCE_CONTINUE; +} + static void _check_complete(NMVpnConnection *self, gboolean success) { @@ -1442,13 +1457,24 @@ _check_complete(NMVpnConnection *self, gboolean success) connection = _get_applied_connection(self); ifindex = nm_vpn_connection_get_ip_ifindex(self, FALSE); + device = nm_manager_get_device_by_ifindex(NM_MANAGER_GET, ifindex); + + /* We have a defined interface index, but the device is not processed yet. + * The processing of the new kernel link could be queued in an idle handler, + * so schedule an idle handler once to check if the device has been processed. + */ + if (ifindex > 0 && !device && !priv->check_device_added_idle_source) { + priv->check_device_added_idle_source = + nm_g_idle_add_source(_check_device_added_idle_cb, self); + return; + } + /* Use nm_device_create_l3_config_data_from_connection here if possible. This ensures that * connection properties like mdns, llmnr, dns-over-tls or dnssec are applied to vpn connections * If this vpn connection does not have its own device resort to nm_l3_config_data_new_from_connection * since we can't properly apply these properties anyway */ if (ifindex > 0) { - device = nm_manager_get_device_by_ifindex(NM_MANAGER_GET, ifindex); nm_assert(device); l3cd = nm_device_create_l3_config_data_from_connection(device, connection); } else { @@ -3042,6 +3068,8 @@ dispose(GObject *object) nm_clear_g_source_inst(&priv->init_fail_on_idle_source); + nm_clear_g_source_inst(&priv->check_device_added_idle_source); + nm_clear_g_cancellable(&priv->main_cancellable); nm_clear_g_source_inst(&priv->start_timeout_source);