summaryrefslogtreecommitdiff
path: root/src/nm-policy.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nm-policy.c')
-rw-r--r--src/nm-policy.c451
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 ();