From ef6ad048214ce2254264455aa4e04f0e5cf2d536 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Sun, 3 Feb 2019 11:15:47 +0100 Subject: [PATCH] vpn: add route to vpn gw when parent has a default device route When the parent device has a device default route (i.e. without gateway) and we establish a VPN on top of it, 'ip route get' for the VPN gateway returns a device route, which is the same result we get for an unreachable VPN gateway. However it is necessary to add the route to the gateway or otherwise it will possibly become unreachable once the VPN gets activated. https://gitlab.freedesktop.org/NetworkManager/NetworkManager/issues/93 (cherry picked from commit 797eab2f6b97db35d78c558ca2b37cff1cdc936f) (cherry picked from commit 6808cd48aad6f03e22047ea36ecff58ed0266435) --- src/vpn/nm-vpn-connection.c | 40 ++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/src/vpn/nm-vpn-connection.c b/src/vpn/nm-vpn-connection.c index 91acf07e77..6f4bc20569 100644 --- a/src/vpn/nm-vpn-connection.c +++ b/src/vpn/nm-vpn-connection.c @@ -729,15 +729,23 @@ add_ip4_vpn_gateway_route (NMIP4Config *config, const NMPlatformIP4Route *r = NMP_OBJECT_CAST_IP4_ROUTE (route_resolved); if (r->ifindex == ifindex) { + const NMPObject *obj; + /* `ip route get` always resolves the route, even if the destination is unreachable. * In which case, it pretends the destination is directly reachable. * - * So, only accept direct routes, if @vpn_gw is a private network. */ - if ( nm_platform_route_table_is_main (r->table_coerced) - && ( r->gateway - || nm_utils_ip_is_site_local (AF_INET, &vpn_gw))) { - parent_gw = r->gateway; - has_parent_gw = TRUE; + * So, only accept direct routes if @vpn_gw is a private network + * or if the parent device also has a direct default route */ + if (nm_platform_route_table_is_main (r->table_coerced)) { + if (r->gateway) { + parent_gw = r->gateway; + has_parent_gw = TRUE; + } else if (nm_utils_ip_is_site_local (AF_INET, &vpn_gw)) { + has_parent_gw = TRUE; + } else if ( (obj = nm_device_get_best_default_route (parent_device, AF_INET)) + && !NMP_OBJECT_CAST_IP4_ROUTE (obj)->gateway) { + has_parent_gw = TRUE; + } } } } @@ -803,15 +811,23 @@ add_ip6_vpn_gateway_route (NMIP6Config *config, const NMPlatformIP6Route *r = NMP_OBJECT_CAST_IP6_ROUTE (route_resolved); if (r->ifindex == ifindex) { + const NMPObject *obj; + /* `ip route get` always resolves the route, even if the destination is unreachable. * In which case, it pretends the destination is directly reachable. * - * So, only accept direct routes, if @vpn_gw is a private network. */ - if ( nm_platform_route_table_is_main (r->table_coerced) - && ( !IN6_IS_ADDR_UNSPECIFIED (&r->gateway) - || nm_utils_ip_is_site_local (AF_INET6, &vpn_gw))) { - parent_gw = &r->gateway; - has_parent_gw = TRUE; + * So, only accept direct routes if @vpn_gw is a private network + * or if the parent device also has a direct default route */ + if (nm_platform_route_table_is_main (r->table_coerced)) { + if (!IN6_IS_ADDR_UNSPECIFIED (&r->gateway)) { + parent_gw = &r->gateway; + has_parent_gw = TRUE; + } else if (nm_utils_ip_is_site_local (AF_INET6, &vpn_gw)) { + has_parent_gw = TRUE; + } else if ( (obj = nm_device_get_best_default_route (parent_device, AF_INET6)) + && IN6_IS_ADDR_UNSPECIFIED (&NMP_OBJECT_CAST_IP6_ROUTE (obj)->gateway)) { + has_parent_gw = TRUE; + } } } }