diff options
author | Dan Williams <dcbw@redhat.com> | 2008-10-10 23:05:45 +0000 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2008-10-10 23:05:45 +0000 |
commit | ad7a46d8676bd01b8294900ef1aaebcaa92a9015 (patch) | |
tree | 0e98beabad163749eb8f0a4e567960e64a44b43c /src/NetworkManagerSystem.c | |
parent | 9b82c1e92f5c1a03238d57069f66bddcdfdfc81d (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.c | 284 |
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); } /* |