about summary refs log tree commit diff
path: root/src/core/vpn/nm-vpn-connection.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/vpn/nm-vpn-connection.c')
-rw-r--r--src/core/vpn/nm-vpn-connection.c116
1 files changed, 75 insertions, 41 deletions
diff --git a/src/core/vpn/nm-vpn-connection.c b/src/core/vpn/nm-vpn-connection.c
index 3dba9ff6..de0c9f71 100644
--- a/src/core/vpn/nm-vpn-connection.c
+++ b/src/core/vpn/nm-vpn-connection.c
@@ -2099,20 +2099,12 @@ _dbus_signal_ip_config_cb(NMVpnConnection *self, int addr_family, GVariant *dict
                                                  NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4))
                 nm_l3_config_data_add_route(l3cd, addr_family, route, NULL);
         }
-    } else if (IS_IPv4 ? g_variant_lookup(dict, NM_VPN_PLUGIN_IP4_CONFIG_ROUTES, "aau", &var_iter)
-                       : g_variant_lookup(dict,
-                                          NM_VPN_PLUGIN_IP6_CONFIG_ROUTES,
-                                          "a(ayuayu)",
-                                          &var_iter)) {
-        _nm_unused nm_auto_free_variant_iter GVariantIter *var_iter_ref_owner = var_iter;
-        NMPlatformIPXRoute                                 route              = {};
-        guint32                                            plen;
-        GVariant                                          *next_hop;
-        GVariant                                          *dest;
-        guint32                                            prefix;
-        guint32                                            metric;
+    } else if (IS_IPv4) {
+        if (g_variant_lookup(dict, NM_VPN_PLUGIN_IP4_CONFIG_ROUTES, "aau", &var_iter)) {
+            _nm_unused nm_auto_free_variant_iter GVariantIter *var_iter_ref_owner = var_iter;
+            NMPlatformIPXRoute                                 route              = {};
+            guint32                                            plen;
 
-        if (IS_IPv4) {
             while (g_variant_iter_next(var_iter, "@au", &v)) {
                 _nm_unused gs_unref_variant GVariant *v_ref_owner = v;
 
@@ -2151,42 +2143,84 @@ _dbus_signal_ip_config_cb(NMVpnConnection *self, int addr_family, GVariant *dict
                     break;
                 }
             }
-        } else {
-            while (
-                g_variant_iter_next(var_iter, "(@ayu@ayu)", &dest, &prefix, &next_hop, &metric)) {
-                _nm_unused gs_unref_variant GVariant *next_hop_ref_owner = next_hop;
-                _nm_unused gs_unref_variant GVariant *dest_ref_owner     = dest;
+        }
+    } else {
+        _nm_unused nm_auto_free_variant_iter GVariantIter *var_iter_ref_owner = NULL;
+        NMPlatformIPXRoute                                 route              = {};
+        guint32                                            prefix;
+        guint32                                            metric;
+        NMOptionBool                                       new_signature = NM_OPTION_BOOL_DEFAULT;
+
+        /* IPv6 and no "preserve-routes" */
+
+        if (g_variant_lookup(dict, NM_VPN_PLUGIN_IP6_CONFIG_ROUTES, "a(ayuayu)", &var_iter))
+            new_signature = FALSE;
+        else if (g_variant_lookup(dict, NM_VPN_PLUGIN_IP6_CONFIG_ROUTES, "a(ayuayuay)", &var_iter))
+            new_signature = TRUE;
+        else
+            var_iter = NULL;
+
+        var_iter_ref_owner = var_iter;
+
+        while (TRUE) {
+            gs_unref_variant GVariant *next_hop = NULL;
+            gs_unref_variant GVariant *dest     = NULL;
+            gs_unref_variant GVariant *pref_src = NULL;
+
+            if (new_signature == NM_OPTION_BOOL_DEFAULT) {
+                break;
+            } else if (new_signature) {
+                if (!g_variant_iter_next(var_iter,
+                                         "(@ayu@ayu@ay)",
+                                         &dest,
+                                         &prefix,
+                                         &next_hop,
+                                         &metric,
+                                         &pref_src))
+                    break;
+            } else {
+                if (!g_variant_iter_next(var_iter,
+                                         "(@ayu@ayu)",
+                                         &dest,
+                                         &prefix,
+                                         &next_hop,
+                                         &metric))
+                    break;
+            }
 
-                if (prefix > 128)
-                    continue;
+            if (prefix > 128)
+                continue;
 
-                route.r6 = (NMPlatformIP6Route){
-                    .plen       = prefix,
-                    .table_any  = TRUE,
-                    .metric_any = TRUE,
-                    .rt_source  = NM_IP_CONFIG_SOURCE_VPN,
-                };
+            route.r6 = (NMPlatformIP6Route){
+                .plen       = prefix,
+                .table_any  = TRUE,
+                .metric_any = TRUE,
+                .rt_source  = NM_IP_CONFIG_SOURCE_VPN,
+            };
 
-                if (!nm_ip_addr_set_from_variant(AF_INET6, &route.r6.network, dest, NULL))
-                    continue;
+            if (!nm_ip_addr_set_from_variant(AF_INET6, &route.r6.network, dest, NULL))
+                continue;
 
-                nm_ip_addr_set_from_variant(AF_INET6, &route.r6.gateway, next_hop, NULL);
+            if (pref_src
+                && !nm_ip_addr_set_from_variant(AF_INET6, &route.r6.pref_src, pref_src, NULL))
+                continue;
 
-                nm_ip6_addr_clear_host_address(&route.r6.network, &route.r6.network, route.r6.plen);
+            nm_ip_addr_set_from_variant(AF_INET6, &route.r6.gateway, next_hop, NULL);
 
-                if (!IN6_IS_ADDR_UNSPECIFIED(&priv->ip_data_6.gw_external.addr6)
-                    && IN6_ARE_ADDR_EQUAL(&route.r6.network, &priv->ip_data_6.gw_external.addr6)
-                    && route.r6.plen == 128) {
-                    /* Ignore host routes to the VPN gateway since NM adds one itself.
-                     * Since NM knows more about the routing situation than the VPN
-                     * server, we want to use the NM created route instead of whatever
-                     * the server provides.
-                     */
-                    continue;
-                }
+            nm_ip6_addr_clear_host_address(&route.r6.network, &route.r6.network, route.r6.plen);
 
-                nm_l3_config_data_add_route_6(l3cd, &route.r6);
+            if (!IN6_IS_ADDR_UNSPECIFIED(&priv->ip_data_6.gw_external.addr6)
+                && IN6_ARE_ADDR_EQUAL(&route.r6.network, &priv->ip_data_6.gw_external.addr6)
+                && route.r6.plen == 128) {
+                /* Ignore host routes to the VPN gateway since NM adds one itself.
+                 * Since NM knows more about the routing situation than the VPN
+                 * server, we want to use the NM created route instead of whatever
+                 * the server provides.
+                 */
+                continue;
             }
+
+            nm_l3_config_data_add_route_6(l3cd, &route.r6);
         }
     }