core: fix connection matching with dynamic IPv6 routes

https://bugzilla.gnome.org/show_bug.cgi?id=729203
https://bugzilla.redhat.com/show_bug.cgi?id=1086237
This commit is contained in:
Dan Winship 2014-06-06 10:26:19 -04:00
commit 9df69b1029
18 changed files with 263 additions and 105 deletions

View file

@ -2483,6 +2483,7 @@ aipd_get_ip4_config (NMDevice *self, guint32 lla)
route.network = htonl (0xE0000000L);
route.plen = 4;
route.source = NM_PLATFORM_SOURCE_IP4LL;
route.metric = nm_device_get_priority (self);
nm_ip4_config_add_route (config, &route);
return config;
@ -2885,6 +2886,7 @@ dhcp4_start (NMDevice *self,
nm_device_get_ip_iface (self),
tmp,
nm_connection_get_uuid (connection),
nm_device_get_priority (self),
s_ip4,
priv->dhcp_timeout,
priv->dhcp_anycast_address);
@ -3325,6 +3327,7 @@ dhcp6_start (NMDevice *self,
nm_device_get_ip_iface (self),
tmp,
nm_connection_get_uuid (connection),
nm_device_get_priority (self),
nm_connection_get_setting_ip6_config (connection),
priv->dhcp_timeout,
priv->dhcp_anycast_address,
@ -3623,6 +3626,7 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *device
route.plen = discovered_route->plen;
route.gateway = discovered_route->gateway;
route.source = NM_PLATFORM_SOURCE_RDISC;
route.metric = nm_device_get_priority (device);
nm_ip6_config_add_route (priv->ac_ip6_config, &route);
}
@ -5279,7 +5283,7 @@ nm_device_set_ip4_config (NMDevice *self,
/* Always commit to nm-platform to update lifetimes */
if (commit && new_config) {
success = nm_ip4_config_commit (new_config, ip_ifindex, nm_device_get_priority (self));
success = nm_ip4_config_commit (new_config, ip_ifindex);
if (!success)
reason_local = NM_DEVICE_STATE_REASON_CONFIG_FAILED;
}
@ -5387,7 +5391,7 @@ nm_device_set_ip6_config (NMDevice *self,
/* Always commit to nm-platform to update lifetimes */
if (commit && new_config) {
success = nm_ip6_config_commit (new_config, ip_ifindex, nm_device_get_priority (self));
success = nm_ip6_config_commit (new_config, ip_ifindex);
if (!success)
reason_local = NM_DEVICE_STATE_REASON_CONFIG_FAILED;
}

View file

@ -39,6 +39,7 @@ typedef struct {
GByteArray * hwaddr;
gboolean ipv6;
char * uuid;
guint priority;
guint32 timeout;
GByteArray * duid;
@ -72,6 +73,7 @@ enum {
PROP_HWADDR,
PROP_IPV6,
PROP_UUID,
PROP_PRIORITY,
PROP_TIMEOUT,
LAST_PROP
};
@ -795,10 +797,12 @@ nm_dhcp_client_foreach_option (NMDHCPClient *self,
/********************************************/
static gboolean
ip4_process_dhcpcd_rfc3442_routes (const char *str,
ip4_process_dhcpcd_rfc3442_routes (NMDHCPClient *self,
const char *str,
NMIP4Config *ip4_config,
guint32 *gwaddr)
{
NMDHCPClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
char **routes, **r;
gboolean have_routes = FALSE;
@ -847,6 +851,7 @@ ip4_process_dhcpcd_rfc3442_routes (const char *str,
route.plen = rt_cidr;
route.gateway = rt_route;
route.source = NM_PLATFORM_SOURCE_DHCP;
route.metric = priv->priority;
nm_ip4_config_add_route (ip4_config, &route);
}
}
@ -918,10 +923,12 @@ error:
}
static gboolean
ip4_process_dhclient_rfc3442_routes (const char *str,
ip4_process_dhclient_rfc3442_routes (NMDHCPClient *self,
const char *str,
NMIP4Config *ip4_config,
guint32 *gwaddr)
{
NMDHCPClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
char **octets, **o;
gboolean have_routes = FALSE;
NMPlatformIP4Route route;
@ -950,6 +957,7 @@ ip4_process_dhclient_rfc3442_routes (const char *str,
/* normal route */
route.source = NM_PLATFORM_SOURCE_DHCP;
route.metric = priv->priority;
nm_ip4_config_add_route (ip4_config, &route);
nm_log_info (LOGD_DHCP4, " classless static route %s/%d gw %s",
@ -964,7 +972,8 @@ out:
}
static gboolean
ip4_process_classless_routes (GHashTable *options,
ip4_process_classless_routes (NMDHCPClient *self,
GHashTable *options,
NMIP4Config *ip4_config,
guint32 *gwaddr)
{
@ -1020,15 +1029,16 @@ ip4_process_classless_routes (GHashTable *options,
if (strchr (str, '/')) {
/* dhcpcd format */
return ip4_process_dhcpcd_rfc3442_routes (str, ip4_config, gwaddr);
return ip4_process_dhcpcd_rfc3442_routes (self, str, ip4_config, gwaddr);
}
return ip4_process_dhclient_rfc3442_routes (str, ip4_config, gwaddr);
return ip4_process_dhclient_rfc3442_routes (self, str, ip4_config, gwaddr);
}
static void
process_classful_routes (GHashTable *options, NMIP4Config *ip4_config)
process_classful_routes (NMDHCPClient *self, GHashTable *options, NMIP4Config *ip4_config)
{
NMDHCPClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
const char *str;
char **searches, **s;
@ -1070,6 +1080,7 @@ process_classful_routes (GHashTable *options, NMIP4Config *ip4_config)
}
route.gateway = rt_route;
route.source = NM_PLATFORM_SOURCE_DHCP;
route.metric = priv->priority;
nm_ip4_config_add_route (ip4_config, &route);
nm_log_info (LOGD_DHCP, " static route %s",
@ -1166,8 +1177,8 @@ ip4_options_to_config (NMDHCPClient *self)
/* Routes: if the server returns classless static routes, we MUST ignore
* the 'static_routes' option.
*/
if (!ip4_process_classless_routes (priv->options, ip4_config, &gwaddr))
process_classful_routes (priv->options, ip4_config);
if (!ip4_process_classless_routes (self, priv->options, ip4_config, &gwaddr))
process_classful_routes (self, priv->options, ip4_config);
if (gwaddr) {
nm_log_info (LOGD_DHCP4, " gateway %s", nm_utils_inet4_ntop (gwaddr, NULL));
@ -1220,6 +1231,8 @@ ip4_options_to_config (NMDHCPClient *self)
route.plen = 32;
/* this will be a device route if gwaddr is 0 */
route.gateway = gwaddr;
route.source = NM_PLATFORM_SOURCE_DHCP;
route.metric = priv->priority;
nm_ip4_config_add_route (ip4_config, &route);
nm_log_dbg (LOGD_IP, "adding route for server identifier: %s",
nm_platform_ip4_route_to_string (&route));
@ -1499,6 +1512,9 @@ get_property (GObject *object, guint prop_id,
case PROP_UUID:
g_value_set_string (value, priv->uuid);
break;
case PROP_PRIORITY:
g_value_set_uint (value, priv->priority);
break;
case PROP_TIMEOUT:
g_value_set_uint (value, priv->timeout);
break;
@ -1531,6 +1547,10 @@ set_property (GObject *object, guint prop_id,
/* construct-only */
priv->uuid = g_value_dup_string (value);
break;
case PROP_PRIORITY:
/* construct-only */
priv->priority = g_value_get_uint (value);
break;
case PROP_TIMEOUT:
priv->timeout = g_value_get_uint (value);
break;
@ -1622,6 +1642,14 @@ nm_dhcp_client_class_init (NMDHCPClientClass *client_class)
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property
(object_class, PROP_PRIORITY,
g_param_spec_uint (NM_DHCP_CLIENT_PRIORITY,
"priority",
"Priority",
0, G_MAXUINT, 0,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property
(object_class, PROP_TIMEOUT,
g_param_spec_uint (NM_DHCP_CLIENT_TIMEOUT,

View file

@ -38,6 +38,7 @@
#define NM_DHCP_CLIENT_HWADDR "hwaddr"
#define NM_DHCP_CLIENT_IPV6 "ipv6"
#define NM_DHCP_CLIENT_UUID "uuid"
#define NM_DHCP_CLIENT_PRIORITY "priority"
#define NM_DHCP_CLIENT_TIMEOUT "timeout"
#define NM_DHCP_CLIENT_SIGNAL_TIMEOUT "timeout"

View file

@ -384,6 +384,7 @@ client_start (NMDHCPManager *self,
const char *iface,
const GByteArray *hwaddr,
const char *uuid,
guint priority,
gboolean ipv6,
const char *dhcp_client_id,
guint32 timeout,
@ -418,6 +419,7 @@ client_start (NMDHCPManager *self,
NM_DHCP_CLIENT_HWADDR, hwaddr,
NM_DHCP_CLIENT_IPV6, ipv6,
NM_DHCP_CLIENT_UUID, uuid,
NM_DHCP_CLIENT_PRIORITY, priority,
NM_DHCP_CLIENT_TIMEOUT, timeout ? timeout : DHCP_TIMEOUT,
NULL);
g_return_val_if_fail (client != NULL, NULL);
@ -452,6 +454,7 @@ nm_dhcp_manager_start_ip4 (NMDHCPManager *self,
const char *iface,
const GByteArray *hwaddr,
const char *uuid,
guint priority,
NMSettingIP4Config *s_ip4,
guint32 timeout,
GByteArray *dhcp_anycast_addr)
@ -469,7 +472,9 @@ nm_dhcp_manager_start_ip4 (NMDHCPManager *self,
if (send_hostname)
hostname = get_send_hostname (self, nm_setting_ip4_config_get_dhcp_hostname (s_ip4));
return client_start (self, iface, hwaddr, uuid, FALSE, nm_setting_ip4_config_get_dhcp_client_id (s_ip4), timeout, dhcp_anycast_addr, hostname, FALSE);
return client_start (self, iface, hwaddr, uuid, priority, FALSE,
nm_setting_ip4_config_get_dhcp_client_id (s_ip4),
timeout, dhcp_anycast_addr, hostname, FALSE);
}
/* Caller owns a reference to the NMDHCPClient on return */
@ -478,6 +483,7 @@ nm_dhcp_manager_start_ip6 (NMDHCPManager *self,
const char *iface,
const GByteArray *hwaddr,
const char *uuid,
guint priority,
NMSettingIP6Config *s_ip6,
guint32 timeout,
GByteArray *dhcp_anycast_addr,
@ -489,7 +495,8 @@ nm_dhcp_manager_start_ip6 (NMDHCPManager *self,
hostname = get_send_hostname (self, nm_setting_ip6_config_get_dhcp_hostname (s_ip6));
return client_start (self, iface, hwaddr, uuid, TRUE, NULL, timeout, dhcp_anycast_addr, hostname, info_only);
return client_start (self, iface, hwaddr, uuid, priority, TRUE,
NULL, timeout, dhcp_anycast_addr, hostname, info_only);
}
void

View file

@ -68,6 +68,7 @@ NMDHCPClient * nm_dhcp_manager_start_ip4 (NMDHCPManager *manager,
const char *iface,
const GByteArray *hwaddr,
const char *uuid,
guint priority,
NMSettingIP4Config *s_ip4,
guint32 timeout,
GByteArray *dhcp_anycast_addr);
@ -76,6 +77,7 @@ NMDHCPClient * nm_dhcp_manager_start_ip6 (NMDHCPManager *manager,
const char *iface,
const GByteArray *hwaddr,
const char *uuid,
guint priority,
NMSettingIP6Config *s_ip6,
guint32 timeout,
GByteArray *dhcp_anycast_addr,

View file

@ -244,7 +244,7 @@ nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf)
}
gboolean
nm_ip4_config_commit (const NMIP4Config *config, int ifindex, int priority)
nm_ip4_config_commit (const NMIP4Config *config, int ifindex)
{
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
int mtu = nm_ip4_config_get_mtu (config);
@ -273,17 +273,12 @@ nm_ip4_config_commit (const NMIP4Config *config, int ifindex, int priority)
&& nm_ip4_config_destination_is_direct (config, route.network, route.plen))
continue;
/* Don't add the default route when and the connection
/* Don't add the default route if the connection
* is never supposed to be the default connection.
*/
if (nm_ip4_config_get_never_default (config) && route.network == 0)
continue;
/* Use the default metric only if the route was created by NM and
* didn't already specify a metric.
*/
if (route.source != NM_PLATFORM_SOURCE_KERNEL && !route.metric)
route.metric = priority ? priority : NM_PLATFORM_ROUTE_METRIC_DEFAULT;
g_array_append_val (routes, route);
}
@ -449,6 +444,10 @@ nm_ip4_config_create_setting (const NMIP4Config *config)
if (!route->plen)
continue;
/* Ignore routes provided by external sources */
if (route->source != NM_PLATFORM_SOURCE_USER)
continue;
s_route = nm_ip4_route_new ();
nm_ip4_route_set_dest (s_route, route->network);
nm_ip4_route_set_prefix (s_route, route->plen);

View file

@ -60,7 +60,7 @@ const char * nm_ip4_config_get_dbus_path (const NMIP4Config *config);
/* Integration with nm-platform and nm-setting */
NMIP4Config *nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf);
gboolean nm_ip4_config_commit (const NMIP4Config *config, int ifindex, int priority);
gboolean nm_ip4_config_commit (const NMIP4Config *config, int ifindex);
void nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIP4Config *setting);
NMSetting *nm_ip4_config_create_setting (const NMIP4Config *config);

View file

@ -356,7 +356,7 @@ nm_ip6_config_capture (int ifindex, gboolean capture_resolv_conf, NMSettingIP6Co
}
gboolean
nm_ip6_config_commit (const NMIP6Config *config, int ifindex, int priority)
nm_ip6_config_commit (const NMIP6Config *config, int ifindex)
{
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config);
int i;
@ -384,17 +384,12 @@ nm_ip6_config_commit (const NMIP6Config *config, int ifindex, int priority)
&& nm_ip6_config_destination_is_direct (config, &route.network, route.plen))
continue;
/* Don't add the default route when and the connection
/* Don't add the default route if the connection
* is never supposed to be the default connection.
*/
if (nm_ip6_config_get_never_default (config) && IN6_IS_ADDR_UNSPECIFIED (&route.network))
continue;
/* Use the default metric only if the route was created by NM and
* didn't already specify a metric.
*/
if (route.source != NM_PLATFORM_SOURCE_KERNEL && !route.metric)
route.metric = priority ? priority : NM_PLATFORM_ROUTE_METRIC_DEFAULT;
g_array_append_val (routes, route);
}
@ -556,6 +551,10 @@ nm_ip6_config_create_setting (const NMIP6Config *config)
if (!route->plen)
continue;
/* Ignore routes provided by external sources */
if (route->source != NM_PLATFORM_SOURCE_USER)
continue;
s_route = nm_ip6_route_new ();
nm_ip6_route_set_dest (s_route, &route->network);
nm_ip6_route_set_prefix (s_route, route->plen);

View file

@ -59,7 +59,7 @@ const char * nm_ip6_config_get_dbus_path (const NMIP6Config *config);
/* Integration with nm-platform and nm-setting */
NMIP6Config *nm_ip6_config_capture (int ifindex, gboolean capture_resolv_conf, NMSettingIP6ConfigPrivacy use_temporary);
gboolean nm_ip6_config_commit (const NMIP6Config *config, int ifindex, int priority);
gboolean nm_ip6_config_commit (const NMIP6Config *config, int ifindex);
void nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIP6Config *setting);
NMSetting *nm_ip6_config_create_setting (const NMIP6Config *config);

View file

@ -658,9 +658,15 @@ update_ip4_routing (NMPolicy *policy, gboolean force_update)
if (ip_ifindex <= 0)
ip_ifindex = parent_ifindex;
if (!nm_platform_ip4_route_add (ip_ifindex, 0, 0, int_gw, NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) {
(void) nm_platform_ip4_route_add (parent_ifindex, gw_addr, 32, 0, NM_PLATFORM_ROUTE_METRIC_DEFAULT, parent_mss);
if (!nm_platform_ip4_route_add (ip_ifindex, 0, 0, int_gw, NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss))
if (!nm_platform_ip4_route_add (ip_ifindex, NM_PLATFORM_SOURCE_VPN,
0, 0, int_gw,
NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) {
(void) nm_platform_ip4_route_add (parent_ifindex, NM_PLATFORM_SOURCE_VPN,
gw_addr, 32, 0,
NM_PLATFORM_ROUTE_METRIC_DEFAULT, parent_mss);
if (!nm_platform_ip4_route_add (ip_ifindex, NM_PLATFORM_SOURCE_VPN,
0, 0, int_gw,
NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss))
nm_log_err (LOGD_IP4 | LOGD_VPN, "Failed to set default route.");
}
@ -669,9 +675,15 @@ update_ip4_routing (NMPolicy *policy, gboolean force_update)
int mss = nm_ip4_config_get_mss (ip4_config);
g_assert (ip_iface);
if (!nm_platform_ip4_route_add (ip_ifindex, 0, 0, gw_addr, NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) {
(void) nm_platform_ip4_route_add (ip_ifindex, gw_addr, 32, 0, NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss);
if (!nm_platform_ip4_route_add (ip_ifindex, 0, 0, gw_addr, NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) {
if (!nm_platform_ip4_route_add (ip_ifindex, NM_PLATFORM_SOURCE_USER,
0, 0, gw_addr,
NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) {
(void) nm_platform_ip4_route_add (ip_ifindex, NM_PLATFORM_SOURCE_USER,
gw_addr, 32, 0,
NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss);
if (!nm_platform_ip4_route_add (ip_ifindex, NM_PLATFORM_SOURCE_USER,
0, 0, gw_addr,
NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) {
nm_log_err (LOGD_IP4, "Failed to set default route.");
}
}
@ -852,9 +864,15 @@ update_ip6_routing (NMPolicy *policy, gboolean force_update)
if (ip_ifindex <= 0)
ip_ifindex = parent_ifindex;
if (!nm_platform_ip6_route_add (ip_ifindex, in6addr_any, 0, *int_gw, NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) {
(void) nm_platform_ip6_route_add (parent_ifindex, *gw_addr, 128, in6addr_any, NM_PLATFORM_ROUTE_METRIC_DEFAULT, parent_mss);
if (!nm_platform_ip6_route_add (ip_ifindex, in6addr_any, 0, *int_gw, NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) {
if (!nm_platform_ip6_route_add (ip_ifindex, NM_PLATFORM_SOURCE_VPN,
in6addr_any, 0, *int_gw,
NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) {
(void) nm_platform_ip6_route_add (parent_ifindex, NM_PLATFORM_SOURCE_VPN,
*gw_addr, 128, in6addr_any,
NM_PLATFORM_ROUTE_METRIC_DEFAULT, parent_mss);
if (!nm_platform_ip6_route_add (ip_ifindex, NM_PLATFORM_SOURCE_VPN,
in6addr_any, 0, *int_gw,
NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) {
nm_log_err (LOGD_IP6 | LOGD_VPN, "Failed to set default route.");
}
}
@ -863,9 +881,15 @@ update_ip6_routing (NMPolicy *policy, gboolean force_update)
} else {
int mss = nm_ip6_config_get_mss (ip6_config);
if (!nm_platform_ip6_route_add (ip_ifindex, in6addr_any, 0, *gw_addr, NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) {
(void) nm_platform_ip6_route_add (ip_ifindex, *gw_addr, 128, in6addr_any, NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss);
if (!nm_platform_ip6_route_add (ip_ifindex, in6addr_any, 0, *gw_addr, NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss))
if (!nm_platform_ip6_route_add (ip_ifindex, NM_PLATFORM_SOURCE_USER,
in6addr_any, 0, *gw_addr,
NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) {
(void) nm_platform_ip6_route_add (ip_ifindex, NM_PLATFORM_SOURCE_USER,
*gw_addr, 128, in6addr_any,
NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss);
if (!nm_platform_ip6_route_add (ip_ifindex, NM_PLATFORM_SOURCE_USER,
in6addr_any, 0, *gw_addr,
NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss))
nm_log_err (LOGD_IP6, "Failed to set default route.");
}

View file

@ -1039,8 +1039,9 @@ ip6_route_get_all (NMPlatform *platform, int ifindex, gboolean include_default)
}
static gboolean
ip4_route_add (NMPlatform *platform, int ifindex, in_addr_t network, int plen,
in_addr_t gateway, int metric, int mss)
ip4_route_add (NMPlatform *platform, int ifindex, NMPlatformSource source,
in_addr_t network, int plen, in_addr_t gateway,
int metric, int mss)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
NMPlatformIP4Route route;
@ -1049,6 +1050,7 @@ ip4_route_add (NMPlatform *platform, int ifindex, in_addr_t network, int plen,
memset (&route, 0, sizeof (route));
route.source = NM_PLATFORM_SOURCE_KERNEL;
route.ifindex = ifindex;
route.source = source;
route.network = network;
route.plen = plen;
route.gateway = gateway;
@ -1077,8 +1079,9 @@ ip4_route_add (NMPlatform *platform, int ifindex, in_addr_t network, int plen,
}
static gboolean
ip6_route_add (NMPlatform *platform, int ifindex, struct in6_addr network, int plen,
struct in6_addr gateway, int metric, int mss)
ip6_route_add (NMPlatform *platform, int ifindex, NMPlatformSource source,
struct in6_addr network, int plen, struct in6_addr gateway,
int metric, int mss)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
NMPlatformIP6Route route;
@ -1087,6 +1090,7 @@ ip6_route_add (NMPlatform *platform, int ifindex, struct in6_addr network, int p
memset (&route, 0, sizeof (route));
route.source = NM_PLATFORM_SOURCE_KERNEL;
route.ifindex = ifindex;
route.source = source;
route.network = network;
route.plen = plen;
route.gateway = gateway;

View file

@ -1048,6 +1048,43 @@ init_ip6_address (NMPlatformIP6Address *address, struct rtnl_addr *rtnladdr)
return TRUE;
}
static guint
source_to_rtprot (NMPlatformSource source)
{
switch (source) {
case NM_PLATFORM_SOURCE_UNKNOWN:
return RTPROT_UNSPEC;
case NM_PLATFORM_SOURCE_KERNEL:
return RTPROT_KERNEL;
case NM_PLATFORM_SOURCE_DHCP:
return RTPROT_DHCP;
case NM_PLATFORM_SOURCE_RDISC:
return RTPROT_RA;
default:
return RTPROT_STATIC;
}
}
static NMPlatformSource
rtprot_to_source (guint rtprot)
{
switch (rtprot) {
case RTPROT_UNSPEC:
return NM_PLATFORM_SOURCE_UNKNOWN;
case RTPROT_REDIRECT:
case RTPROT_KERNEL:
return NM_PLATFORM_SOURCE_KERNEL;
case RTPROT_RA:
return NM_PLATFORM_SOURCE_RDISC;
case RTPROT_DHCP:
return NM_PLATFORM_SOURCE_DHCP;
default:
return NM_PLATFORM_SOURCE_USER;
}
}
static gboolean
init_ip4_route (NMPlatformIP4Route *route, struct rtnl_route *rtnlroute)
{
@ -1083,6 +1120,7 @@ init_ip4_route (NMPlatformIP4Route *route, struct rtnl_route *rtnlroute)
}
route->metric = rtnl_route_get_priority (rtnlroute);
rtnl_route_get_metric (rtnlroute, RTAX_ADVMSS, &route->mss);
route->source = rtprot_to_source (rtnl_route_get_protocol (rtnlroute));
return TRUE;
}
@ -1122,6 +1160,7 @@ init_ip6_route (NMPlatformIP6Route *route, struct rtnl_route *rtnlroute)
}
route->metric = rtnl_route_get_priority (rtnlroute);
rtnl_route_get_metric (rtnlroute, RTAX_ADVMSS, &route->mss);
route->source = rtprot_to_source (rtnl_route_get_protocol (rtnlroute));
return TRUE;
}
@ -3263,7 +3302,6 @@ ip4_route_get_all (NMPlatform *platform, int ifindex, gboolean include_default)
for (object = nl_cache_get_first (priv->route_cache); object; object = nl_cache_get_next (object)) {
if (_route_match ((struct rtnl_route *) object, AF_INET, ifindex)) {
if (init_ip4_route (&route, (struct rtnl_route *) object)) {
route.source = NM_PLATFORM_SOURCE_KERNEL;
if (route.plen != 0 || include_default)
g_array_append_val (routes, route);
}
@ -3286,7 +3324,6 @@ ip6_route_get_all (NMPlatform *platform, int ifindex, gboolean include_default)
for (object = nl_cache_get_first (priv->route_cache); object; object = nl_cache_get_next (object)) {
if (_route_match ((struct rtnl_route *) object, AF_INET6, ifindex)) {
if (init_ip6_route (&route, (struct rtnl_route *) object)) {
route.source = NM_PLATFORM_SOURCE_KERNEL;
if (route.plen != 0 || include_default)
g_array_append_val (routes, route);
}
@ -3315,7 +3352,9 @@ clear_host_address (int family, const void *network, int plen, void *dst)
}
static struct nl_object *
build_rtnl_route (int family, int ifindex, gconstpointer network, int plen, gconstpointer gateway, int metric, int mss)
build_rtnl_route (int family, int ifindex, NMPlatformSource source,
gconstpointer network, int plen, gconstpointer gateway,
int metric, int mss)
{
guint32 network_clean[4];
struct rtnl_route *rtnlroute;
@ -3339,6 +3378,7 @@ build_rtnl_route (int family, int ifindex, gconstpointer network, int plen, gcon
rtnl_route_set_dst (rtnlroute, dst);
rtnl_route_set_priority (rtnlroute, metric);
rtnl_route_set_family (rtnlroute, family);
rtnl_route_set_protocol (rtnlroute, source_to_rtprot (source));
nexthop = _nm_rtnl_route_nh_alloc ();
rtnl_route_nh_set_ifindex (nexthop, ifindex);
@ -3353,15 +3393,19 @@ build_rtnl_route (int family, int ifindex, gconstpointer network, int plen, gcon
}
static gboolean
ip4_route_add (NMPlatform *platform, int ifindex, in_addr_t network, int plen, in_addr_t gateway, int metric, int mss)
ip4_route_add (NMPlatform *platform, int ifindex, NMPlatformSource source,
in_addr_t network, int plen, in_addr_t gateway,
int metric, int mss)
{
return add_object (platform, build_rtnl_route (AF_INET, ifindex, &network, plen, &gateway, metric, mss));
return add_object (platform, build_rtnl_route (AF_INET, ifindex, source, &network, plen, &gateway, metric, mss));
}
static gboolean
ip6_route_add (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, struct in6_addr gateway, int metric, int mss)
ip6_route_add (NMPlatform *platform, int ifindex, NMPlatformSource source,
struct in6_addr network, int plen, struct in6_addr gateway,
int metric, int mss)
{
return add_object (platform, build_rtnl_route (AF_INET6, ifindex, &network, plen, &gateway, metric, mss));
return add_object (platform, build_rtnl_route (AF_INET6, ifindex, source, &network, plen, &gateway, metric, mss));
}
static struct rtnl_route *
@ -3418,7 +3462,7 @@ ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen
{
in_addr_t gateway = 0;
struct rtnl_route *cached_object;
struct nl_object *route = build_rtnl_route (AF_INET, ifindex, &network, plen, &gateway, metric, 0);
struct nl_object *route = build_rtnl_route (AF_INET, ifindex, NM_PLATFORM_SOURCE_UNKNOWN, &network, plen, &gateway, metric, 0);
uint8_t scope = RT_SCOPE_NOWHERE;
struct nl_cache *cache;
@ -3459,9 +3503,6 @@ ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen
}
rtnl_route_set_scope ((struct rtnl_route *) route, scope);
/* protocol defaults to RTPROT_STATIC, set to zero so that the kernel ignores the value */
rtnl_route_set_protocol ((struct rtnl_route *) route, 0);
if (cached_object)
rtnl_route_set_tos ((struct rtnl_route *) route, rtnl_route_get_tos (cached_object));
@ -3481,15 +3522,16 @@ ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, in
{
struct in6_addr gateway = IN6ADDR_ANY_INIT;
return delete_object (platform, build_rtnl_route (AF_INET6, ifindex, &network, plen, &gateway, metric, 0), FALSE) &&
return delete_object (platform, build_rtnl_route (AF_INET6, ifindex, NM_PLATFORM_SOURCE_UNKNOWN ,&network, plen, &gateway, metric, 0), FALSE) &&
refresh_route (platform, AF_INET6, ifindex, &network, plen, metric);
}
static gboolean
ip_route_exists (NMPlatform *platform, int family, int ifindex, gpointer network, int plen, int metric)
{
auto_nl_object struct nl_object *object = build_rtnl_route (family, ifindex, network,
plen, NULL, metric, 0);
auto_nl_object struct nl_object *object = build_rtnl_route (family, ifindex,
NM_PLATFORM_SOURCE_UNKNOWN,
network, plen, NULL, metric, 0);
struct nl_cache *cache = choose_cache (platform, object);
auto_nl_object struct nl_object *cached_object = nl_cache_search (cache, object);

View file

@ -1711,9 +1711,9 @@ nm_platform_ip6_route_get_all (int ifindex, gboolean include_default)
}
gboolean
nm_platform_ip4_route_add (int ifindex,
in_addr_t network, int plen,
in_addr_t gateway, int metric, int mss)
nm_platform_ip4_route_add (int ifindex, NMPlatformSource source,
in_addr_t network, int plen,
in_addr_t gateway, int metric, int mss)
{
reset_error ();
@ -1727,6 +1727,7 @@ nm_platform_ip4_route_add (int ifindex,
NMPlatformIP4Route route = { 0 };
route.ifindex = ifindex;
route.source = source;
route.network = network;
route.plen = plen;
route.gateway = gateway;
@ -1735,12 +1736,13 @@ nm_platform_ip4_route_add (int ifindex,
debug ("route: adding or updating IPv4 route: %s", nm_platform_ip4_route_to_string (&route));
}
return klass->ip4_route_add (platform, ifindex, network, plen, gateway, metric, mss);
return klass->ip4_route_add (platform, ifindex, source, network, plen, gateway, metric, mss);
}
gboolean
nm_platform_ip6_route_add (int ifindex,
struct in6_addr network, int plen, struct in6_addr gateway, int metric, int mss)
nm_platform_ip6_route_add (int ifindex, NMPlatformSource source,
struct in6_addr network, int plen, struct in6_addr gateway,
int metric, int mss)
{
g_return_val_if_fail (platform, FALSE);
g_return_val_if_fail (0 <= plen && plen <= 128, FALSE);
@ -1752,6 +1754,7 @@ nm_platform_ip6_route_add (int ifindex,
NMPlatformIP6Route route = { 0 };
route.ifindex = ifindex;
route.source = source;
route.network = network;
route.plen = plen;
route.gateway = gateway;
@ -1760,7 +1763,7 @@ nm_platform_ip6_route_add (int ifindex,
debug ("route: adding or updating IPv6 route: %s", nm_platform_ip6_route_to_string (&route));
}
return klass->ip6_route_add (platform, ifindex, network, plen, gateway, metric, mss);
return klass->ip6_route_add (platform, ifindex, source, network, plen, gateway, metric, mss);
}
gboolean
@ -1776,8 +1779,7 @@ nm_platform_ip4_route_delete (int ifindex, in_addr_t network, int plen, int metr
}
gboolean
nm_platform_ip6_route_delete (int ifindex,
struct in6_addr network, int plen, int metric)
nm_platform_ip6_route_delete (int ifindex, struct in6_addr network, int plen, int metric)
{
reset_error ();
@ -1896,6 +1898,7 @@ nm_platform_ip4_route_sync (int ifindex, const GArray *known_routes)
/* Ignore routes that already exist */
if (!array_contains_ip4_route (routes, known_route)) {
success = nm_platform_ip4_route_add (ifindex,
known_route->source,
known_route->network,
known_route->plen,
known_route->gateway,
@ -1963,6 +1966,7 @@ nm_platform_ip6_route_sync (int ifindex, const GArray *known_routes)
/* Ignore routes that already exist */
if (!array_contains_ip6_route (routes, known_route)) {
success = nm_platform_ip6_route_add (ifindex,
known_route->source,
known_route->network,
known_route->plen,
known_route->gateway,

View file

@ -428,10 +428,12 @@ typedef struct {
GArray * (*ip4_route_get_all) (NMPlatform *, int ifindex, gboolean include_default);
GArray * (*ip6_route_get_all) (NMPlatform *, int ifindex, gboolean include_default);
gboolean (*ip4_route_add) (NMPlatform *, int ifindex,
in_addr_t network, int plen, in_addr_t gateway, int prio, int mss);
gboolean (*ip6_route_add) (NMPlatform *, int ifindex,
struct in6_addr network, int plen, struct in6_addr gateway, int prio, int mss);
gboolean (*ip4_route_add) (NMPlatform *, int ifindex, NMPlatformSource source,
in_addr_t network, int plen, in_addr_t gateway,
int prio, int mss);
gboolean (*ip6_route_add) (NMPlatform *, int ifindex, NMPlatformSource source,
struct in6_addr network, int plen, struct in6_addr gateway,
int prio, int mss);
gboolean (*ip4_route_delete) (NMPlatform *, int ifindex, in_addr_t network, int plen, int metric);
gboolean (*ip6_route_delete) (NMPlatform *, int ifindex, struct in6_addr network, int plen, int metric);
gboolean (*ip4_route_exists) (NMPlatform *, int ifindex, in_addr_t network, int plen, int metric);
@ -570,10 +572,12 @@ gboolean nm_platform_address_flush (int ifindex);
GArray *nm_platform_ip4_route_get_all (int ifindex, gboolean include_default);
GArray *nm_platform_ip6_route_get_all (int ifindex, gboolean include_default);
gboolean nm_platform_route_set_metric (int ifindex, int metric);
gboolean nm_platform_ip4_route_add (int ifindex,
in_addr_t network, int plen, in_addr_t gateway, int metric, int mss);
gboolean nm_platform_ip6_route_add (int ifindex,
struct in6_addr network, int plen, struct in6_addr gateway, int metric, int mss);
gboolean nm_platform_ip4_route_add (int ifindex, NMPlatformSource source,
in_addr_t network, int plen, in_addr_t gateway,
int metric, int mss);
gboolean nm_platform_ip6_route_add (int ifindex, NMPlatformSource source,
struct in6_addr network, int plen, struct in6_addr gateway,
int metric, int mss);
gboolean nm_platform_ip4_route_delete (int ifindex, in_addr_t network, int plen, int metric);
gboolean nm_platform_ip6_route_delete (int ifindex, struct in6_addr network, int plen, int metric);
gboolean nm_platform_ip4_route_exists (int ifindex, in_addr_t network, int plen, int metric);

View file

@ -677,7 +677,9 @@ do_ip4_route_add (char **argv)
metric = strtol (*argv++, NULL, 10);
mss = strtol (*argv++, NULL, 10);
return nm_platform_ip4_route_add (ifindex, network, plen, gateway, metric, mss);
return nm_platform_ip4_route_add (ifindex, NM_PLATFORM_SOURCE_USER,
network, plen, gateway,
metric, mss);
}
static gboolean
@ -691,7 +693,9 @@ do_ip6_route_add (char **argv)
parse_ip6_address (*argv++, &gateway, NULL);
metric = strtol (*argv++, NULL, 10);
mss = strtol (*argv++, NULL, 10);
return nm_platform_ip6_route_add (ifindex, network, plen, gateway, metric, mss);
return nm_platform_ip6_route_add (ifindex, NM_PLATFORM_SOURCE_USER,
network, plen, gateway,
metric, mss);
}
static gboolean

View file

@ -43,12 +43,12 @@ test_cleanup_internal ()
/* Add routes and addresses */
g_assert (nm_platform_ip4_address_add (ifindex, addr4, 0, plen4, lifetime, preferred, NULL));
g_assert (nm_platform_ip6_address_add (ifindex, addr6, in6addr_any, plen6, lifetime, preferred, flags));
g_assert (nm_platform_ip4_route_add (ifindex, gateway4, 32, INADDR_ANY, metric, mss));
g_assert (nm_platform_ip4_route_add (ifindex, network4, plen4, gateway4, metric, mss));
g_assert (nm_platform_ip4_route_add (ifindex, 0, 0, gateway4, metric, mss));
g_assert (nm_platform_ip6_route_add (ifindex, gateway6, 128, in6addr_any, metric, mss));
g_assert (nm_platform_ip6_route_add (ifindex, network6, plen6, gateway6, metric, mss));
g_assert (nm_platform_ip6_route_add (ifindex, in6addr_any, 0, gateway6, metric, mss));
g_assert (nm_platform_ip4_route_add (ifindex, NM_PLATFORM_SOURCE_USER, gateway4, 32, INADDR_ANY, metric, mss));
g_assert (nm_platform_ip4_route_add (ifindex, NM_PLATFORM_SOURCE_USER, network4, plen4, gateway4, metric, mss));
g_assert (nm_platform_ip4_route_add (ifindex, NM_PLATFORM_SOURCE_USER, 0, 0, gateway4, metric, mss));
g_assert (nm_platform_ip6_route_add (ifindex, NM_PLATFORM_SOURCE_USER, gateway6, 128, in6addr_any, metric, mss));
g_assert (nm_platform_ip6_route_add (ifindex, NM_PLATFORM_SOURCE_USER, network6, plen6, gateway6, metric, mss));
g_assert (nm_platform_ip6_route_add (ifindex, NM_PLATFORM_SOURCE_USER, in6addr_any, 0, gateway6, metric, mss));
addresses4 = nm_platform_ip4_address_get_all (ifindex);
addresses6 = nm_platform_ip6_address_get_all (ifindex);

View file

@ -66,28 +66,35 @@ test_ip4_route ()
inet_pton (AF_INET, "198.51.100.1", &gateway);
/* Add route to gateway */
g_assert (nm_platform_ip4_route_add (ifindex, gateway, 32, INADDR_ANY, metric, mss)); no_error ();
g_assert (nm_platform_ip4_route_add (ifindex, NM_PLATFORM_SOURCE_USER, gateway, 32, INADDR_ANY, metric, mss));
no_error ();
accept_signal (route_added);
/* Add route */
g_assert (!nm_platform_ip4_route_exists (ifindex, network, plen, metric)); no_error ();
g_assert (nm_platform_ip4_route_add (ifindex, network, plen, gateway, metric, mss)); no_error ();
g_assert (nm_platform_ip4_route_exists (ifindex, network, plen, metric)); no_error ();
g_assert (!nm_platform_ip4_route_exists (ifindex, network, plen, metric));
no_error ();
g_assert (nm_platform_ip4_route_add (ifindex, NM_PLATFORM_SOURCE_USER, network, plen, gateway, metric, mss));
no_error ();
g_assert (nm_platform_ip4_route_exists (ifindex, network, plen, metric));
no_error ();
accept_signal (route_added);
/* Add route again */
g_assert (nm_platform_ip4_route_add (ifindex, network, plen, gateway, metric, mss));
g_assert (nm_platform_ip4_route_add (ifindex, NM_PLATFORM_SOURCE_USER, network, plen, gateway, metric, mss));
no_error ();
accept_signal (route_changed);
/* Add default route */
g_assert (!nm_platform_ip4_route_exists (ifindex, 0, 0, metric)); no_error ();
g_assert (nm_platform_ip4_route_add (ifindex, 0, 0, gateway, metric, mss)); no_error ();
g_assert (nm_platform_ip4_route_exists (ifindex, 0, 0, metric)); no_error ();
g_assert (!nm_platform_ip4_route_exists (ifindex, 0, 0, metric));
no_error ();
g_assert (nm_platform_ip4_route_add (ifindex, NM_PLATFORM_SOURCE_USER, 0, 0, gateway, metric, mss));
no_error ();
g_assert (nm_platform_ip4_route_exists (ifindex, 0, 0, metric));
no_error ();
accept_signal (route_added);
/* Add default route again */
g_assert (nm_platform_ip4_route_add (ifindex, 0, 0, gateway, metric, mss));
g_assert (nm_platform_ip4_route_add (ifindex, NM_PLATFORM_SOURCE_USER, 0, 0, gateway, metric, mss));
no_error ();
accept_signal (route_changed);
@ -121,7 +128,8 @@ test_ip4_route ()
g_array_unref (routes);
/* Remove route */
g_assert (nm_platform_ip4_route_delete (ifindex, network, plen, metric)); no_error ();
g_assert (nm_platform_ip4_route_delete (ifindex, network, plen, metric));
no_error ();
g_assert (!nm_platform_ip4_route_exists (ifindex, network, plen, metric));
accept_signal (route_removed);
@ -153,28 +161,35 @@ test_ip6_route ()
inet_pton (AF_INET6, "2001:db8:c:d:1:2:3:4", &gateway);
/* Add route to gateway */
g_assert (nm_platform_ip6_route_add (ifindex, gateway, 128, in6addr_any, metric, mss)); no_error ();
g_assert (nm_platform_ip6_route_add (ifindex, NM_PLATFORM_SOURCE_USER, gateway, 128, in6addr_any, metric, mss));
no_error ();
accept_signal (route_added);
/* Add route */
g_assert (!nm_platform_ip6_route_exists (ifindex, network, plen, metric)); no_error ();
g_assert (nm_platform_ip6_route_add (ifindex, network, plen, gateway, metric, mss)); no_error ();
g_assert (nm_platform_ip6_route_exists (ifindex, network, plen, metric)); no_error ();
g_assert (!nm_platform_ip6_route_exists (ifindex, network, plen, metric));
no_error ();
g_assert (nm_platform_ip6_route_add (ifindex, NM_PLATFORM_SOURCE_USER, network, plen, gateway, metric, mss));
no_error ();
g_assert (nm_platform_ip6_route_exists (ifindex, network, plen, metric));
no_error ();
accept_signal (route_added);
/* Add route again */
g_assert (nm_platform_ip6_route_add (ifindex, network, plen, gateway, metric, mss));
g_assert (nm_platform_ip6_route_add (ifindex, NM_PLATFORM_SOURCE_USER, network, plen, gateway, metric, mss));
no_error ();
accept_signal (route_changed);
/* Add default route */
g_assert (!nm_platform_ip6_route_exists (ifindex, in6addr_any, 0, metric)); no_error ();
g_assert (nm_platform_ip6_route_add (ifindex, in6addr_any, 0, gateway, metric, mss)); no_error ();
g_assert (nm_platform_ip6_route_exists (ifindex, in6addr_any, 0, metric)); no_error ();
g_assert (!nm_platform_ip6_route_exists (ifindex, in6addr_any, 0, metric));
no_error ();
g_assert (nm_platform_ip6_route_add (ifindex, NM_PLATFORM_SOURCE_USER, in6addr_any, 0, gateway, metric, mss));
no_error ();
g_assert (nm_platform_ip6_route_exists (ifindex, in6addr_any, 0, metric));
no_error ();
accept_signal (route_added);
/* Add default route again */
g_assert (nm_platform_ip6_route_add (ifindex, in6addr_any, 0, gateway, metric, mss));
g_assert (nm_platform_ip6_route_add (ifindex, NM_PLATFORM_SOURCE_USER, in6addr_any, 0, gateway, metric, mss));
no_error ();
accept_signal (route_changed);
@ -208,7 +223,8 @@ test_ip6_route ()
g_array_unref (routes);
/* Remove route */
g_assert (nm_platform_ip6_route_delete (ifindex, network, plen, metric)); no_error ();
g_assert (nm_platform_ip6_route_delete (ifindex, network, plen, metric));
no_error ();
g_assert (!nm_platform_ip6_route_exists (ifindex, network, plen, metric));
accept_signal (route_removed);

View file

@ -334,6 +334,7 @@ add_ip4_vpn_gateway_route (NMIP4Config *config, NMDevice *parent_device, guint32
route.gateway = 0;
route.source = NM_PLATFORM_SOURCE_VPN;
route.metric = nm_device_get_priority (parent_device);
nm_ip4_config_add_route (config, &route);
/* Ensure there's a route to the parent device's gateway through the
@ -345,6 +346,7 @@ add_ip4_vpn_gateway_route (NMIP4Config *config, NMDevice *parent_device, guint32
route.network = parent_gw;
route.plen = 32;
route.source = NM_PLATFORM_SOURCE_VPN;
route.metric = nm_device_get_priority (parent_device);
nm_ip4_config_add_route (config, &route);
}
@ -381,6 +383,7 @@ add_ip6_vpn_gateway_route (NMIP6Config *config,
route.gateway = in6addr_any;
route.source = NM_PLATFORM_SOURCE_VPN;
route.metric = nm_device_get_priority (parent_device);
nm_ip6_config_add_route (config, &route);
/* Ensure there's a route to the parent device's gateway through the
@ -392,6 +395,7 @@ add_ip6_vpn_gateway_route (NMIP6Config *config,
route.network = *parent_gw;
route.plen = 128;
route.source = NM_PLATFORM_SOURCE_VPN;
route.metric = nm_device_get_priority (parent_device);
nm_ip6_config_add_route (config, &route);
}
@ -694,12 +698,12 @@ nm_vpn_connection_apply_config (NMVPNConnection *connection)
nm_platform_link_set_up (priv->ip_ifindex);
if (priv->ip4_config) {
if (!nm_ip4_config_commit (priv->ip4_config, priv->ip_ifindex, 0))
if (!nm_ip4_config_commit (priv->ip4_config, priv->ip_ifindex))
return FALSE;
}
if (priv->ip6_config) {
if (!nm_ip6_config_commit (priv->ip6_config, priv->ip_ifindex, 0))
if (!nm_ip6_config_commit (priv->ip6_config, priv->ip_ifindex))
return FALSE;
}
@ -907,6 +911,20 @@ nm_vpn_connection_config_get (DBusGProxy *proxy,
g_clear_object (&priv->ip6_config);
}
static guint
vpn_routing_metric (NMVPNConnection *connection)
{
NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection);
if (priv->ip_ifindex)
return NM_PLATFORM_ROUTE_METRIC_DEFAULT;
else {
NMDevice *parent_dev = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (connection));
return nm_device_get_priority (parent_dev);
}
}
static void
nm_vpn_connection_ip4_config_get (DBusGProxy *proxy,
GHashTable *config_hash,
@ -1033,6 +1051,7 @@ nm_vpn_connection_ip4_config_get (DBusGProxy *proxy,
route.plen = nm_ip4_route_get_prefix (item);
route.gateway = nm_ip4_route_get_next_hop (item);
route.source = NM_PLATFORM_SOURCE_VPN;
route.metric = vpn_routing_metric (connection);
/* Ignore host routes to the VPN gateway since NM adds one itself
* below. Since NM knows more about the routing situation than
@ -1179,6 +1198,7 @@ nm_vpn_connection_ip6_config_get (DBusGProxy *proxy,
route.plen = nm_ip6_route_get_prefix (item);
route.gateway = *nm_ip6_route_get_next_hop (item);
route.source = NM_PLATFORM_SOURCE_VPN;
route.metric = vpn_routing_metric (connection);
/* Ignore host routes to the VPN gateway since NM adds one itself
* below. Since NM knows more about the routing situation than