NetworkManager r3728 - in trunk: . include src src/vpn-manager



Author: dcbw
Date: Fri Jun  6 15:35:45 2008
New Revision: 3728
URL: http://svn.gnome.org/viewvc/NetworkManager?rev=3728&view=rev

Log:
2008-06-06  Dan Williams <dcbw redhat com>

	Patch from Tambet Ingo  <tambet gmail com>

	* src/NetworkManagerSystem.c
	  src/NetworkManagerSystem.h
		- (nm_system_device_add_ip4_route_via_device_with_iface): remove
		- (nm_system_device_set_from_ip4_config): remove unused route_to_iface
		- (nm_system_device_set_ip4_route): clean up
		- (nm_system_vpn_device_set_from_ip4_config): clean up, add VPN routes

	* src/nm-device.c
		- (nm_device_set_ip4_config): remove unused route_to_iface bits

	* src/vpn-manager/nm-vpn-connection.c
		- (ip_address_to_string): new function
		- (print_vpn_config): use ip_address_to_string
		- (merge_vpn_routes): add user-defined routes to the ip4 config
		- (nm_vpn_connection_ip4_config_get): add routes the VPN server sent

	* include/NetworkManagerVPN.h
		- Add 'routes' key



Modified:
   trunk/ChangeLog
   trunk/include/NetworkManagerVPN.h
   trunk/src/NetworkManagerSystem.c
   trunk/src/NetworkManagerSystem.h
   trunk/src/nm-device.c
   trunk/src/vpn-manager/nm-vpn-connection.c

Modified: trunk/include/NetworkManagerVPN.h
==============================================================================
--- trunk/include/NetworkManagerVPN.h	(original)
+++ trunk/include/NetworkManagerVPN.h	Fri Jun  6 15:35:45 2008
@@ -116,5 +116,6 @@
 #define NM_VPN_PLUGIN_IP4_CONFIG_TUNDEV  "tundev"
 #define NM_VPN_PLUGIN_IP4_CONFIG_DOMAIN  "domain"
 #define NM_VPN_PLUGIN_IP4_CONFIG_BANNER  "banner"
+#define NM_VPN_PLUGIN_IP4_CONFIG_ROUTES  "routes"
 
 #endif /* NETWORK_MANAGER_VPN_H */

Modified: trunk/src/NetworkManagerSystem.c
==============================================================================
--- trunk/src/NetworkManagerSystem.c	(original)
+++ trunk/src/NetworkManagerSystem.c	Fri Jun  6 15:35:45 2008
@@ -61,134 +61,145 @@
 #include <netlink/utils.h>
 #include <netlink/route/link.h>
 
-
-/*
- * nm_system_device_set_ip4_route
- *
- */
 static gboolean
-nm_system_device_set_ip4_route (const char *iface,
-                                NMIP4Config *iface_config,
-                                guint32 ip4_gateway,
-                                guint32 ip4_dest,
-                                int prefix,
-                                int mss)
+route_in_same_subnet (NMIP4Config *config, guint32 dest, guint32 netmask)
 {
-	gboolean success = FALSE;
-	struct rtnl_route *route = NULL;
-	struct rtnl_route *route2 = NULL;
-	struct nl_handle *nlh = NULL;
-	struct nl_addr *gw_addr = NULL;
-	struct nl_addr *dest_addr = NULL;
-	int err, iface_idx, i;
+	int num;
+	int i;
 
-	/*
-	 * Zero is not a legal gateway and the ioctl will fail.  But zero is a
-	 * way of saying "no route" so we just return here.  Hopefully the
-	 * caller flushed the routes, first.
-	 */
-	if (ip4_gateway == 0)
-		return TRUE;
+	num = nm_ip4_config_get_num_addresses (config);
+	for (i = 0; i < num; i++) {
+		const NMSettingIP4Address *cfg_addr;
 
-	/*
-	 * Do not add the route if the destination is on the same subnet.
-	 */
-	if (iface_config) {
-		for (i = 0; i < nm_ip4_config_get_num_addresses (iface_config); i++) {
-			const NMSettingIP4Address *cfg_addr;
-
-			cfg_addr = nm_ip4_config_get_address (iface_config, i);
-			if ((ip4_dest & cfg_addr->netmask) == (cfg_addr->address & cfg_addr->netmask))
-				return TRUE;
-		}
+		cfg_addr = nm_ip4_config_get_address (config, i);
+		if ((dest & netmask) == (cfg_addr->address & cfg_addr->netmask))
+			return TRUE;
 	}
 
-	nlh = nm_netlink_get_default_handle ();
-	g_return_val_if_fail (nlh != NULL, FALSE);
+	return FALSE;
+}
 
-	iface_idx = nm_netlink_iface_to_index (iface);
-	g_return_val_if_fail (iface_idx >= 0, FALSE);
+static struct rtnl_route *
+create_route (int iface_idx, int mss)
+{
+	struct rtnl_route *route;
 
 	route = rtnl_route_alloc ();
-	g_return_val_if_fail (route != NULL, FALSE);
+	if (route) {
+		rtnl_route_set_oif (route, iface_idx);
 
-	rtnl_route_set_scope (route, RT_SCOPE_UNIVERSE);
-	rtnl_route_set_oif (route, iface_idx);
+		if (mss && rtnl_route_set_metric (route, RTAX_ADVMSS, mss) < 0)
+			nm_warning ("Could not set mss");
+	} else
+		nm_warning ("Could not allocate route");
 
-	gw_addr = nl_addr_build (AF_INET, &ip4_gateway, sizeof (ip4_gateway));
-	if (gw_addr == NULL)
-		goto out;
-	rtnl_route_set_gateway (route, gw_addr);
+	return route;
+}
 
-	dest_addr = nl_addr_build (AF_INET, &ip4_dest, sizeof (ip4_dest));
-	if (dest_addr == NULL)
-		goto out;
-	nl_addr_set_prefixlen (dest_addr, prefix);
-	rtnl_route_set_dst (route, dest_addr);
-	nl_addr_put (dest_addr);
+static int
+netmask_to_prefix (guint32 netmask)
+{
+	guchar *p;
+	guchar *end;
+	int prefix = 0;
 
-	if (mss) {
-		if (rtnl_route_set_metric (route, RTAX_ADVMSS, mss) < 0)
-			goto out;
-	}
+	p = (guchar *) &netmask;
+	end = p + sizeof (guint32);
 
-	err = rtnl_route_add (nlh, route, 0);
-	if (err == 0) {
-		/* Everything good */
-		success = TRUE;
-		goto out;
+	while ((*p == 0xFF) && p < end) {
+		prefix += 8;
+		p++;
 	}
 
-	if (err != ESRCH) {
-		nm_warning ("Failed to set IPv4 default route on '%s': %s",
-		            iface,
-		            nl_geterror ());
-		goto out;
-	}
-		
-	/* Gateway might be over a bridge; try adding a route to gateway first */
-	route2 = rtnl_route_alloc ();
-	if (route2 == NULL)
-		goto out;
-	rtnl_route_set_oif (route2, iface_idx);
-	rtnl_route_set_dst (route2, gw_addr);
+	if (p < end) {
+		guchar v = *p;
 
-	if (mss) {
-		if (rtnl_route_set_metric (route2, RTAX_ADVMSS, mss) < 0)
-			goto out;
+		while (v) {
+			prefix++;
+			v <<= 1;
+		}
 	}
 
-	/* Add route to gateway over bridge */
-	err = rtnl_route_add (nlh, route2, 0);
-	if (err) {
-		nm_warning ("Failed to add IPv4 default route on '%s': %s",
-		            iface,
-		            nl_geterror ());
-		goto out;
+	return prefix;
+}
+
+static void
+nm_system_device_set_ip4_route (const char *iface, 
+						  NMIP4Config *iface_config,
+						  guint32 ip4_dest,
+						  guint32 ip4_netmask,
+						  guint32 ip4_gateway,
+						  int mss)
+{
+	struct nl_handle *nlh;
+	struct rtnl_route *route;
+	struct nl_addr *dest_addr;
+	struct nl_addr *gw_addr = NULL;
+	int err, iface_idx;
+
+	if (iface_config && route_in_same_subnet (iface_config, ip4_dest, ip4_netmask))
+		return;
+
+	nlh = nm_netlink_get_default_handle ();
+	g_return_if_fail (nlh != NULL);
+
+	iface_idx = nm_netlink_iface_to_index (iface);
+	g_return_if_fail (iface_idx >= 0);
+
+	route = create_route (iface_idx, mss);
+	g_return_if_fail (route != NULL);
+
+	/* Destination */
+	dest_addr = nl_addr_build (AF_INET, &ip4_dest, sizeof (ip4_dest));
+	g_return_if_fail (dest_addr != NULL);
+	nl_addr_set_prefixlen (dest_addr, netmask_to_prefix (ip4_netmask));
+
+	rtnl_route_set_dst (route, dest_addr);
+	nl_addr_put (dest_addr);
+
+	/* Gateway */
+	if (ip4_gateway) {
+		gw_addr = nl_addr_build (AF_INET, &ip4_gateway, sizeof (ip4_gateway));
+		if (gw_addr) {
+			rtnl_route_set_gateway (route, gw_addr);
+			rtnl_route_set_scope (route, RT_SCOPE_UNIVERSE);
+		} else {
+			nm_warning ("Invalid gateway");
+			rtnl_route_put (route);
+			return;
+		}
 	}
 
-	/* Try adding the route again */
+	/* Add the route */
 	err = rtnl_route_add (nlh, route, 0);
-	if (!err) {
-		success = TRUE;
-	} else {
-		rtnl_route_del (nlh, route2, 0);
-		nm_warning ("Failed to set IPv4 default route on '%s': %s",
-		            iface,
-		            nl_geterror ());
+	if (err == ESRCH && ip4_gateway) {
+		/* Gateway might be over a bridge; try adding a route to gateway first */
+		struct rtnl_route *route2;
+
+		route2 = create_route (iface_idx, mss);
+		if (route2) {
+			/* Add route to gateway over bridge */
+			rtnl_route_set_dst (route2, gw_addr);
+			err = rtnl_route_add (nlh, route2, 0);
+			if (!err) {
+				/* Try adding the route again */
+				err = rtnl_route_add (nlh, route, 0);
+				if (err)
+					rtnl_route_del (nlh, route2, 0);
+			}
+
+			rtnl_route_put (route2);
+		}
 	}
 
-out:
+	if (err)
+		nm_warning ("Failed to set IPv4 route on '%s': %s", iface, nl_geterror ());
+
+	rtnl_route_put (route);
 	if (gw_addr)
 		nl_addr_put (gw_addr);
-	if (route2)
-		rtnl_route_put (route2);
-	if (route)
-		rtnl_route_put (route);
-	return success;
 }
 
-
 typedef struct {
 	const char *iface;
 	int ifindex;
@@ -275,33 +286,6 @@
 	return TRUE;
 }
 
-static int
-netmask_to_prefix (guint32 netmask)
-{
-	guchar *p;
-	guchar *end;
-	int prefix = 0;
-
-	p = (guchar *) &netmask;
-	end = p + sizeof (guint32);
-
-	while ((*p == 0xFF) && p < end) {
-		prefix += 8;
-		p++;
-	}
-
-	if (p < end) {
-		guchar v = *p;
-
-		while (v) {
-			prefix++;
-			v <<= 1;
-		}
-	}
-
-	return prefix;
-}
-
 /*
  * nm_system_device_set_from_ip4_config
  *
@@ -310,8 +294,7 @@
  */
 gboolean
 nm_system_device_set_from_ip4_config (const char *iface,
-							   NMIP4Config *config,
-							   gboolean route_to_iface)
+							   NMIP4Config *config)
 {
 	int len, i;
 
@@ -328,9 +311,9 @@
 		const NMSettingIP4Address *route = nm_ip4_config_get_static_route (config, i);
 
 		nm_system_device_set_ip4_route (iface, config, 
-								  route->gateway,
 								  route->address,
-								  netmask_to_prefix (route->netmask),
+								  route->netmask,
+								  route->gateway,
 								  nm_ip4_config_get_mss (config));
 	}
 
@@ -349,11 +332,11 @@
 gboolean
 nm_system_vpn_device_set_from_ip4_config (NMDevice *active_device,
                                           const char *iface,
-                                          NMIP4Config *config,
-                                          GSList *routes)
+                                          NMIP4Config *config)
 {
 	NMIP4Config *ad_config = NULL;
 	NMNamedManager *named_mgr;
+	int num;
 	int i;
 
 	g_return_val_if_fail (config != NULL, FALSE);
@@ -363,7 +346,8 @@
 		guint32 ad_gw = 0, vpn_gw = 0;
 		const NMSettingIP4Address *tmp;
 
-		for (i = 0; i < nm_ip4_config_get_num_addresses (ad_config); i++) {
+		num = nm_ip4_config_get_num_addresses (ad_config);
+		for (i = 0; i < num; i++) {
 			tmp = nm_ip4_config_get_address (ad_config, i);
 			if (tmp->gateway) {
 				ad_gw = tmp->gateway;
@@ -371,17 +355,20 @@
 			}
 		}
 
-		for (i = 0; i < nm_ip4_config_get_num_addresses (config); i++) {
-			tmp = nm_ip4_config_get_address (config, i);
-			if (tmp->gateway) {
-				vpn_gw = tmp->gateway;
-				break;
+		if (ad_gw) {
+			num = nm_ip4_config_get_num_addresses (config);
+			for (i = 0; i < num; i++) {
+				tmp = nm_ip4_config_get_address (config, i);
+				if (tmp->gateway) {
+					vpn_gw = tmp->gateway;
+					break;
+				}
 			}
-		}
 
-		nm_system_device_set_ip4_route (nm_device_get_ip_iface (active_device),
-								  ad_config, ad_gw, vpn_gw, 32,
-								  nm_ip4_config_get_mss (config));
+			nm_system_device_set_ip4_route (nm_device_get_ip_iface (active_device),
+									  ad_config, vpn_gw, 0xFFFFFFFF, ad_gw,
+									  nm_ip4_config_get_mss (config));
+		}
 	}
 
 	if (!iface || !strlen (iface))
@@ -396,15 +383,21 @@
 	if (nm_ip4_config_get_mtu (config))
 		nm_system_device_set_mtu (iface, nm_ip4_config_get_mtu (config));
 
-	if (g_slist_length (routes) == 0) {
-		nm_system_device_replace_default_ip4_route (iface, 0, 0);
-	} else {
-		GSList *iter;
+	/* Set routes */
+	num = nm_ip4_config_get_num_static_routes (config);
+	for (i = 0; i < num; i++) {
+		const NMSettingIP4Address *route = nm_ip4_config_get_static_route (config, i);
 
-		for (iter = routes; iter; iter = iter->next)
-			nm_system_device_add_ip4_route_via_device_with_iface (iface, (char *) iter->data);
+		nm_system_device_set_ip4_route (iface, config,
+								  route->address,
+								  route->netmask,
+								  route->gateway,
+								  nm_ip4_config_get_mss (config));
 	}
 
+	if (num == 0)
+		nm_system_device_replace_default_ip4_route (iface, 0, 0);
+
 out:
 	named_mgr = nm_named_manager_get ();
 	nm_named_manager_add_ip4_config (named_mgr, config, NM_NAMED_IP_CONFIG_TYPE_VPN);
@@ -552,45 +545,6 @@
 }
 
 /*
- * nm_system_device_add_ip4_route_via_device_with_iface
- *
- * Add route to the given device
- *
- */
-void nm_system_device_add_ip4_route_via_device_with_iface (const char *iface, const char *addr)
-{
-	struct rtnl_route *route;
-	struct nl_handle *nlh;
-	struct nl_addr *dst;
-	int iface_idx, err;
-
-	nlh = nm_netlink_get_default_handle ();
-	g_return_if_fail (nlh != NULL);
-
-	route = rtnl_route_alloc ();
-	g_return_if_fail (route != NULL);
-
-	iface_idx = nm_netlink_iface_to_index (iface);
-	if (iface_idx < 0)
-		goto out;
-	rtnl_route_set_oif (route, iface_idx);
-
-	if (!(dst = nl_addr_parse (addr, AF_INET)))
-		goto out;
-	rtnl_route_set_dst (route, dst);
-	nl_addr_put (dst);
-
-	err = rtnl_route_add (nlh, route, 0);
-	if (err) {
-		nm_warning ("rtnl_route_add() returned error %s (%d)\n%s",
-		            strerror (err), err, nl_geterror());
-	}
-
-out:
-	rtnl_route_put (route);
-}
-
-/*
  * nm_system_replace_default_ip4_route
  *
  * Replace default IPv4 route with one via the current device
@@ -803,4 +757,3 @@
 
 	nl_cache_free (route_cache);
 }
-

Modified: trunk/src/NetworkManagerSystem.h
==============================================================================
--- trunk/src/NetworkManagerSystem.h	(original)
+++ trunk/src/NetworkManagerSystem.h	Fri Jun  6 15:35:45 2008
@@ -41,8 +41,6 @@
                                                              guint32 gw,
                                                              guint32 mss);
 
-void			nm_system_device_add_ip4_route_via_device_with_iface (const char *iface, const char *route);
-
 void			nm_system_device_flush_ip4_addresses			(NMDevice *dev);
 void			nm_system_device_flush_ip4_addresses_with_iface	(const char *iface);
 
@@ -51,13 +49,11 @@
 void			nm_system_update_dns					(void);
 
 gboolean		nm_system_device_set_from_ip4_config		(const char *iface,
-												 NMIP4Config *config,
-												 gboolean route_to_iface);
+												 NMIP4Config *config);
 
 gboolean		nm_system_vpn_device_set_from_ip4_config	(NMDevice *active_device,
 									 const char *iface,
-									 NMIP4Config *config,
-									 GSList *routes);
+									 NMIP4Config *config);
 
 gboolean		nm_system_vpn_device_unset_from_ip4_config	(NMDevice *active_device, 
 									 const char *iface,

Modified: trunk/src/nm-device.c
==============================================================================
--- trunk/src/nm-device.c	(original)
+++ trunk/src/nm-device.c	Fri Jun  6 15:35:45 2008
@@ -1355,7 +1355,6 @@
 {
 	NMDevicePrivate *priv;
 	const char *ip_iface;
-	gboolean route_to_iface;
 	gboolean success;
 
 	g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
@@ -1381,16 +1380,7 @@
 
 	ip_iface = nm_device_get_ip_iface (self);
 
-	/* FIXME: Not sure if the following makes any sense. */
-	/* If iface and ip_iface are the same, it's a regular network device and we
-	   treat it as such. However, if they differ, it's most likely something like
-	   a serial device with ppp interface, so route all the traffic to it. */
-	if (strcmp (ip_iface, nm_device_get_iface (self)))
-		route_to_iface = TRUE;
-	else
-		route_to_iface = FALSE;
-
-	success = nm_system_device_set_from_ip4_config (ip_iface, config, route_to_iface);
+	success = nm_system_device_set_from_ip4_config (ip_iface, config);
 	if (success) {
 		nm_device_update_ip4_address (self);
 		nm_system_set_hostname (config);

Modified: trunk/src/vpn-manager/nm-vpn-connection.c
==============================================================================
--- trunk/src/vpn-manager/nm-vpn-connection.c	(original)
+++ trunk/src/vpn-manager/nm-vpn-connection.c	Fri Jun  6 15:35:45 2008
@@ -27,6 +27,8 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <errno.h>
+#include <stdlib.h>
 
 #include "NetworkManager.h"
 #include "NetworkManagerVPN.h"
@@ -228,17 +230,6 @@
 	return setting->service_type;
 }
 
-static GSList *
-nm_vpn_connection_get_routes (NMVPNConnection *connection)
-{
-	NMSettingVPN *setting;
-
-	setting = (NMSettingVPN *) nm_connection_get_setting (NM_VPN_CONNECTION_GET_PRIVATE (connection)->connection,
-											    NM_TYPE_SETTING_VPN);
-
-	return setting->routes;
-}
-
 static void
 plugin_state_changed (DBusGProxy *proxy,
 				  NMVPNServiceState state,
@@ -266,13 +257,21 @@
 	}
 }
 
+static const char *
+ip_address_to_string (guint32 numeric)
+{
+	struct in_addr temp_addr;
+
+	temp_addr.s_addr = numeric;
+	return inet_ntoa (temp_addr);
+}
+
 static void
 print_vpn_config (NMIP4Config *config,
 			   const char *tundev,
 			   const char *banner)
 {
 	const NMSettingIP4Address *addr;
-	struct in_addr temp_addr;
 	char *         dns_domain = NULL;
 	guint32        num;
 	guint32        i;
@@ -280,23 +279,28 @@
 	g_return_if_fail (config != NULL);
 
 	addr = nm_ip4_config_get_address (config, 0);
-	temp_addr.s_addr = addr->gateway;
-	nm_info ("VPN Gateway: %s", inet_ntoa (temp_addr));
+
+	nm_info ("VPN Gateway: %s", ip_address_to_string (addr->gateway));
 	nm_info ("Tunnel Device: %s", tundev);
-	temp_addr.s_addr = addr->address;
-	nm_info ("Internal IP4 Address: %s", inet_ntoa (temp_addr));
-	temp_addr.s_addr = addr->netmask;
-	nm_info ("Internal IP4 Netmask: %s", inet_ntoa (temp_addr));
-	temp_addr.s_addr = nm_ip4_config_get_ptp_address (config);
-	nm_info ("Internal IP4 Point-to-Point Address: %s", inet_ntoa (temp_addr));
+	nm_info ("Internal IP4 Address: %s", ip_address_to_string (addr->address));
+	nm_info ("Internal IP4 Netmask: %s", ip_address_to_string (addr->netmask));
+	nm_info ("Internal IP4 Point-to-Point Address: %s",
+		    ip_address_to_string (nm_ip4_config_get_ptp_address (config)));
 	nm_info ("Maximum Segment Size (MSS): %d", nm_ip4_config_get_mss (config));
 
-	num = nm_ip4_config_get_num_nameservers (config);
+	num = nm_ip4_config_get_num_static_routes (config);
 	for (i = 0; i < num; i++) {
-		temp_addr.s_addr = nm_ip4_config_get_nameserver (config, i);
-		nm_info ("Internal IP4 DNS: %s", inet_ntoa (temp_addr));
+		addr = nm_ip4_config_get_static_route (config, i);
+		nm_info ("Static Route: %s/%s Gateway: %s",
+			    ip_address_to_string (addr->address),
+			    ip_address_to_string (addr->netmask),
+			    ip_address_to_string (addr->gateway));
 	}
 
+	num = nm_ip4_config_get_num_nameservers (config);
+	for (i = 0; i < num; i++)
+		nm_info ("Internal IP4 DNS: %s", ip_address_to_string (nm_ip4_config_get_nameserver (config, i)));
+
 	if (nm_ip4_config_get_num_domains (config) > 0)
 		dns_domain = (char *) nm_ip4_config_get_domain (config, 0);
 	nm_info ("DNS Domain: '%s'", dns_domain ? dns_domain : "(none)");
@@ -307,6 +311,57 @@
 }
 
 static void
+merge_vpn_routes (NMVPNConnection *connection, NMIP4Config *config)
+{
+	NMSettingVPN *setting;
+	GSList *iter;
+
+	setting = NM_SETTING_VPN (nm_connection_get_setting (NM_VPN_CONNECTION_GET_PRIVATE (connection)->connection,
+											   NM_TYPE_SETTING_VPN));
+
+	/* FIXME: Shouldn't the routes from user (NMSettingVPN) be inserted in the beginning
+	   instead of appending to the end?
+	*/
+
+	for (iter = setting->routes; iter; iter = iter->next) {
+		struct in_addr tmp;
+		char *p, *route;
+		long int prefix = 32;
+
+		route = g_strdup ((char *) iter->data);
+		p = strchr (route, '/');
+		if (!p || !(*(p + 1))) {
+			nm_warning ("Ignoring invalid route '%s'", route);
+			goto next;
+		}
+
+		errno = 0;
+		prefix = strtol (p + 1, NULL, 10);
+		if (errno || prefix < 0 || prefix > 32) {
+			nm_warning ("Ignoring invalid route '%s'", route);
+			goto next;
+		}
+
+		/* don't pass the prefix to inet_pton() */
+		*p = '\0';
+		if (inet_pton (AF_INET, route, &tmp) > 0) {
+			NMSettingIP4Address *addr;
+
+			addr = g_new0 (NMSettingIP4Address, 1);
+			addr->address = tmp.s_addr;
+			addr->netmask = ntohl (0xFFFFFFFF << (32 - prefix));
+			addr->gateway = 0;
+
+			nm_ip4_config_take_static_route (config, addr);
+		} else
+			nm_warning ("Ignoring invalid route '%s'", route);
+
+next:
+		g_free (route);
+	}
+}
+
+static void
 nm_vpn_connection_ip4_config_get (DBusGProxy *proxy,
 						    GHashTable *config_hash,
 						    gpointer user_data)
@@ -395,6 +450,18 @@
 		priv->banner = g_strdup (g_value_get_string (val));
 	}
 
+	val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP4_CONFIG_ROUTES);
+	if (val) {
+		GSList *routes;
+		GSList *iter;
+
+		routes = nm_utils_ip4_addresses_from_gvalue (val);
+		for (iter = routes; iter; iter = iter->next)
+			nm_ip4_config_take_static_route (config, (NMSettingIP4Address *) iter->data);
+
+		g_slist_free (routes);
+	}
+
 	print_vpn_config (config, priv->tundev, priv->banner);
 
 	priv = NM_VPN_CONNECTION_GET_PRIVATE (connection);
@@ -403,9 +470,9 @@
 	/* Merge in user overrides from the NMConnection's IPv4 setting */
 	s_ip4 = NM_SETTING_IP4_CONFIG (nm_connection_get_setting (priv->connection, NM_TYPE_SETTING_IP4_CONFIG));
 	nm_utils_merge_ip4_config (config, s_ip4);
+	merge_vpn_routes (connection, config);
 
-	if (nm_system_vpn_device_set_from_ip4_config (priv->parent_dev, priv->tundev, priv->ip4_config,
-										 nm_vpn_connection_get_routes (connection))) {
+	if (nm_system_vpn_device_set_from_ip4_config (priv->parent_dev, priv->tundev, priv->ip4_config)) {
 		nm_info ("VPN connection '%s' (IP Config Get) complete.",
 			    nm_vpn_connection_get_name (connection));
 		nm_vpn_connection_set_vpn_state (connection,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]