about summary refs log tree commit diff
path: root/src/core/vpn
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/vpn')
-rw-r--r--src/core/vpn/nm-vpn-connection.c51
1 files changed, 48 insertions, 3 deletions
diff --git a/src/core/vpn/nm-vpn-connection.c b/src/core/vpn/nm-vpn-connection.c
index 22364ef9..54478c53 100644
--- a/src/core/vpn/nm-vpn-connection.c
+++ b/src/core/vpn/nm-vpn-connection.c
@@ -26,10 +26,12 @@
 #include "nm-active-connection.h"
 #include "nm-config.h"
 #include "nm-dbus-manager.h"
+#include "devices/nm-device.h"
 #include "nm-dispatcher.h"
 #include "nm-firewalld-manager.h"
 #include "nm-ip-config.h"
 #include "nm-l3-config-data.h"
+#include "nm-manager.h"
 #include "nm-netns.h"
 #include "nm-pacrunner-manager.h"
 #include "nm-vpn-manager.h"
@@ -173,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;
@@ -227,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
@@ -1403,15 +1408,29 @@ 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)
 {
     NMVpnConnectionPrivate                 *priv = NM_VPN_CONNECTION_GET_PRIVATE(self);
     nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
     NMConnection                           *connection;
+    NMDevice                               *device;
     NMSettingConnection                    *s_con;
     const char                             *zone;
     const char                             *iface;
+    int                                     ifindex;
 
     if (priv->vpn_state < STATE_IP_CONFIG_GET || priv->vpn_state > STATE_ACTIVATED)
         return;
@@ -1437,10 +1456,34 @@ _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;
+    }
 
-    l3cd = nm_l3_config_data_new_from_connection(nm_netns_get_multi_idx(priv->netns),
-                                                 nm_vpn_connection_get_ip_ifindex(self, TRUE),
-                                                 connection);
+    /* 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) {
+        nm_assert(device);
+        l3cd = nm_device_create_l3_config_data_from_connection(device, connection);
+    } else {
+        l3cd = nm_l3_config_data_new_from_connection(nm_netns_get_multi_idx(priv->netns),
+                                                     nm_vpn_connection_get_ip_ifindex(self, TRUE),
+                                                     connection);
+        _LOGD("VPN connection does not have its own device. Some connection properties won't be "
+              "supported.");
+    }
 
     nm_l3_config_data_set_allow_routes_without_address(l3cd, AF_INET, TRUE);
     nm_l3_config_data_set_allow_routes_without_address(l3cd, AF_INET6, TRUE);
@@ -3025,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);