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



Author: dcbw
Date: Sat Oct 11 14:26:41 2008
New Revision: 4169
URL: http://svn.gnome.org/viewvc/NetworkManager?rev=4169&view=rev

Log:
2008-10-11  Dan Williams  <dcbw redhat com>

	Add support for VPN subnet gateways (bgo #549196)

	* include/NetworkManager.h
		- Add key for internal VPN subnet gateway

	* src/vpn-manager/nm-vpn-connection.c
		- (ip_address_to_string): return a const from a static buffer so we
			don't leak a lot of strings
		- (print_vpn_config): print internal VPN gateway as well
		- (nm_vpn_connection_ip4_config_get): grab internal VPN gateway from
			VPN service too
		- (nm_vpn_connection_get_ip4_internal_gateway): new function

	* src/NetworkManagerSystem.c
	  src/NetworkManagerSystem.h
		- (nm_system_device_replace_default_ip4_route): split into two, one for
			VPN connections and one for normal devices
		- (replace_default_ip4_route): break out route stuff into its own function
		- (nm_system_replace_default_ip4_route_vpn,
		   nm_system_replace_default_ip4_route): simplify by having two cases,
			one for VPNs and one for normal devices

	* src/NetworkManagerPolicy.c
		- (update_routing_and_dns): simplify, use split default route replacement
			functions



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

Modified: trunk/include/NetworkManagerVPN.h
==============================================================================
--- trunk/include/NetworkManagerVPN.h	(original)
+++ trunk/include/NetworkManagerVPN.h	Sat Oct 11 14:26:41 2008
@@ -112,17 +112,23 @@
 	NM_VPN_PLUGIN_FAILURE_BAD_IP_CONFIG
 } NMVPNPluginFailure;
 
-#define NM_VPN_PLUGIN_IP4_CONFIG_GATEWAY "gateway"
-#define NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS "address"
-#define NM_VPN_PLUGIN_IP4_CONFIG_PTP     "ptp"
-#define NM_VPN_PLUGIN_IP4_CONFIG_PREFIX  "prefix"
-#define NM_VPN_PLUGIN_IP4_CONFIG_DNS     "dns"
-#define NM_VPN_PLUGIN_IP4_CONFIG_NBNS    "nbns"
-#define NM_VPN_PLUGIN_IP4_CONFIG_MSS     "mss"
-#define NM_VPN_PLUGIN_IP4_CONFIG_MTU     "mtu"
-#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"
+
+#define NM_VPN_PLUGIN_IP4_CONFIG_EXT_GATEWAY "gateway"
+#define NM_VPN_PLUGIN_IP4_CONFIG_INT_GATEWAY "internal-gateway"
+#define NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS     "address"
+#define NM_VPN_PLUGIN_IP4_CONFIG_PTP         "ptp"
+#define NM_VPN_PLUGIN_IP4_CONFIG_PREFIX      "prefix"
+#define NM_VPN_PLUGIN_IP4_CONFIG_DNS         "dns"
+#define NM_VPN_PLUGIN_IP4_CONFIG_NBNS        "nbns"
+#define NM_VPN_PLUGIN_IP4_CONFIG_MSS         "mss"
+#define NM_VPN_PLUGIN_IP4_CONFIG_MTU         "mtu"
+#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"
+
+/* Deprecated */
+#define NM_VPN_PLUGIN_IP4_CONFIG_GATEWAY   NM_VPN_PLUGIN_IP4_CONFIG_EXT_GATEWAY
+
 
 #endif /* NETWORK_MANAGER_VPN_H */

Modified: trunk/src/NetworkManagerPolicy.c
==============================================================================
--- trunk/src/NetworkManagerPolicy.c	(original)
+++ trunk/src/NetworkManagerPolicy.c	Sat Oct 11 14:26:41 2008
@@ -475,13 +475,11 @@
 	NMNamedManager *named_mgr;
 	GSList *devices = NULL, *iter, *vpns;
 	NMIP4Config *ip4_config = NULL;
+	const NMSettingIP4Address *addr;
 	const char *ip_iface = NULL;
-	const char *parent_iface = NULL;
 	NMVPNConnection *vpn = NULL;
 	NMConnection *connection = NULL;
 	NMSettingConnection *s_con = NULL;
-	guint32 parent_mss = 0;
-	guint32 gateway = 0;
 
 	best = get_best_device (policy->manager, &best_req);
 	if (!best)
@@ -502,22 +500,24 @@
 
 	/* VPNs are the default route only if they don't have custom routes */
 	if (vpn) {
-		NMIP4Config *vpn_config;
-
-		vpn_config = nm_vpn_connection_get_ip4_config (vpn);
-		if (nm_ip4_config_get_num_routes (vpn_config) == 0) {
+		ip4_config = nm_vpn_connection_get_ip4_config (vpn);
+		if (nm_ip4_config_get_num_routes (ip4_config) == 0) {
 			NMIP4Config *parent_ip4;
 			NMDevice *parent;
 
-			connection = nm_vpn_connection_get_connection (vpn);
 			ip_iface = nm_vpn_connection_get_ip_iface (vpn);
-			ip4_config = vpn_config;
+			connection = nm_vpn_connection_get_connection (vpn);
+			addr = nm_ip4_config_get_address (ip4_config, 0);
 
 			parent = nm_vpn_connection_get_parent_device (vpn);
-			parent_iface = nm_device_get_ip_iface (parent);
 			parent_ip4 = nm_device_get_ip4_config (parent);
-			if (parent_ip4)
-				parent_mss = nm_ip4_config_get_mss (parent_ip4);
+
+			nm_system_replace_default_ip4_route_vpn (ip_iface,
+			                                         addr->gateway,
+			                                         nm_vpn_connection_get_ip4_internal_gateway (vpn),
+			                                         nm_ip4_config_get_mss (ip4_config),
+			                                         nm_device_get_ip_iface (parent),
+			                                         nm_ip4_config_get_mss (parent_ip4));
 
 			dns_type = NM_NAMED_IP_CONFIG_TYPE_VPN;
 		}
@@ -526,15 +526,13 @@
 
 	/* The best device gets the default route if a VPN connection didn't */
 	if (!ip_iface || !ip4_config) {
-		const NMSettingIP4Address *addr;
-
 		connection = nm_act_request_get_connection (best_req);
 		ip_iface = nm_device_get_ip_iface (best);
 		ip4_config = nm_device_get_ip4_config (best);
-		if (ip4_config) {
-			addr = nm_ip4_config_get_address (ip4_config, 0);
-			gateway = addr->gateway;
-		}
+		g_assert (ip4_config);
+		addr = nm_ip4_config_get_address (ip4_config, 0);
+
+		nm_system_replace_default_ip4_route (ip_iface, addr->gateway, nm_ip4_config_get_mss (ip4_config));
 
 		dns_type = NM_NAMED_IP_CONFIG_TYPE_BEST_DEVICE;
 	}
@@ -545,13 +543,6 @@
 		goto out;
 	}
 
-	/* Set the new default route */
-	nm_system_device_replace_default_ip4_route (ip_iface,
-	                                            gateway,
-	                                            nm_ip4_config_get_mss (ip4_config),
-	                                            parent_iface,
-	                                            parent_mss);
-
 	/* Update the default active connection.  Only mark the new default
 	 * active connection after setting default = FALSE on all other connections
 	 * first.  The order is important, we don't want two connections marked

Modified: trunk/src/NetworkManagerSystem.c
==============================================================================
--- trunk/src/NetworkManagerSystem.c	(original)
+++ trunk/src/NetworkManagerSystem.c	Sat Oct 11 14:26:41 2008
@@ -533,35 +533,25 @@
 	return NULL;
 }
 
-/*
- * nm_system_replace_default_ip4_route
- *
- * Replace default IPv4 route with one via the current device
- *
- */
-void
-nm_system_device_replace_default_ip4_route (const char *iface,
-                                            guint32 gw,
-                                            guint32 mss,
-                                            const char *parent_iface,
-                                            guint32 parent_mss)
+static int
+replace_default_ip4_route (const char *iface, guint32 gw, guint32 mss)
 {
 	struct rtnl_route *route = NULL;
-	struct rtnl_route *gw_route = NULL;
 	struct nl_handle *nlh;
 	struct nl_addr *gw_addr = NULL;
-	int iface_idx, err;
-	gboolean success = FALSE;
+	int iface_idx, err = -1;
+
+	g_return_val_if_fail (iface != NULL, -1);
 
 	nlh = nm_netlink_get_default_handle ();
-	g_return_if_fail (nlh != NULL);
+	g_return_val_if_fail (nlh != NULL, -1);
 
 	iface_idx = nm_netlink_iface_to_index (iface);
 	if (iface_idx < 0)
-		return;
+		return -1;
 
 	route = rtnl_route_alloc();
-	g_return_if_fail (route != NULL);
+	g_return_val_if_fail (route != NULL, -1);
 
 	rtnl_route_set_scope (route, RT_SCOPE_UNIVERSE);
 	rtnl_route_set_oif (route, iface_idx);
@@ -580,36 +570,97 @@
 
 	/* Add the new default route */
 	err = rtnl_route_add (nlh, route, NLM_F_REPLACE);
-	if (err == 0) {
-		/* Everything good */
-		success = TRUE;
-		goto out;
-	} else if (err != -ESRCH) {
-		nm_warning ("rtnl_route_add() returned error %s (%d)\n%s",
-		            strerror (err), err, nl_geterror());
-		goto out;
+
+out:
+	rtnl_route_put (route);
+	return err;
+}
+
+/*
+ * nm_system_replace_default_ip4_route_vpn
+ *
+ * Replace default IPv4 route with one via the current device
+ *
+ */
+gboolean
+nm_system_replace_default_ip4_route_vpn (const char *iface,
+                                         guint32 ext_gw,
+                                         guint32 int_gw,
+                                         guint32 mss,
+                                         const char *parent_iface,
+                                         guint32 parent_mss)
+{
+	struct rtnl_route *gw_route = NULL;
+	struct nl_handle *nlh;
+	gboolean success = FALSE;
+	int err;
+
+	nlh = nm_netlink_get_default_handle ();
+	g_return_val_if_fail (nlh != NULL, FALSE);
+
+	err = replace_default_ip4_route (iface, int_gw, mss);
+	if (err != -ESRCH) {
+		nm_warning ("replace_default_ip4_route() returned error %s (%d)",
+		            strerror (err), err);
+		return FALSE;
 	}
 
 	/* Try adding a direct route to the gateway first */
-	gw_route = add_ip4_route_to_gateway (parent_iface ? parent_iface : iface,
-	                                     gw,
-	                                     parent_iface ? parent_mss : mss);
+	gw_route = add_ip4_route_to_gateway (parent_iface, ext_gw, parent_mss);
 	if (!gw_route)
-		goto out;
+		return FALSE;
 
 	/* Try adding the original route again */
-	err = rtnl_route_add (nlh, route, NLM_F_REPLACE);
+	err = replace_default_ip4_route (iface, int_gw, mss);
 	if (err != 0) {
 		rtnl_route_del (nlh, gw_route, 0);
 		nm_warning ("Failed to set IPv4 default route on '%s': %s", iface, nl_geterror ());
+	} else
+		success = TRUE;
+
+	rtnl_route_put (gw_route);
+	return success;
+}
+
+/*
+ * nm_system_replace_default_ip4_route
+ *
+ * Replace default IPv4 route with one via the current device
+ *
+ */
+gboolean
+nm_system_replace_default_ip4_route (const char *iface, guint32 gw, guint32 mss)
+{
+	struct rtnl_route *gw_route = NULL;
+	struct nl_handle *nlh;
+	gboolean success = FALSE;
+	int err;
+
+	nlh = nm_netlink_get_default_handle ();
+	g_return_val_if_fail (nlh != NULL, FALSE);
+
+	err = replace_default_ip4_route (iface, gw, mss);
+	if (err != -ESRCH) {
+		nm_warning ("replace_default_ip4_route() returned error %s (%d)",
+		            strerror (err), err);
+		return FALSE;
 	}
 
-out:
-	if (gw_route)
-		rtnl_route_put (gw_route);
+	/* Try adding a direct route to the gateway first */
+	gw_route = add_ip4_route_to_gateway (iface, gw, mss);
+	if (!gw_route)
+		return FALSE;
+
+	/* Try adding the original route again */
+	err = replace_default_ip4_route (iface, gw, mss);
+	if (err != 0) {
+		rtnl_route_del (nlh, gw_route, 0);
+		nm_warning ("Failed to set IPv4 default route on '%s': %s", iface, nl_geterror ());
+	} else
+		success = TRUE;
 
-	if (route)
-		rtnl_route_put (route);
+	rtnl_route_put (gw_route);
+	return success;
 }
 
 /*

Modified: trunk/src/NetworkManagerSystem.h
==============================================================================
--- trunk/src/NetworkManagerSystem.h	(original)
+++ trunk/src/NetworkManagerSystem.h	Sat Oct 11 14:26:41 2008
@@ -34,11 +34,16 @@
 void			nm_system_device_flush_ip4_routes				(NMDevice *dev);
 void			nm_system_device_flush_ip4_routes_with_iface	(const char *iface);
 
-void			nm_system_device_replace_default_ip4_route   (const char *iface,
-                                                             guint32 gw,
-                                                             guint32 mss,
-                                                             const char *parent_iface,
-                                                             guint32 parent_mss);
+gboolean		nm_system_replace_default_ip4_route   (const char *iface,
+                                                       guint32 gw,
+                                                       guint32 mss);
+
+gboolean		nm_system_replace_default_ip4_route_vpn (const char *iface,
+                                                         guint32 ext_gw,
+                                                         guint32 int_gw,
+                                                         guint32 mss,
+                                                         const char *parent_iface,
+                                                         guint32 parent_mss);
 
 void			nm_system_device_flush_ip4_addresses			(NMDevice *dev);
 void			nm_system_device_flush_ip4_addresses_with_iface	(const char *iface);

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	Sat Oct 11 14:26:41 2008
@@ -71,6 +71,7 @@
 	DBusGProxy *proxy;
 	guint ipconfig_timeout;
 	NMIP4Config *ip4_config;
+	guint32 ip4_internal_gw;
 	char *tundev;
 	char *tapdev;
 	char *banner;
@@ -293,13 +294,13 @@
 ip_address_to_string (guint32 numeric)
 {
 	struct in_addr temp_addr;
-	char buf[INET_ADDRSTRLEN+1];
+	static char buf[INET_ADDRSTRLEN + 1];
 
 	memset (&buf, '\0', sizeof (buf));
 	temp_addr.s_addr = numeric;
 
 	if (inet_ntop (AF_INET, &temp_addr, buf, INET_ADDRSTRLEN)) {
-		return g_strdup (buf);
+		return buf;
 	} else {
 		nm_warning ("%s: error converting IP4 address 0x%X",
 		            __func__, ntohl (temp_addr.s_addr));
@@ -309,8 +310,9 @@
 
 static void
 print_vpn_config (NMIP4Config *config,
-			   const char *tundev,
-			   const char *banner)
+                  guint32 internal_gw,
+                  const char *tundev,
+                  const char *banner)
 {
 	const NMSettingIP4Address *addr;
 	char *         dns_domain = NULL;
@@ -322,6 +324,8 @@
 	addr = nm_ip4_config_get_address (config, 0);
 
 	nm_info ("VPN Gateway: %s", ip_address_to_string (addr->gateway));
+	if (internal_gw)
+		nm_info ("Internal Gateway: %s", ip_address_to_string (internal_gw));
 	nm_info ("Tunnel Device: %s", tundev);
 	nm_info ("Internal IP4 Address: %s", ip_address_to_string (addr->address));
 	nm_info ("Internal IP4 Prefix: %d", addr->prefix);
@@ -385,7 +389,13 @@
 		goto error;
 	}
 
-	val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP4_CONFIG_GATEWAY);
+	/* Internal address of the VPN subnet's gateway */
+	val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP4_CONFIG_INT_GATEWAY);
+	if (val)
+		priv->ip4_internal_gw = g_value_get_uint (val);
+
+	/* External world-visible address of the VPN server */
+	val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP4_CONFIG_EXT_GATEWAY);
 	if (val)
 		addr->gateway = g_value_get_uint (val);
 
@@ -456,7 +466,7 @@
 		g_slist_free (routes);
 	}
 
-	print_vpn_config (config, priv->tundev, priv->banner);
+	print_vpn_config (config, priv->ip4_internal_gw, priv->tundev, priv->banner);
 
 	/* 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));
@@ -672,6 +682,14 @@
 	return NM_VPN_CONNECTION_GET_PRIVATE (connection)->parent_dev;
 }
 
+guint32
+nm_vpn_connection_get_ip4_internal_gateway (NMVPNConnection *connection)
+{
+	g_return_val_if_fail (NM_IS_VPN_CONNECTION (connection), 0);
+
+	return NM_VPN_CONNECTION_GET_PRIVATE (connection)->ip4_internal_gw;
+}
+
 void
 nm_vpn_connection_fail (NMVPNConnection *connection,
                         NMVPNConnectionStateReason reason)

Modified: trunk/src/vpn-manager/nm-vpn-connection.h
==============================================================================
--- trunk/src/vpn-manager/nm-vpn-connection.h	(original)
+++ trunk/src/vpn-manager/nm-vpn-connection.h	Sat Oct 11 14:26:41 2008
@@ -73,5 +73,6 @@
 NMIP4Config *        nm_vpn_connection_get_ip4_config  (NMVPNConnection *connection);
 const char *         nm_vpn_connection_get_ip_iface    (NMVPNConnection *connection);
 NMDevice *           nm_vpn_connection_get_parent_device (NMVPNConnection *connection);
+guint32        nm_vpn_connection_get_ip4_internal_gateway (NMVPNConnection *connection);
 
 #endif /* NM_VPN_CONNECTION_H */



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