NetworkManager r4277 - in trunk: . src src/vpn-manager
- From: dcbw svn gnome org
- To: svn-commits-list gnome org
- Subject: NetworkManager r4277 - in trunk: . src src/vpn-manager
- Date: Fri, 7 Nov 2008 13:57:39 +0000 (UTC)
Author: dcbw
Date: Fri Nov 7 13:57:39 2008
New Revision: 4277
URL: http://svn.gnome.org/viewvc/NetworkManager?rev=4277&view=rev
Log:
2008-11-07 Dan Williams <dcbw redhat com>
Fix deletion of VPN gateway route on DHCP renew (bgo #558133)
* src/NetworkManagerSystem.c
src/NetworkManagerSystem.h
- (nm_system_device_set_ip4_route): return the route that was added
- (nm_system_add_ip4_vpn_gateway_route): make add_vpn_gateway_route()
public, clean up, and return the route that was added
- (nm_system_apply_ip4_config): remove VPN related stuff to simplify,
since nm_system_add_ip4_vpn_gateway_route() is now available; add
flags to allow only certain attributes of the NMIP4Config to be
applied
* src/nm-device.c
- (handle_dhcp_lease_change): don't touch the DHCP4 config on failure
- (nm_device_set_ip4_config): use nm_ip4_config_diff() to only apply
what's really changed between the old and new configs; don't export
the new IP4 config on failure; always send the DNS info to the
named manager
* src/vpn-manager/nm-vpn-connection.c
- (device_ip4_config_changed, nm_vpn_connection_new, dispose): track the
parent device's IP4Config and re-add the VPN gateway route when it
changes
- (nm_vpn_connection_ip4_config_get): add the VPN gateway route (since
nm_system_apply_ip4_config() no longer does) and cache it for later
- (connection_state_changed): move cleanup code to its own function
- (vpn_cleanup): delete any previously added VPN gateway route; and
re-apply the parent device's addresses and routes using
nm_system_apply_ip4_config(), not nm_device_set_ip4_config()
Modified:
trunk/ChangeLog
trunk/src/NetworkManagerSystem.c
trunk/src/NetworkManagerSystem.h
trunk/src/nm-device.c
trunk/src/nm-device.h
trunk/src/vpn-manager/nm-vpn-connection.c
Modified: trunk/src/NetworkManagerSystem.c
==============================================================================
--- trunk/src/NetworkManagerSystem.c (original)
+++ trunk/src/NetworkManagerSystem.c Fri Nov 7 13:57:39 2008
@@ -103,7 +103,7 @@
return route;
}
-static void
+static struct rtnl_route *
nm_system_device_set_ip4_route (const char *iface,
guint32 ip4_dest,
guint32 ip4_prefix,
@@ -118,17 +118,17 @@
int err, iface_idx;
nlh = nm_netlink_get_default_handle ();
- g_return_if_fail (nlh != NULL);
+ g_return_val_if_fail (nlh != NULL, NULL);
iface_idx = nm_netlink_iface_to_index (iface);
- g_return_if_fail (iface_idx >= 0);
+ g_return_val_if_fail (iface_idx >= 0, NULL);
route = create_route (iface_idx, mss);
- g_return_if_fail (route != NULL);
+ g_return_val_if_fail (route != NULL, NULL);
/* Destination */
dest_addr = nl_addr_build (AF_INET, &ip4_dest, sizeof (ip4_dest));
- g_return_if_fail (dest_addr != NULL);
+ g_return_val_if_fail (dest_addr != NULL, NULL);
nl_addr_set_prefixlen (dest_addr, (int) ip4_prefix);
rtnl_route_set_dst (route, dest_addr);
@@ -143,7 +143,7 @@
} else {
nm_warning ("Invalid gateway");
rtnl_route_put (route);
- return;
+ return NULL;
}
}
@@ -168,17 +168,20 @@
if (err)
rtnl_route_del (nlh, route2, 0);
}
-
rtnl_route_put (route2);
}
}
- 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 (err) {
+ nm_warning ("Failed to set IPv4 route on '%s': %s", iface, nl_geterror ());
+ rtnl_route_put (route);
+ route = NULL;
+ }
+
+ return route;
}
typedef struct {
@@ -267,23 +270,22 @@
return TRUE;
}
-static void
-add_vpn_gateway_route (NMDevice *parent_device,
- const char *iface,
- NMIP4Config *vpn_config)
+struct rtnl_route *
+nm_system_add_ip4_vpn_gateway_route (NMDevice *parent_device, NMIP4Config *vpn_config)
{
NMIP4Config *parent_config;
guint32 parent_gw = 0, parent_prefix = 0, vpn_gw = 0, i;
NMIP4Address *tmp;
+ struct rtnl_route *route = NULL;
- g_return_if_fail (NM_IS_DEVICE (parent_device));
+ g_return_val_if_fail (NM_IS_DEVICE (parent_device), NULL);
/* Set up a route to the VPN gateway's public IP address through the default
* network device if the VPN gateway is on a different subnet.
*/
parent_config = nm_device_get_ip4_config (parent_device);
- g_return_if_fail (parent_config != NULL);
+ g_return_val_if_fail (parent_config != NULL, NULL);
for (i = 0; i < nm_ip4_config_get_num_addresses (parent_config); i++) {
tmp = nm_ip4_config_get_address (parent_config, i);
@@ -303,19 +305,21 @@
}
if (!parent_gw || !vpn_gw)
- return;
+ return NULL;
/* 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)) {
- nm_system_device_set_ip4_route (nm_device_get_ip_iface (parent_device),
- vpn_gw, 32, 0, 0, nm_ip4_config_get_mss (parent_config));
+ route = nm_system_device_set_ip4_route (nm_device_get_ip_iface (parent_device),
+ vpn_gw, 32, 0, 0, nm_ip4_config_get_mss (parent_config));
} else {
- nm_system_device_set_ip4_route (nm_device_get_ip_iface (parent_device),
- vpn_gw, 32, parent_gw, 0, nm_ip4_config_get_mss (parent_config));
+ route = nm_system_device_set_ip4_route (nm_device_get_ip_iface (parent_device),
+ vpn_gw, 32, parent_gw, 0, nm_ip4_config_get_mss (parent_config));
}
+
+ return route;
}
/*
@@ -325,46 +329,49 @@
*
*/
gboolean
-nm_system_apply_ip4_config (NMDevice *device,
- const char *iface,
+nm_system_apply_ip4_config (const char *iface,
NMIP4Config *config,
int priority,
- gboolean is_vpn)
+ NMIP4ConfigCompareFlags flags)
{
int i;
g_return_val_if_fail (iface != NULL, FALSE);
g_return_val_if_fail (config != NULL, FALSE);
- if (!add_ip4_addresses (config, iface))
- return FALSE;
-
- if (is_vpn)
- add_vpn_gateway_route (device, iface, config);
-
- sleep (1);
-
- for (i = 0; i < nm_ip4_config_get_num_routes (config); i++) {
- NMIP4Route *route = nm_ip4_config_get_route (config, i);
-
- /* Don't add the route if it's more specific than one of the subnets
- * the device already has an IP address on.
- */
- if (ip4_dest_in_same_subnet (config,
- nm_ip4_route_get_dest (route),
- nm_ip4_route_get_prefix (route)))
- continue;
-
- nm_system_device_set_ip4_route (iface,
- nm_ip4_route_get_dest (route),
- nm_ip4_route_get_prefix (route),
- nm_ip4_route_get_next_hop (route),
- nm_ip4_route_get_metric (route),
- nm_ip4_config_get_mss (config));
+ if (flags & NM_IP4_COMPARE_FLAG_ADDRESSES) {
+ if (!add_ip4_addresses (config, iface))
+ return FALSE;
+ sleep (1);
+ }
+
+ if (flags & NM_IP4_COMPARE_FLAG_ROUTES) {
+ for (i = 0; i < nm_ip4_config_get_num_routes (config); i++) {
+ NMIP4Route *route = nm_ip4_config_get_route (config, i);
+ struct rtnl_route *tmp;
+
+ /* Don't add the route if it's more specific than one of the subnets
+ * the device already has an IP address on.
+ */
+ if (ip4_dest_in_same_subnet (config,
+ nm_ip4_route_get_dest (route),
+ nm_ip4_route_get_prefix (route)))
+ continue;
+
+ tmp = nm_system_device_set_ip4_route (iface,
+ nm_ip4_route_get_dest (route),
+ nm_ip4_route_get_prefix (route),
+ nm_ip4_route_get_next_hop (route),
+ nm_ip4_route_get_metric (route),
+ nm_ip4_config_get_mss (config));
+ rtnl_route_put (tmp);
+ }
}
- if (nm_ip4_config_get_mtu (config))
- nm_system_device_set_mtu (iface, nm_ip4_config_get_mtu (config));
+ if (flags & NM_IP4_COMPARE_FLAG_MTU) {
+ if (nm_ip4_config_get_mtu (config))
+ nm_system_device_set_mtu (iface, nm_ip4_config_get_mtu (config));
+ }
if (priority > 0)
nm_system_device_set_priority (iface, config, priority);
Modified: trunk/src/NetworkManagerSystem.h
==============================================================================
--- trunk/src/NetworkManagerSystem.h (original)
+++ trunk/src/NetworkManagerSystem.h Fri Nov 7 13:57:39 2008
@@ -22,6 +22,9 @@
#ifndef NETWORK_MANAGER_SYSTEM_H
#define NETWORK_MANAGER_SYSTEM_H
+#include <netlink/route/rtnl.h>
+#include <netlink/route/route.h>
+
#include <glib.h>
#include "nm-device.h"
#include "nm-ip4-config.h"
@@ -44,17 +47,19 @@
const char *parent_iface,
guint32 parent_mss);
+struct rtnl_route *nm_system_add_ip4_vpn_gateway_route (NMDevice *parent_device, NMIP4Config *vpn_config);
+
+
void nm_system_device_flush_ip4_addresses (NMDevice *dev);
void nm_system_device_flush_ip4_addresses_with_iface (const char *iface);
void nm_system_enable_loopback (void);
void nm_system_update_dns (void);
-gboolean nm_system_apply_ip4_config (NMDevice *device,
- const char *iface,
+gboolean nm_system_apply_ip4_config (const char *iface,
NMIP4Config *config,
int priority,
- gboolean is_vpn);
+ NMIP4ConfigCompareFlags flags);
gboolean nm_system_device_set_up_down (NMDevice *dev,
gboolean up,
Modified: trunk/src/nm-device.c
==============================================================================
--- trunk/src/nm-device.c (original)
+++ trunk/src/nm-device.c Fri Nov 7 13:57:39 2008
@@ -120,6 +120,8 @@
static gboolean nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware);
static gboolean nm_device_is_up (NMDevice *self);
+static gboolean nm_device_set_ip4_config (NMDevice *dev, NMIP4Config *config, NMDeviceStateReason *reason);
+
static void
device_interface_init (NMDeviceInterface *device_interface_class)
{
@@ -1754,12 +1756,12 @@
g_object_set_data (G_OBJECT (req), NM_ACT_REQUEST_IP4_CONFIG, config);
- if (!nm_device_set_ip4_config (device, config, &reason)) {
+ if (nm_device_set_ip4_config (device, config, &reason))
+ nm_dhcp_manager_set_dhcp4_config (priv->dhcp_manager, ip_iface, priv->dhcp4_config);
+ else {
nm_warning ("Failed to update IP4 config in response to DHCP event.");
nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason);
}
-
- nm_dhcp_manager_set_dhcp4_config (priv->dhcp_manager, ip_iface, priv->dhcp4_config);
}
static void
@@ -1905,12 +1907,17 @@
}
-gboolean
-nm_device_set_ip4_config (NMDevice *self, NMIP4Config *config, NMDeviceStateReason *reason)
+static gboolean
+nm_device_set_ip4_config (NMDevice *self,
+ NMIP4Config *new_config,
+ NMDeviceStateReason *reason)
{
NMDevicePrivate *priv;
const char *ip_iface;
- gboolean success;
+ NMIP4Config *old_config = NULL;
+ gboolean success = TRUE;
+ NMIP4ConfigCompareFlags diff = NM_IP4_COMPARE_FLAG_ALL;
+ NMNamedManager *named_mgr;
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
g_return_val_if_fail (reason != NULL, FALSE);
@@ -1918,30 +1925,39 @@
priv = NM_DEVICE_GET_PRIVATE (self);
ip_iface = nm_device_get_ip_iface (self);
- if (priv->ip4_config) {
- NMNamedManager *named_mgr;
+ old_config = priv->ip4_config;
- /* Remove any previous IP4 Config from the named manager */
- named_mgr = nm_named_manager_get ();
- nm_named_manager_remove_ip4_config (named_mgr, ip_iface, priv->ip4_config);
- g_object_unref (named_mgr);
+ if (new_config && old_config)
+ diff = nm_ip4_config_diff (new_config, old_config);
+
+ /* No actual change, do nothing */
+ if (diff == NM_IP4_COMPARE_FLAG_NONE)
+ return TRUE;
- g_object_unref (priv->ip4_config);
+ named_mgr = nm_named_manager_get ();
+ if (old_config) {
+ /* Remove any previous IP4 Config from the named manager */
+ nm_named_manager_remove_ip4_config (named_mgr, ip_iface, old_config);
+ g_object_unref (old_config);
priv->ip4_config = NULL;
}
- if (!config)
- return TRUE;
+ if (new_config) {
+ priv->ip4_config = g_object_ref (new_config);
- priv->ip4_config = g_object_ref (config);
+ success = nm_system_apply_ip4_config (ip_iface, new_config, nm_device_get_priority (self), diff);
+ if (success) {
+ /* Export over D-Bus */
+ if (!nm_ip4_config_get_dbus_path (new_config))
+ nm_ip4_config_export (new_config);
- /* Export over D-Bus if needed */
- if (!nm_ip4_config_get_dbus_path (config))
- nm_ip4_config_export (config);
-
- success = nm_system_apply_ip4_config (self, ip_iface, config, nm_device_get_priority (self), FALSE);
- if (success)
- nm_device_update_ip4_address (self);
+ /* Add the DNS information to the named manager */
+ nm_named_manager_add_ip4_config (named_mgr, ip_iface, new_config, NM_NAMED_IP_CONFIG_TYPE_DEFAULT);
+
+ nm_device_update_ip4_address (self);
+ }
+ }
+ g_object_unref (named_mgr);
g_object_notify (G_OBJECT (self), NM_DEVICE_INTERFACE_IP4_CONFIG);
Modified: trunk/src/nm-device.h
==============================================================================
--- trunk/src/nm-device.h (original)
+++ trunk/src/nm-device.h Fri Nov 7 13:57:39 2008
@@ -139,9 +139,6 @@
NMDHCP4Config * nm_device_get_dhcp4_config (NMDevice *dev);
NMIP4Config * nm_device_get_ip4_config (NMDevice *dev);
-gboolean nm_device_set_ip4_config (NMDevice *dev,
- NMIP4Config *config,
- NMDeviceStateReason *reason);
void * nm_device_get_system_config_data (NMDevice *dev);
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 Nov 7 13:57:39 2008
@@ -44,6 +44,7 @@
#include "nm-dbus-glib-types.h"
#include "NetworkManagerUtils.h"
#include "nm-named-manager.h"
+#include "nm-netlink.h"
#include "nm-vpn-connection-glue.h"
@@ -56,22 +57,25 @@
DBusGProxyCall *secrets_call;
NMActRequest *act_request;
- NMDevice *parent_dev;
char *ac_path;
+ NMDevice *parent_dev;
+ gulong device_monitor;
+ gulong device_ip4;
+
gboolean is_default;
NMActiveConnectionState state;
NMVPNConnectionState vpn_state;
NMVPNConnectionStateReason failure_reason;
- gulong device_monitor;
DBusGProxy *proxy;
guint ipconfig_timeout;
NMIP4Config *ip4_config;
guint32 ip4_internal_gw;
char *tundev;
- char *tapdev;
char *banner;
+
+ struct rtnl_route *gw_route;
} NMVPNConnectionPrivate;
#define NM_VPN_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_VPN_CONNECTION, NMVPNConnectionPrivate))
@@ -155,7 +159,7 @@
nm_utils_call_dispatcher ("vpn-up",
priv->connection,
priv->parent_dev,
- priv->tapdev ? priv->tapdev : priv->tundev);
+ priv->tundev);
break;
case NM_VPN_CONNECTION_STATE_FAILED:
case NM_VPN_CONNECTION_STATE_DISCONNECTED:
@@ -163,7 +167,7 @@
nm_utils_call_dispatcher ("vpn-down",
priv->connection,
priv->parent_dev,
- priv->tapdev ? priv->tapdev : priv->tundev);
+ priv->tundev);
}
break;
default:
@@ -193,6 +197,24 @@
}
}
+static void
+device_ip4_config_changed (NMDevice *device,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ NMVPNConnection *vpn = NM_VPN_CONNECTION (user_data);
+ NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (vpn);
+
+ if (priv->vpn_state != NM_VPN_CONNECTION_STATE_ACTIVATED)
+ return;
+
+ if (priv->gw_route)
+ rtnl_route_put (priv->gw_route);
+
+ /* Re-add the VPN gateway route */
+ priv->gw_route = nm_system_add_ip4_vpn_gateway_route (priv->parent_dev, priv->ip4_config);
+}
+
NMVPNConnection *
nm_vpn_connection_new (NMConnection *connection,
NMActRequest *act_request,
@@ -218,6 +240,10 @@
priv->device_monitor = g_signal_connect (parent_device, "state-changed",
G_CALLBACK (device_state_changed),
vpn_connection);
+
+ priv->device_ip4 = g_signal_connect (parent_device, "notify::" NM_DEVICE_INTERFACE_IP4_CONFIG,
+ G_CALLBACK (device_ip4_config_changed),
+ vpn_connection);
return vpn_connection;
}
@@ -470,9 +496,12 @@
nm_system_device_set_up_down_with_iface (priv->tundev, TRUE, NULL);
- if (nm_system_apply_ip4_config (priv->parent_dev, priv->tundev, config, 0, TRUE)) {
+ if (nm_system_apply_ip4_config (priv->tundev, config, 0, NM_IP4_COMPARE_FLAG_ALL)) {
NMNamedManager *named_mgr;
+ /* Add any explicit route to the VPN gateway through the parent device */
+ priv->gw_route = nm_system_add_ip4_vpn_gateway_route (priv->parent_dev, config);
+
/* Add the VPN to DNS */
named_mgr = nm_named_manager_get ();
nm_named_manager_add_ip4_config (named_mgr, priv->tundev, config, NM_NAMED_IP_CONFIG_TYPE_VPN);
@@ -890,6 +919,58 @@
}
static void
+vpn_cleanup (NMVPNConnection *connection)
+{
+ NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection);
+
+ if (priv->tundev) {
+ nm_system_device_set_up_down_with_iface (priv->tundev, FALSE, NULL);
+ nm_system_device_flush_ip4_routes_with_iface (priv->tundev);
+ nm_system_device_flush_ip4_addresses_with_iface (priv->tundev);
+ }
+
+ if (priv->ip4_config) {
+ NMIP4Config *parent_config;
+ NMNamedManager *named_mgr;
+
+ /* Remove attributes of the VPN's IP4 Config */
+ named_mgr = nm_named_manager_get ();
+ nm_named_manager_remove_ip4_config (named_mgr, priv->tundev, priv->ip4_config);
+ g_object_unref (named_mgr);
+
+ /* Remove any previously added VPN gateway host route */
+ if (priv->gw_route)
+ rtnl_route_del (nm_netlink_get_default_handle (), priv->gw_route, 0);
+
+ /* Reset routes and addresses of the currently active device */
+ parent_config = nm_device_get_ip4_config (priv->parent_dev);
+ if (parent_config) {
+ if (!nm_system_apply_ip4_config (nm_device_get_ip_iface (priv->parent_dev),
+ nm_device_get_ip4_config (priv->parent_dev),
+ nm_device_get_priority (priv->parent_dev),
+ NM_IP4_COMPARE_FLAG_ADDRESSES | NM_IP4_COMPARE_FLAG_ROUTES)) {
+ nm_warning ("%s: failed to re-apply VPN parent device addresses and routes.", __func__);
+ }
+ }
+ }
+
+ if (priv->gw_route) {
+ rtnl_route_put (priv->gw_route);
+ priv->gw_route = NULL;
+ }
+
+ if (priv->banner) {
+ g_free (priv->banner);
+ priv->banner = NULL;
+ }
+
+ if (priv->tundev) {
+ g_free (priv->tundev);
+ priv->tundev = NULL;
+ }
+}
+
+static void
connection_state_changed (NMVPNConnection *connection,
NMVPNConnectionState state,
NMVPNConnectionStateReason reason)
@@ -916,41 +997,7 @@
g_object_unref (priv->proxy);
priv->proxy = NULL;
}
-
- if (priv->tundev) {
- nm_system_device_set_up_down_with_iface (priv->tundev, FALSE, NULL);
- nm_system_device_flush_ip4_routes_with_iface (priv->tundev);
- nm_system_device_flush_ip4_addresses_with_iface (priv->tundev);
- }
-
- if (priv->ip4_config) {
- NMIP4Config *dev_ip4_config;
- NMNamedManager *named_mgr;
-
- /* Remove attributes of the VPN's IP4 Config */
- named_mgr = nm_named_manager_get ();
- nm_named_manager_remove_ip4_config (named_mgr, priv->tundev, priv->ip4_config);
- g_object_unref (named_mgr);
-
- /* Reset routes, nameservers, and domains of the currently active device */
- dev_ip4_config = nm_device_get_ip4_config (priv->parent_dev);
- if (dev_ip4_config) {
- NMDeviceStateReason dev_reason = NM_DEVICE_STATE_REASON_NONE;
-
- /* Since the config we're setting is also the device's current
- * config, have to ref the config to ensure it doesn't get
- * destroyed when the device unrefs it in nm_device_set_ip4_config().
- */
- nm_device_set_ip4_config (priv->parent_dev,
- g_object_ref (dev_ip4_config),
- &dev_reason);
- }
- }
-
- if (priv->banner) {
- g_free (priv->banner);
- priv->banner = NULL;
- }
+ vpn_cleanup (connection);
break;
default:
break;
@@ -987,7 +1034,13 @@
cleanup_secrets_dbus_call (NM_VPN_CONNECTION (object));
+ if (priv->gw_route)
+ rtnl_route_put (priv->gw_route);
+
if (priv->parent_dev) {
+ if (priv->device_ip4)
+ g_signal_handler_disconnect (priv->parent_dev, priv->device_ip4);
+
if (priv->device_monitor)
g_signal_handler_disconnect (priv->parent_dev, priv->device_monitor);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]