diff options
Diffstat (limited to 'src/nm-policy.c')
-rw-r--r-- | src/nm-policy.c | 451 |
1 files changed, 36 insertions, 415 deletions
diff --git a/src/nm-policy.c b/src/nm-policy.c index e21df28a9c..963be3099b 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -32,6 +32,7 @@ #include "nm-activation-request.h" #include "nm-logging.h" #include "nm-device.h" +#include "nm-default-route-manager.h" #include "nm-dbus-manager.h" #include "nm-setting-ip4-config.h" #include "nm-setting-connection.h" @@ -100,164 +101,22 @@ static NMDevice * get_best_ip4_device (NMPolicy *self, gboolean fully_activated) { NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); - const GSList *iter; - NMDevice *best = NULL; - int best_prio = G_MAXINT; - - for (iter = nm_manager_get_devices (priv->manager); iter; iter = g_slist_next (iter)) { - NMDevice *dev = NM_DEVICE (iter->data); - NMDeviceType devtype = nm_device_get_device_type (dev); - NMDeviceState state = nm_device_get_state (dev); - NMActRequest *req; - NMConnection *connection; - NMSettingIP4Config *s_ip4; - int prio; - const char *method = NULL; - - if ( state <= NM_DEVICE_STATE_DISCONNECTED - || state >= NM_DEVICE_STATE_DEACTIVATING) - continue; - - if (fully_activated && state < NM_DEVICE_STATE_SECONDARIES) - continue; - - if (fully_activated) { - NMIP4Config *ip4_config; - - ip4_config = nm_device_get_ip4_config (dev); - if (!ip4_config) - continue; - - /* Make sure the device has a gateway */ - if (!nm_ip4_config_get_gateway (ip4_config) && (devtype != NM_DEVICE_TYPE_MODEM)) - continue; - - /* 'never-default' devices can't ever be the default */ - if (nm_ip4_config_get_never_default (ip4_config)) - continue; - } - req = nm_device_get_act_request (dev); - g_assert (req); - connection = nm_act_request_get_connection (req); - g_assert (connection); - - method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG); - /* If IPv4 is disabled or link-local-only, it can't be the default */ - if ( !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) - || !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) - continue; - - /* 'never-default' devices can't ever be the default */ - s_ip4 = nm_connection_get_setting_ip4_config (connection); - g_assert (s_ip4); - if (nm_setting_ip4_config_get_never_default (s_ip4)) - continue; - - prio = nm_device_get_priority (dev); - if ( prio < best_prio - || (priv->default_device4 == dev && prio == best_prio) - || !best) { - best = dev; - best_prio = prio; - } - } - - if (!best) - return NULL; - - if (!fully_activated) { - NMDeviceState state = nm_device_get_state (best); - - /* There's only a best activating device if the best device - * among all activating and already-activated devices is a - * still-activating one. - */ - if (state >= NM_DEVICE_STATE_SECONDARIES) - return NULL; - } - - return best; + return nm_default_route_manager_ip4_get_best_device (nm_default_route_manager_get (), + nm_manager_get_devices (priv->manager), + fully_activated, + priv->default_device4); } static NMDevice * get_best_ip6_device (NMPolicy *self, gboolean fully_activated) { NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); - const GSList *iter; - NMDevice *best = NULL; - int best_prio = G_MAXINT; - for (iter = nm_manager_get_devices (priv->manager); iter; iter = g_slist_next (iter)) { - NMDevice *dev = NM_DEVICE (iter->data); - NMDeviceType devtype = nm_device_get_device_type (dev); - NMDeviceState state = nm_device_get_state (dev); - NMActRequest *req; - NMConnection *connection; - NMSettingIP6Config *s_ip6; - int prio; - const char *method = NULL; - - if ( state <= NM_DEVICE_STATE_DISCONNECTED - || state >= NM_DEVICE_STATE_DEACTIVATING) - continue; - - if (fully_activated && state < NM_DEVICE_STATE_SECONDARIES) - continue; - - if (fully_activated) { - NMIP6Config *ip6_config; - - ip6_config = nm_device_get_ip6_config (dev); - if (!ip6_config) - continue; - - if (!nm_ip6_config_get_gateway (ip6_config) && (devtype != NM_DEVICE_TYPE_MODEM)) - continue; - - if (nm_ip6_config_get_never_default (ip6_config)) - continue; - } - - req = nm_device_get_act_request (dev); - g_assert (req); - connection = nm_act_request_get_connection (req); - g_assert (connection); - - method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG); - if ( !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) - || !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)) - continue; - - s_ip6 = nm_connection_get_setting_ip6_config (connection); - g_assert (s_ip6); - if (nm_setting_ip6_config_get_never_default (s_ip6)) - continue; - - prio = nm_device_get_priority (dev); - if ( prio < best_prio - || (priv->default_device6 == dev && prio == best_prio) - || !best) { - best = dev; - best_prio = prio; - } - } - - if (!best) - return NULL; - - if (!fully_activated) { - NMDeviceState state = nm_device_get_state (best); - - /* There's only a best activating device if the best device - * among all activating and already-activated devices is an - * activating one. - */ - if (state >= NM_DEVICE_STATE_SECONDARIES) - return NULL; - } - - return best; + return nm_default_route_manager_ip6_get_best_device (nm_default_route_manager_get (), + nm_manager_get_devices (priv->manager), + fully_activated, + priv->default_device6); } #define FALLBACK_HOSTNAME4 "localhost.localdomain" @@ -473,12 +332,14 @@ update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6) const NMPlatformIP4Address *addr4; addr4 = nm_ip4_config_get_address (ip4_config, 0); + g_clear_object (&priv->lookup_addr); priv->lookup_addr = g_inet_address_new_from_bytes ((guint8 *) &addr4->address, G_SOCKET_FAMILY_IPV4); } else if (ip6_config && nm_ip6_config_get_num_addresses (ip6_config) > 0) { const NMPlatformIP6Address *addr6; addr6 = nm_ip6_config_get_address (ip6_config, 0); + g_clear_object (&priv->lookup_addr); priv->lookup_addr = g_inet_address_new_from_bytes ((guint8 *) &addr6->address, G_SOCKET_FAMILY_IPV6); } else { @@ -518,90 +379,19 @@ update_default_ac (NMPolicy *policy, } static NMIP4Config * -get_best_ip4_config (NMPolicy *policy, +get_best_ip4_config (NMPolicy *self, gboolean ignore_never_default, const char **out_ip_iface, - int *out_ip_ifindex, NMActiveConnection **out_ac, NMDevice **out_device, NMVpnConnection **out_vpn) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); - const GSList *connections, *iter; - NMDevice *device; - NMActRequest *req = NULL; - NMIP4Config *ip4_config = NULL; - - /* If a VPN connection is active, it is preferred */ - connections = nm_manager_get_active_connections (priv->manager); - for (iter = connections; iter; iter = g_slist_next (iter)) { - NMActiveConnection *active = NM_ACTIVE_CONNECTION (iter->data); - NMVpnConnection *candidate; - NMIP4Config *vpn_ip4; - NMConnection *tmp; - NMSettingIP4Config *s_ip4; - NMVpnConnectionState vpn_state; - - if (!NM_IS_VPN_CONNECTION (active)) - continue; - - candidate = NM_VPN_CONNECTION (active); - - tmp = nm_active_connection_get_connection (active); - g_assert (tmp); - - vpn_state = nm_vpn_connection_get_vpn_state (candidate); - if (vpn_state != NM_VPN_CONNECTION_STATE_ACTIVATED) - continue; - - vpn_ip4 = nm_vpn_connection_get_ip4_config (candidate); - if (!vpn_ip4) - continue; - - if (ignore_never_default == FALSE) { - /* Check for a VPN-provided config never-default */ - if (nm_ip4_config_get_never_default (vpn_ip4)) - continue; - - /* Check the user's preference from the NMConnection */ - s_ip4 = nm_connection_get_setting_ip4_config (tmp); - if (nm_setting_ip4_config_get_never_default (s_ip4)) - continue; - } - - ip4_config = vpn_ip4; - if (out_vpn) - *out_vpn = candidate; - if (out_ac) - *out_ac = active; - if (out_ip_iface) - *out_ip_iface = nm_vpn_connection_get_ip_iface (candidate); - if (out_ip_ifindex) - *out_ip_ifindex = nm_vpn_connection_get_ip_ifindex (candidate); - break; - } - - /* If no VPN connections, we use the best device instead */ - if (!ip4_config) { - device = get_best_ip4_device (policy, TRUE); - if (device) { - ip4_config = nm_device_get_ip4_config (device); - g_assert (ip4_config); - req = nm_device_get_act_request (device); - g_assert (req); - - if (out_device) - *out_device = device; - if (out_ac) - *out_ac = NM_ACTIVE_CONNECTION (req); - if (out_ip_iface) - *out_ip_iface = nm_device_get_ip_iface (device); - if (out_ip_ifindex) - *out_ip_ifindex = nm_device_get_ip_ifindex (device); - } - } - - return ip4_config; + return nm_default_route_manager_ip4_get_best_config (nm_default_route_manager_get (), + ignore_never_default, + out_ip_iface, + out_ac, + out_device, + out_vpn); } static void @@ -612,7 +402,7 @@ update_ip4_dns (NMPolicy *policy, NMDnsManager *dns_mgr) NMVpnConnection *vpn = NULL; NMDnsIPConfigType dns_type = NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE; - ip4_config = get_best_ip4_config (policy, TRUE, &ip_iface, NULL, NULL, NULL, &vpn); + ip4_config = get_best_ip4_config (policy, TRUE, &ip_iface, NULL, NULL, &vpn); if (ip4_config) { if (vpn) dns_type = NM_DNS_IP_CONFIG_TYPE_VPN; @@ -632,16 +422,12 @@ update_ip4_routing (NMPolicy *policy, gboolean force_update) NMConnection *connection = NULL; NMVpnConnection *vpn = NULL; NMActiveConnection *best_ac = NULL; - NMIP4Config *ip4_config = NULL; const char *ip_iface = NULL; - int ip_ifindex = -1; - guint32 gw_addr = 0; /* Note that we might have an IPv4 VPN tunneled over an IPv6-only device, * so we can get (vpn != NULL && best == NULL). */ - ip4_config = get_best_ip4_config (policy, FALSE, &ip_iface, &ip_ifindex, &best_ac, &best, &vpn); - if (!ip4_config) { + if (!get_best_ip4_config (policy, FALSE, &ip_iface, &best_ac, &best, &vpn)) { gboolean changed; changed = (priv->default_device4 != NULL); @@ -656,8 +442,6 @@ update_ip4_routing (NMPolicy *policy, gboolean force_update) if (!force_update && best && (best == priv->default_device4)) return; - gw_addr = nm_ip4_config_get_gateway (ip4_config); - if (best) { const GSList *connections, *iter; @@ -672,50 +456,10 @@ update_ip4_routing (NMPolicy *policy, gboolean force_update) } } - if (vpn) { - NMDevice *parent = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (vpn)); - int parent_ifindex = nm_device_get_ip_ifindex (parent); - NMIP4Config *parent_ip4 = nm_device_get_ip4_config (parent); - guint32 parent_mss = parent_ip4 ? nm_ip4_config_get_mss (parent_ip4) : 0; - in_addr_t int_gw = nm_vpn_connection_get_ip4_internal_gateway (vpn); - int mss = nm_ip4_config_get_mss (ip4_config); - - /* If no VPN interface, use the parent interface */ - if (ip_ifindex <= 0) - ip_ifindex = parent_ifindex; - - if (!nm_platform_ip4_route_add (ip_ifindex, NM_IP_CONFIG_SOURCE_VPN, - 0, 0, int_gw, - NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) { - (void) nm_platform_ip4_route_add (parent_ifindex, NM_IP_CONFIG_SOURCE_VPN, - gw_addr, 32, 0, - NM_PLATFORM_ROUTE_METRIC_DEFAULT, parent_mss); - if (!nm_platform_ip4_route_add (ip_ifindex, NM_IP_CONFIG_SOURCE_VPN, - 0, 0, int_gw, - NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) - nm_log_err (LOGD_IP4 | LOGD_VPN, "Failed to set default route."); - } - + if (vpn) default_device = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (vpn)); - } else { - int mss = nm_ip4_config_get_mss (ip4_config); - - g_assert (ip_iface); - if (!nm_platform_ip4_route_add (ip_ifindex, NM_IP_CONFIG_SOURCE_USER, - 0, 0, gw_addr, - NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) { - (void) nm_platform_ip4_route_add (ip_ifindex, NM_IP_CONFIG_SOURCE_USER, - gw_addr, 32, 0, - NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss); - if (!nm_platform_ip4_route_add (ip_ifindex, NM_IP_CONFIG_SOURCE_USER, - 0, 0, gw_addr, - NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) { - nm_log_err (LOGD_IP4, "Failed to set default route."); - } - } - + else default_device = best; - } update_default_ac (policy, best_ac, nm_active_connection_set_default); @@ -730,90 +474,19 @@ update_ip4_routing (NMPolicy *policy, gboolean force_update) } static NMIP6Config * -get_best_ip6_config (NMPolicy *policy, +get_best_ip6_config (NMPolicy *self, gboolean ignore_never_default, const char **out_ip_iface, - int *out_ip_ifindex, NMActiveConnection **out_ac, NMDevice **out_device, NMVpnConnection **out_vpn) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); - const GSList *connections, *iter; - NMDevice *device; - NMActRequest *req = NULL; - NMIP6Config *ip6_config = NULL; - - /* If a VPN connection is active, it is preferred */ - connections = nm_manager_get_active_connections (priv->manager); - for (iter = connections; iter; iter = g_slist_next (iter)) { - NMActiveConnection *active = NM_ACTIVE_CONNECTION (iter->data); - NMVpnConnection *candidate; - NMIP6Config *vpn_ip6; - NMConnection *tmp; - NMSettingIP6Config *s_ip6; - NMVpnConnectionState vpn_state; - - if (!NM_IS_VPN_CONNECTION (active)) - continue; - - candidate = NM_VPN_CONNECTION (active); - - tmp = nm_active_connection_get_connection (active); - g_assert (tmp); - - vpn_state = nm_vpn_connection_get_vpn_state (candidate); - if (vpn_state != NM_VPN_CONNECTION_STATE_ACTIVATED) - continue; - - vpn_ip6 = nm_vpn_connection_get_ip6_config (candidate); - if (!vpn_ip6) - continue; - - if (ignore_never_default == FALSE) { - /* Check for a VPN-provided config never-default */ - if (nm_ip6_config_get_never_default (vpn_ip6)) - continue; - - /* Check the user's preference from the NMConnection */ - s_ip6 = nm_connection_get_setting_ip6_config (tmp); - if (nm_setting_ip6_config_get_never_default (s_ip6)) - continue; - } - - ip6_config = vpn_ip6; - if (out_vpn) - *out_vpn = candidate; - if (out_ac) - *out_ac = NM_ACTIVE_CONNECTION (candidate); - if (out_ip_iface) - *out_ip_iface = nm_vpn_connection_get_ip_iface (candidate); - if (out_ip_ifindex) - *out_ip_ifindex = nm_vpn_connection_get_ip_ifindex (candidate); - break; - } - - /* If no VPN connections, we use the best device instead */ - if (!ip6_config) { - device = get_best_ip6_device (policy, TRUE); - if (device) { - req = nm_device_get_act_request (device); - g_assert (req); - ip6_config = nm_device_get_ip6_config (device); - g_assert (ip6_config); - - if (out_device) - *out_device = device; - if (out_ac) - *out_ac = NM_ACTIVE_CONNECTION (req); - if (out_ip_iface) - *out_ip_iface = nm_device_get_ip_iface (device); - if (out_ip_ifindex) - *out_ip_ifindex = nm_device_get_ip_ifindex (device); - } - } - - return ip6_config; + return nm_default_route_manager_ip6_get_best_config (nm_default_route_manager_get (), + ignore_never_default, + out_ip_iface, + out_ac, + out_device, + out_vpn); } static void @@ -824,7 +497,7 @@ update_ip6_dns (NMPolicy *policy, NMDnsManager *dns_mgr) NMVpnConnection *vpn = NULL; NMDnsIPConfigType dns_type = NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE; - ip6_config = get_best_ip6_config (policy, TRUE, &ip_iface, NULL, NULL, NULL, &vpn); + ip6_config = get_best_ip6_config (policy, TRUE, &ip_iface, NULL, NULL, &vpn); if (ip6_config) { if (vpn) dns_type = NM_DNS_IP_CONFIG_TYPE_VPN; @@ -844,16 +517,12 @@ update_ip6_routing (NMPolicy *policy, gboolean force_update) NMConnection *connection = NULL; NMVpnConnection *vpn = NULL; NMActiveConnection *best_ac = NULL; - NMIP6Config *ip6_config = NULL; const char *ip_iface = NULL; - int ip_ifindex = -1; - const struct in6_addr *gw_addr; /* Note that we might have an IPv6 VPN tunneled over an IPv4-only device, * so we can get (vpn != NULL && best == NULL). */ - ip6_config = get_best_ip6_config (policy, FALSE, &ip_iface, &ip_ifindex, &best_ac, &best, &vpn); - if (!ip6_config) { + if (!get_best_ip6_config (policy, FALSE, &ip_iface, &best_ac, &best, &vpn)) { gboolean changed; changed = (priv->default_device6 != NULL); @@ -868,13 +537,6 @@ update_ip6_routing (NMPolicy *policy, gboolean force_update) if (!force_update && best && (best == priv->default_device6)) return; - /* If no better gateway is found, use ::; not all configurations will - * have a gateway, especially WWAN/Point-to-Point connections. - */ - gw_addr = nm_ip6_config_get_gateway (ip6_config); - if (!gw_addr) - gw_addr = &in6addr_any; - if (best) { const GSList *connections, *iter; @@ -889,52 +551,10 @@ update_ip6_routing (NMPolicy *policy, gboolean force_update) } } - if (vpn) { - NMDevice *parent = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (vpn)); - int parent_ifindex = nm_device_get_ip_ifindex (parent); - NMIP6Config *parent_ip6 = nm_device_get_ip6_config (parent); - guint32 parent_mss = parent_ip6 ? nm_ip6_config_get_mss (parent_ip6) : 0; - const struct in6_addr *int_gw = nm_vpn_connection_get_ip6_internal_gateway (vpn); - int mss = nm_ip6_config_get_mss (ip6_config); - - if (!int_gw) - int_gw = &in6addr_any; - - /* If no VPN interface, use the parent interface */ - if (ip_ifindex <= 0) - ip_ifindex = parent_ifindex; - - if (!nm_platform_ip6_route_add (ip_ifindex, NM_IP_CONFIG_SOURCE_VPN, - in6addr_any, 0, *int_gw, - NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) { - (void) nm_platform_ip6_route_add (parent_ifindex, NM_IP_CONFIG_SOURCE_VPN, - *gw_addr, 128, in6addr_any, - NM_PLATFORM_ROUTE_METRIC_DEFAULT, parent_mss); - if (!nm_platform_ip6_route_add (ip_ifindex, NM_IP_CONFIG_SOURCE_VPN, - in6addr_any, 0, *int_gw, - NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) { - nm_log_err (LOGD_IP6 | LOGD_VPN, "Failed to set default route."); - } - } - + if (vpn) default_device6 = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (vpn)); - } else { - int mss = nm_ip6_config_get_mss (ip6_config); - - if (!nm_platform_ip6_route_add (ip_ifindex, NM_IP_CONFIG_SOURCE_USER, - in6addr_any, 0, *gw_addr, - NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) { - (void) nm_platform_ip6_route_add (ip_ifindex, NM_IP_CONFIG_SOURCE_USER, - *gw_addr, 128, in6addr_any, - NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss); - if (!nm_platform_ip6_route_add (ip_ifindex, NM_IP_CONFIG_SOURCE_USER, - in6addr_any, 0, *gw_addr, - NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) - nm_log_err (LOGD_IP6, "Failed to set default route."); - } - + else default_device6 = best; - } update_default_ac (policy, best_ac, nm_active_connection_set_default6); @@ -2015,9 +1635,10 @@ dns_config_changed (NMDnsManager *dns_manager, gpointer user_data) /* Re-start the hostname lookup thread if we don't have hostname yet. */ if (priv->lookup_addr) { - char *str = g_inet_address_to_string (priv->lookup_addr); + char *str = NULL; - nm_log_dbg (LOGD_DNS, "restarting reverse-lookup thread for address %s", str); + nm_log_dbg (LOGD_DNS, "restarting reverse-lookup thread for address %s", + (str = g_inet_address_to_string (priv->lookup_addr))); g_free (str); priv->lookup_cancellable = g_cancellable_new (); |