summaryrefslogtreecommitdiff
path: root/src/NetworkManagerSystem.c
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2008-10-10 23:05:45 +0000
committerDan Williams <dcbw@redhat.com>2008-10-10 23:05:45 +0000
commitad7a46d8676bd01b8294900ef1aaebcaa92a9015 (patch)
tree0e98beabad163749eb8f0a4e567960e64a44b43c /src/NetworkManagerSystem.c
parent9b82c1e92f5c1a03238d57069f66bddcdfdfc81d (diff)
2008-10-10 Dan Williams <dcbw@redhat.com>
Rework default route handling to consolidate decisions in the policy, and to take active VPN connections into account when changing the default route (bgo #545912) * src/NetworkManager.c - (main): pass the vpn_manager to the policy so it knows about active VPN connections; clean up the named manager which wasn't done before * src/NetworkManagerPolicy.c src/NetworkManagerPolicy.h - (nm_policy_new): get a clue about the vpn_manager - (update_default_route): remove, fold into update_routing_and_dns() - (update_routing_and_dns): handle active VPN connections too; an active VPN connection becomes the default route if it does not have server-specified or user-specified custom routes. Otherwise, the best active device gets the default route - (vpn_connection_activated, vpn_connection_deactivated, nm_policy_new, nm_policy_destroy): track VPN connection activation and deactivation and update the default route when appropriate * src/NetworkManagerSystem.c src/NetworkManagerSystem.h - (nm_system_vpn_device_unset_from_ip4_config): remove, put functionality in the VPN connection itself - (nm_system_vpn_device_set_from_ip4_config, nm_system_device_set_from_ip4_config): merge together to make nm_system_apply_ip4_config() - (add_vpn_gateway_route): add a route to the VPN's external gateway via the parent device - (nm_system_apply_ip4_config): simplify - (add_ip4_route_to_gateway): new function; add a direct route to the gateway if needed - (nm_system_device_replace_default_ip4_route): simplify, break gateway route stuff out into add_ip4_route_to_gateway() for clarity * src/nm-device.c - (nm_device_set_ip4_config): update for nm_system_apply_ip4_config() * src/vpn-manager/nm-vpn-connection.c src/vpn-manager/nm-vpn-connection.h - (nm_vpn_connection_get_ip4_config, nm_vpn_connection_get_ip_iface, nm_vpn_connection_get_parent_device): add - (nm_vpn_connection_ip4_config_get): make the requirement of a tunnel device explicit - (connection_state_changed): update the named manager now that nm_system_vpn_device_unset_from_ip4_config() is gone; do something useful on errors * src/vpn-manager/nm-vpn-manager.c src/vpn-manager/nm-vpn-manager.h - Add a 'connection-activated' signal - (nm_vpn_manager_get_active_connections): new function; mainly for the policy to find out about active VPN connections git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@4167 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
Diffstat (limited to 'src/NetworkManagerSystem.c')
-rw-r--r--src/NetworkManagerSystem.c284
1 files changed, 130 insertions, 154 deletions
diff --git a/src/NetworkManagerSystem.c b/src/NetworkManagerSystem.c
index 8f836d98a2..653e90a712 100644
--- a/src/NetworkManagerSystem.c
+++ b/src/NetworkManagerSystem.c
@@ -273,114 +273,75 @@ add_ip4_addresses (NMIP4Config *config, const char *iface)
return TRUE;
}
-/*
- * nm_system_device_set_from_ip4_config
- *
- * Set IPv4 configuration of the device from an NMIP4Config object.
- *
- */
-gboolean
-nm_system_device_set_from_ip4_config (const char *iface,
- NMIP4Config *config,
- int priority)
+static void
+add_vpn_gateway_route (NMDevice *device, const char *iface, NMIP4Config *config)
{
- int len, i;
+ NMIP4Config *ad_config;
+ guint32 ad_gw = 0, vpn_gw = 0, i;
+ const NMSettingIP4Address *tmp;
- g_return_val_if_fail (iface != NULL, FALSE);
- g_return_val_if_fail (config != NULL, FALSE);
+ g_return_if_fail (NM_IS_DEVICE (device));
- if (!add_ip4_addresses (config, iface))
- return FALSE;
-
- sleep (1);
+ ad_config = nm_device_get_ip4_config (device);
+ g_return_if_fail (ad_config != NULL);
- len = nm_ip4_config_get_num_routes (config);
- for (i = 0; i < len; i++) {
- const NMSettingIP4Route *route = nm_ip4_config_get_route (config, i);
-
- nm_system_device_set_ip4_route (iface, config,
- route->address,
- route->prefix,
- route->next_hop,
- route->metric,
- nm_ip4_config_get_mss (config));
+ /* Set up a route to the VPN gateway's public IP address through the default
+ * network device.
+ */
+ for (i = 0; i < nm_ip4_config_get_num_addresses (ad_config); i++) {
+ tmp = nm_ip4_config_get_address (ad_config, i);
+ if (tmp->gateway) {
+ ad_gw = tmp->gateway;
+ break;
+ }
}
- if (nm_ip4_config_get_mtu (config))
- nm_system_device_set_mtu (iface, nm_ip4_config_get_mtu (config));
+ if (!ad_gw)
+ return;
- if (priority > 0)
- nm_system_device_set_priority (iface, config, priority);
+ 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;
+ }
+ }
- return TRUE;
+ nm_system_device_set_ip4_route (nm_device_get_ip_iface (device),
+ ad_config, vpn_gw, 32, ad_gw, 0,
+ nm_ip4_config_get_mss (ad_config));
}
/*
- * nm_system_vpn_device_set_from_ip4_config
+ * nm_system_apply_ip4_config
*
- * Set IPv4 configuration of a VPN device from an NMIP4Config object.
+ * Set IPv4 configuration of the device from an NMIP4Config object.
*
*/
gboolean
-nm_system_vpn_device_set_from_ip4_config (NMDevice *active_device,
- const char *iface,
- NMIP4Config *config)
+nm_system_apply_ip4_config (NMDevice *device,
+ const char *iface,
+ NMIP4Config *config,
+ int priority,
+ gboolean is_vpn)
{
- NMIP4Config *ad_config = NULL;
- NMNamedManager *named_mgr;
- int num;
int i;
+ g_return_val_if_fail (iface != NULL, FALSE);
g_return_val_if_fail (config != NULL, FALSE);
- /* Set up a route to the VPN gateway through the real network device */
- if (active_device && (ad_config = nm_device_get_ip4_config (active_device))) {
- guint32 ad_gw = 0, vpn_gw = 0;
- const NMSettingIP4Address *tmp;
-
- 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;
- 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, vpn_gw, 32, ad_gw, 0,
- nm_ip4_config_get_mss (config));
- }
- }
-
- if (!iface || !strlen (iface))
- goto out;
-
- nm_system_device_set_up_down_with_iface (iface, TRUE, NULL);
-
if (!add_ip4_addresses (config, iface))
- goto out;
+ return FALSE;
- /* Set the MTU */
- if (nm_ip4_config_get_mtu (config))
- nm_system_device_set_mtu (iface, nm_ip4_config_get_mtu (config));
+ if (is_vpn)
+ add_vpn_gateway_route (device, iface, config);
- /* Set routes */
- num = nm_ip4_config_get_num_routes (config);
- for (i = 0; i < num; i++) {
+ sleep (1);
+
+ for (i = 0; i < nm_ip4_config_get_num_routes (config); i++) {
const NMSettingIP4Route *route = nm_ip4_config_get_route (config, i);
- nm_system_device_set_ip4_route (iface, config,
+ nm_system_device_set_ip4_route (iface, config,
route->address,
route->prefix,
route->next_hop,
@@ -388,39 +349,15 @@ nm_system_vpn_device_set_from_ip4_config (NMDevice *active_device,
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, iface, config, NM_NAMED_IP_CONFIG_TYPE_VPN);
- g_object_unref (named_mgr);
-
- return TRUE;
-}
-
-
-/*
- * nm_system_vpn_device_unset_from_ip4_config
- *
- * Unset an IPv4 configuration of a VPN device from an NMIP4Config object.
- *
- */
-gboolean nm_system_vpn_device_unset_from_ip4_config (NMDevice *active_device, const char *iface, NMIP4Config *config)
-{
- NMNamedManager *named_mgr;
-
- g_return_val_if_fail (active_device != NULL, FALSE);
- g_return_val_if_fail (config != NULL, FALSE);
+ if (nm_ip4_config_get_mtu (config))
+ nm_system_device_set_mtu (iface, nm_ip4_config_get_mtu (config));
- named_mgr = nm_named_manager_get ();
- nm_named_manager_remove_ip4_config (named_mgr, iface, config);
- g_object_unref (named_mgr);
+ if (priority > 0)
+ nm_system_device_set_priority (iface, config, priority);
return TRUE;
}
-
/*
* nm_system_device_set_up_down
*
@@ -547,6 +484,55 @@ nm_system_device_set_mtu (const char *iface, guint32 mtu)
return success;
}
+static struct rtnl_route *
+add_ip4_route_to_gateway (const char *iface, guint32 gw, guint32 mss)
+{
+ struct nl_handle *nlh;
+ struct rtnl_route *route = NULL;
+ struct nl_addr *gw_addr = NULL;
+ int iface_idx, err;
+
+ nlh = nm_netlink_get_default_handle ();
+ g_return_val_if_fail (nlh != NULL, NULL);
+
+ iface_idx = nm_netlink_iface_to_index (iface);
+ if (iface_idx < 0)
+ return NULL;
+
+ /* Gateway might be over a bridge; try adding a route to gateway first */
+ route = rtnl_route_alloc ();
+ if (route == NULL)
+ return NULL;
+
+ rtnl_route_set_oif (route, iface_idx);
+ rtnl_route_set_scope (route, RT_SCOPE_UNIVERSE);
+
+ gw_addr = nl_addr_build (AF_INET, &gw, sizeof (gw));
+ if (!gw_addr)
+ goto error;
+ rtnl_route_set_dst (route, gw_addr);
+ nl_addr_put (gw_addr);
+
+ if (mss) {
+ if (rtnl_route_set_metric (route, RTAX_ADVMSS, mss) < 0)
+ goto error;
+ }
+
+ /* Add direct route to the gateway */
+ err = rtnl_route_add (nlh, route, 0);
+ if (err) {
+ nm_warning ("Failed to add IPv4 default route on '%s': (%d) %s",
+ iface, err, nl_geterror ());
+ goto error;
+ }
+
+ return route;
+
+error:
+ rtnl_route_put (route);
+ return NULL;
+}
+
/*
* nm_system_replace_default_ip4_route
*
@@ -554,32 +540,35 @@ nm_system_device_set_mtu (const char *iface, guint32 mtu)
*
*/
void
-nm_system_device_replace_default_ip4_route (const char *iface, guint32 gw, guint32 mss)
+nm_system_device_replace_default_ip4_route (const char *iface,
+ guint32 gw,
+ guint32 mss,
+ const char *parent_iface,
+ guint32 parent_mss)
{
- struct rtnl_route * route;
- struct rtnl_route * route2 = NULL;
- struct nl_handle * nlh;
- struct nl_addr * gw_addr;
+ 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;
nlh = nm_netlink_get_default_handle ();
g_return_if_fail (nlh != NULL);
+ iface_idx = nm_netlink_iface_to_index (iface);
+ if (iface_idx < 0)
+ return;
+
route = rtnl_route_alloc();
g_return_if_fail (route != NULL);
rtnl_route_set_scope (route, RT_SCOPE_UNIVERSE);
-
- iface_idx = nm_netlink_iface_to_index (iface);
- if (iface_idx < 0)
- goto out;
rtnl_route_set_oif (route, iface_idx);
- /* Build up gateway address; a gateway of 0 (used in e.g. PPP links) means
- * that all packets should be sent to the gateway since it's a point-to-point
- * link and has no broadcast segment really.
- */
- if (!(gw_addr = nl_addr_build (AF_INET, &gw, sizeof (gw))))
+ /* Build up the gateway address */
+ gw_addr = nl_addr_build (AF_INET, &gw, sizeof (gw));
+ if (!gw_addr)
goto out;
rtnl_route_set_gateway (route, gw_addr);
nl_addr_put (gw_addr);
@@ -589,9 +578,11 @@ nm_system_device_replace_default_ip4_route (const char *iface, guint32 gw, guint
goto out;
}
+ /* 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",
@@ -599,41 +590,26 @@ nm_system_device_replace_default_ip4_route (const char *iface, guint32 gw, guint
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 (mss) {
- if (rtnl_route_set_metric (route2, RTAX_ADVMSS, mss) < 0)
- goto out;
- }
-
- /* 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 ());
+ /* 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);
+ if (!gw_route)
goto out;
- }
- /* Try adding the route again */
- err = rtnl_route_add (nlh, route, 0);
- if (err) {
- rtnl_route_del (nlh, route2, 0);
- nm_warning ("Failed to set IPv4 default route on '%s': %s",
- iface,
- nl_geterror ());
+ /* Try adding the original route again */
+ err = rtnl_route_add (nlh, route, NLM_F_REPLACE);
+ if (err != 0) {
+ rtnl_route_del (nlh, gw_route, 0);
+ nm_warning ("Failed to set IPv4 default route on '%s': %s", iface, nl_geterror ());
}
out:
- if (route2)
- rtnl_route_put (route2);
+ if (gw_route)
+ rtnl_route_put (gw_route);
- rtnl_route_put (route);
+ if (route)
+ rtnl_route_put (route);
}
/*