vpn: use nm-platform for default routes

This commit is contained in:
Pavel Šimerda 2013-05-27 17:24:30 +02:00
parent 91f8de7936
commit 96219b1d86
4 changed files with 93 additions and 52 deletions

@ -1 +1 @@
Subproject commit 72d437cf9349ccfb8723ea09b381b17c0a23ab88
Subproject commit 8e11654015d91b62049315aa7f9a459d0ec2c82e

View file

@ -144,13 +144,13 @@ nm_system_device_set_ip4_route (int ifindex,
return route;
}
struct rtnl_route *
NMPlatformIP4Route *
nm_system_add_ip4_vpn_gateway_route (NMDevice *parent_device, guint32 vpn_gw)
{
NMIP4Config *parent_config;
guint32 parent_gw = 0, parent_prefix = 0, i;
NMIP4Address *tmp;
struct rtnl_route *route = NULL;
NMPlatformIP4Route *route = g_new0 (NMPlatformIP4Route, 1);
g_return_val_if_fail (NM_IS_DEVICE (parent_device), NULL);
g_return_val_if_fail (vpn_gw != 0, NULL);
@ -171,19 +171,37 @@ nm_system_add_ip4_vpn_gateway_route (NMDevice *parent_device, guint32 vpn_gw)
}
}
if (!parent_gw)
if (!parent_gw) {
g_free (route);
return NULL;
}
route->ifindex = nm_device_get_ip_ifindex (parent_device);
route->network = vpn_gw;
route->plen = 32;
route->gateway = parent_gw;
route->metric = 1024;
route->mss = nm_ip4_config_get_mss (parent_config);
/* If the VPN gateway is in the same subnet as one of the parent device's
* IP addresses, don't add the host route to it, but a route through the
* parent device.
*/
if (ip4_dest_in_same_subnet (parent_config, vpn_gw, parent_prefix)) {
route = nm_system_device_set_ip4_route (nm_device_get_ip_ifindex (parent_device),
vpn_gw, 32, 0, 0, nm_ip4_config_get_mss (parent_config));
} else {
route = nm_system_device_set_ip4_route (nm_device_get_ip_ifindex (parent_device),
vpn_gw, 32, parent_gw, 0, nm_ip4_config_get_mss (parent_config));
if (ip4_dest_in_same_subnet (parent_config, vpn_gw, parent_prefix))
route->gateway = 0;
if (!nm_platform_ip4_route_add (route->ifindex,
route->network,
route->plen,
route->gateway,
route->metric,
route->mss)) {
g_free (route);
nm_log_err (LOGD_DEVICE | LOGD_IP4,
"(%s): failed to add IPv4 route to VPN gateway: %s",
nm_device_get_iface (parent_device),
nm_platform_get_error_msg ());
return NULL;
}
return route;
@ -354,16 +372,16 @@ ip6_dest_in_same_subnet (NMIP6Config *config, const struct in6_addr *dest, guint
return FALSE;
}
struct rtnl_route *
NMPlatformIP6Route *
nm_system_add_ip6_vpn_gateway_route (NMDevice *parent_device,
const struct in6_addr *vpn_gw)
{
NMIP6Config *parent_config;
const struct in6_addr *parent_gw = NULL;
guint32 parent_prefix = 0;
int i, err;
int i;
NMIP6Address *tmp;
struct rtnl_route *route = NULL;
NMPlatformIP6Route *route = g_new0 (NMPlatformIP6Route, 1);
g_return_val_if_fail (NM_IS_DEVICE (parent_device), NULL);
g_return_val_if_fail (vpn_gw != NULL, NULL);
@ -385,28 +403,39 @@ nm_system_add_ip6_vpn_gateway_route (NMDevice *parent_device,
}
}
if (!parent_gw)
if (!parent_gw) {
g_free (route);
return NULL;
if (ip6_dest_in_same_subnet (parent_config, vpn_gw, parent_prefix)) {
err = nm_system_set_ip6_route (nm_device_get_ip_ifindex (parent_device),
vpn_gw, 128, NULL, 0,
nm_ip6_config_get_mss (parent_config),
RTPROT_UNSPEC, RT_TABLE_UNSPEC,
&route);
} else {
err = nm_system_set_ip6_route (nm_device_get_ip_ifindex (parent_device),
vpn_gw, 128, parent_gw, 0,
nm_ip6_config_get_mss (parent_config),
RTPROT_UNSPEC, RT_TABLE_UNSPEC,
&route);
}
if (err) {
route->ifindex = nm_device_get_ip_ifindex (parent_device);
route->network = *vpn_gw;
route->plen = 128;
route->gateway = *parent_gw;
route->metric = 1024;
route->mss = nm_ip6_config_get_mss (parent_config);
/* If the VPN gateway is in the same subnet as one of the parent device's
* IP addresses, don't add the host route to it, but a route through the
* parent device.
*/
if (ip6_dest_in_same_subnet (parent_config, vpn_gw, parent_prefix))
route->gateway = in6addr_any;
if (!nm_platform_ip6_route_add (route->ifindex,
route->network,
route->plen,
route->gateway,
route->metric,
route->mss)) {
g_free (route);
nm_log_err (LOGD_DEVICE | LOGD_IP6,
"(%s): failed to add IPv6 route to VPN gateway (%d)",
nm_device_get_iface (parent_device), err);
"(%s): failed to add IPv6 route to VPN gateway: %s",
nm_device_get_iface (parent_device),
nm_platform_get_error_msg ());
return NULL;
}
return route;
}

View file

@ -25,6 +25,7 @@
#include <glib.h>
#include <netlink/route/route.h>
#include "nm-platform.h"
#include "nm-device.h"
#include "nm-ip4-config.h"
#include "nm-setting-bond.h"
@ -52,9 +53,9 @@ gboolean nm_system_replace_default_ip6_route_vpn (int ifindex,
int parent_ifindex,
guint32 parent_mss);
struct rtnl_route *nm_system_add_ip4_vpn_gateway_route (NMDevice *parent_device,
NMPlatformIP4Route *nm_system_add_ip4_vpn_gateway_route (NMDevice *parent_device,
guint32 vpn_gw);
struct rtnl_route *nm_system_add_ip6_vpn_gateway_route (NMDevice *parent_device,
NMPlatformIP6Route *nm_system_add_ip6_vpn_gateway_route (NMDevice *parent_device,
const struct in6_addr *vpn_gw);
gboolean nm_system_iface_flush_addresses (int ifindex, int family);

View file

@ -41,7 +41,6 @@
#include "nm-active-connection.h"
#include "nm-dbus-glib-types.h"
#include "NetworkManagerUtils.h"
#include "nm-netlink-utils.h"
#include "nm-glib-compat.h"
#include "settings/nm-settings-connection.h"
#include "nm-dispatcher.h"
@ -92,7 +91,8 @@ typedef struct {
char *banner;
guint32 mtu;
struct rtnl_route *gw_route;
NMPlatformIP4Route *ip4_gw_route;
NMPlatformIP6Route *ip6_gw_route;
} NMVPNConnectionPrivate;
#define NM_VPN_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_VPN_CONNECTION, NMVPNConnectionPrivate))
@ -168,10 +168,22 @@ vpn_cleanup (NMVPNConnection *connection)
nm_platform_address_flush (priv->ip_ifindex);
}
if (priv->gw_route) {
nm_netlink_route_delete (priv->gw_route);
rtnl_route_put (priv->gw_route);
priv->gw_route = NULL;
if (priv->ip4_gw_route) {
nm_platform_ip4_route_delete (
priv->ip4_gw_route->ifindex,
priv->ip4_gw_route->network,
priv->ip4_gw_route->plen,
priv->ip4_gw_route->metric);
g_clear_pointer (&priv->ip4_gw_route, g_free);
}
if (priv->ip6_gw_route) {
nm_platform_ip6_route_delete (
priv->ip6_gw_route->ifindex,
priv->ip6_gw_route->network,
priv->ip6_gw_route->plen,
priv->ip6_gw_route->metric);
g_clear_pointer (&priv->ip6_gw_route, g_free);
}
g_free (priv->banner);
@ -309,9 +321,8 @@ device_ip4_config_changed (NMDevice *device,
/* Re-add the VPN gateway route */
if (priv->ip4_external_gw) {
if (priv->gw_route)
rtnl_route_put (priv->gw_route);
priv->gw_route = nm_system_add_ip4_vpn_gateway_route (priv->parent_dev,
g_free (&priv->ip4_gw_route);
priv->ip4_gw_route = nm_system_add_ip4_vpn_gateway_route (priv->parent_dev,
priv->ip4_external_gw);
}
}
@ -330,10 +341,9 @@ device_ip6_config_changed (NMDevice *device,
/* Re-add the VPN gateway route */
if (priv->ip6_external_gw) {
if (priv->gw_route)
rtnl_route_put (priv->gw_route);
priv->gw_route = nm_system_add_ip6_vpn_gateway_route (priv->parent_dev,
priv->ip6_external_gw);
g_free (priv->ip6_gw_route);
priv->ip6_gw_route = nm_system_add_ip6_vpn_gateway_route (priv->parent_dev,
priv->ip6_external_gw);
}
}
@ -612,14 +622,14 @@ nm_vpn_connection_apply_config (NMVPNConnection *connection)
}
/* Add any explicit route to the VPN gateway through the parent device */
g_clear_pointer (&priv->ip4_gw_route, g_free);
g_clear_pointer (&priv->ip6_gw_route, g_free);
if (priv->ip4_external_gw) {
priv->gw_route = nm_system_add_ip4_vpn_gateway_route (priv->parent_dev,
priv->ip4_gw_route = nm_system_add_ip4_vpn_gateway_route (priv->parent_dev,
priv->ip4_external_gw);
} else if (priv->ip6_external_gw) {
priv->gw_route = nm_system_add_ip6_vpn_gateway_route (priv->parent_dev,
priv->ip6_gw_route = nm_system_add_ip6_vpn_gateway_route (priv->parent_dev,
priv->ip6_external_gw);
} else {
priv->gw_route = NULL;
}
nm_log_info (LOGD_VPN, "VPN connection '%s' (IP Config Get) complete.",
@ -689,7 +699,7 @@ process_generic_config (NMVPNConnection *connection,
/* Grab the interface index for address/routing operations */
priv->ip_ifindex = nm_platform_link_get_ifindex (priv->ip_iface);
if (priv->ip_ifindex < 0) {
if (!priv->ip_ifindex) {
nm_log_err (LOGD_VPN, "(%s): failed to look up VPN interface index", priv->ip_iface);
nm_vpn_connection_config_maybe_complete (connection, FALSE);
return FALSE;
@ -1500,8 +1510,9 @@ dispose (GObject *object)
}
priv->disposed = TRUE;
if (priv->gw_route)
rtnl_route_put (priv->gw_route);
g_clear_pointer (&priv->ip4_gw_route, g_free);
g_clear_pointer (&priv->ip6_gw_route, g_free);
if (priv->ip6_internal_gw)
g_free (priv->ip6_internal_gw);
if (priv->ip6_external_gw)