core: merge branch 'th/platform-route-pt4' (part 2)

Drop NMDefaultRouteManager.

https://github.com/NetworkManager/NetworkManager/pull/26
This commit is contained in:
Thomas Haller 2017-09-08 13:49:57 +02:00
commit 4bc231e33a
18 changed files with 722 additions and 2047 deletions

View file

@ -1494,8 +1494,6 @@ src_libNetworkManager_la_SOURCES = \
src/nm-dcb.h \
src/nm-netns.c \
src/nm-netns.h \
src/nm-default-route-manager.c \
src/nm-default-route-manager.h \
src/nm-dhcp4-config.c \
src/nm-dhcp4-config.h \
src/nm-dhcp6-config.c \

View file

@ -65,7 +65,6 @@
#include "nm-utils/c-list.h"
#include "dns/nm-dns-manager.h"
#include "nm-core-internal.h"
#include "nm-default-route-manager.h"
#include "systemd/nm-sd.h"
#include "nm-lldp-listener.h"
#include "nm-audit-manager.h"
@ -360,14 +359,12 @@ typedef struct _NMDevicePrivate {
NMIP4Config * ext_ip4_config; /* Stuff added outside NM */
NMIP4Config * wwan_ip4_config; /* WWAN configuration */
GSList * vpn4_configs; /* VPNs which use this device */
struct {
bool v4_has;
bool v4_is_assumed;
bool v6_has;
bool v6_is_assumed;
NMPlatformIP4Route v4;
NMPlatformIP6Route v6;
} default_route;
const NMPObject *default_route4;
const NMPObject *default_route6;
const NMPObject *default_routegw4;
const NMPObject *default_routegw6;
bool v4_has_shadowed_routes;
const char *ip4_rp_filter;
@ -1691,62 +1688,33 @@ out:
return nm_utils_ip_route_metric_normalize (addr_family, route_metric);
}
static void
_update_default_route (NMDevice *self, int addr_family, gboolean has, gboolean is_assumed)
const NMPObject *
nm_device_get_best_default_route (NMDevice *self,
int addr_family)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
bool *p_has, *p_is_assumed;
nm_assert (NM_IN_SET (addr_family, 0, AF_INET, AF_INET6));
if (addr_family == AF_INET) {
p_has = &priv->default_route.v4_has;
p_is_assumed = &priv->default_route.v4_is_assumed;
} else {
p_has = &priv->default_route.v6_has;
p_is_assumed = &priv->default_route.v6_is_assumed;
/* Prefer the best default-route we have in ipx_config.
*
* Otherwise, use priv->default_routeX. Usually, we would
* expect that if ipx_config has no default route, then
* also priv->default_routeX is unset. This is just to cover
* a case I cannot imagine now. */
switch (addr_family) {
case AF_INET:
return (priv->ip4_config ? nm_ip4_config_best_default_route_get (priv->ip4_config) : NULL)
?: priv->default_route4;
case AF_INET6:
return (priv->ip6_config ? nm_ip6_config_best_default_route_get (priv->ip6_config) : NULL)
?: priv->default_route6;
case AF_UNSPEC:
return (priv->ip4_config ? nm_ip4_config_best_default_route_get (priv->ip4_config) : NULL)
?: priv->default_route4
?: (priv->ip6_config ? nm_ip6_config_best_default_route_get (priv->ip6_config) : NULL)
?: priv->default_route6;
default:
g_return_val_if_reached (NULL);
}
if (*p_has == has && *p_is_assumed == is_assumed)
return;
*p_has = has;
*p_is_assumed = is_assumed;
if (addr_family == AF_INET)
nm_default_route_manager_ip4_update_default_route (nm_netns_get_default_route_manager (priv->netns), self);
else
nm_default_route_manager_ip6_update_default_route (nm_netns_get_default_route_manager (priv->netns), self);
}
const NMPlatformIP4Route *
nm_device_get_ip4_default_route (NMDevice *self, gboolean *out_is_assumed)
{
NMDevicePrivate *priv;
g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
priv = NM_DEVICE_GET_PRIVATE (self);
if (out_is_assumed)
*out_is_assumed = priv->default_route.v4_is_assumed;
return priv->default_route.v4_has ? &priv->default_route.v4 : NULL;
}
const NMPlatformIP6Route *
nm_device_get_ip6_default_route (NMDevice *self, gboolean *out_is_assumed)
{
NMDevicePrivate *priv;
g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
priv = NM_DEVICE_GET_PRIVATE (self);
if (out_is_assumed)
*out_is_assumed = priv->default_route.v6_is_assumed;
return priv->default_route.v6_has ? &priv->default_route.v6 : NULL;
}
const char *
@ -1863,7 +1831,7 @@ update_connectivity_state (NMDevice *self, NMConnectivityState state)
/* If the connectivity check is disabled, make an optimistic guess. */
if (state == NM_CONNECTIVITY_UNKNOWN) {
if (priv->state == NM_DEVICE_STATE_ACTIVATED) {
if (priv->default_route.v4_has || priv->default_route.v6_has)
if (nm_device_get_best_default_route (self, AF_UNSPEC))
state = NM_CONNECTIVITY_FULL;
else
state = NM_CONNECTIVITY_LIMITED;
@ -1883,12 +1851,12 @@ update_connectivity_state (NMDevice *self, NMConnectivityState state)
if ( priv->state == NM_DEVICE_STATE_ACTIVATED
&& !nm_device_sys_iface_state_is_external (self)) {
if ( priv->default_route.v4_has
if ( nm_device_get_best_default_route (self, AF_INET)
&& !ip4_config_merge_and_apply (self, NULL, TRUE))
_LOGW (LOGD_IP4, "Failed to update IPv4 default route metric");
if ( priv->default_route.v6_has
_LOGW (LOGD_IP4, "Failed to update IPv4 route metric");
if ( nm_device_get_best_default_route (self, AF_INET6)
&& !ip6_config_merge_and_apply (self, TRUE))
_LOGW (LOGD_IP6, "Failed to update IPv6 default route metric");
_LOGW (LOGD_IP6, "Failed to update IPv6 route metric");
}
}
}
@ -2002,7 +1970,7 @@ concheck_periodic_update (NMDevice *self)
gboolean check_enable;
check_enable = (priv->state == NM_DEVICE_STATE_ACTIVATED)
&& (priv->default_route.v4_has || priv->default_route.v6_has);
&& nm_device_get_best_default_route (self, AF_UNSPEC);
if (check_enable && !priv->concheck_periodic_id) {
/* We just gained a default route. Enable periodic checking. */
@ -2864,7 +2832,7 @@ ip4_rp_filter_update (NMDevice *self)
const char *ip4_rp_filter;
if ( priv->v4_has_shadowed_routes
|| priv->default_route.v4_has) {
|| nm_device_get_best_default_route (self, AF_INET)) {
if (nm_device_ipv4_sysctl_get_uint32 (self, "rp_filter", 0) != 1) {
/* Don't touch the rp_filter if it's not strict. */
return;
@ -3910,15 +3878,6 @@ nm_device_removed (NMDevice *self, gboolean unconfigure_ip_config)
if (!unconfigure_ip_config)
return;
/* Clean up IP configs; this does not actually deconfigure the
* interface, it just clears the configuration to which policy
* is reacting via NM_DEVICE_IP4_CONFIG_CHANGED/NM_DEVICE_IP6_CONFIG_CHANGED
* signal. As NMPolicy registered the NMIPxConfig instances in NMDnsManager,
* these would be leaked otherwise. */
_update_default_route (self, AF_INET, priv->default_route.v4_has, TRUE);
_update_default_route (self, AF_INET6, priv->default_route.v6_has, TRUE);
_update_default_route (self, AF_INET, FALSE, TRUE);
_update_default_route (self, AF_INET6, FALSE, TRUE);
nm_device_set_ip4_config (self, NULL, 0, FALSE);
nm_device_set_ip6_config (self, NULL, FALSE);
}
@ -5516,49 +5475,6 @@ ipv4ll_start (NMDevice *self)
/*****************************************************************************/
static gboolean
_device_get_default_route_from_platform (NMDevice *self, int addr_family, NMPlatformIPRoute *out_route)
{
int ifindex = nm_device_get_ip_ifindex (self);
const NMDedupMultiHeadEntry *pl_head_entry;
NMDedupMultiIter iter;
const NMPObject *plobj = NULL;
const NMPlatformIPRoute *route = NULL;
guint32 route_metric = G_MAXUINT32;
pl_head_entry = nm_platform_lookup_route_default (nm_device_get_platform (self),
addr_family == AF_INET
? NMP_OBJECT_TYPE_IP4_ROUTE
: NMP_OBJECT_TYPE_IP6_ROUTE);
nmp_cache_iter_for_each (&iter, pl_head_entry, &plobj) {
guint32 m;
const NMPlatformIPRoute *r = NMP_OBJECT_CAST_IP_ROUTE (plobj);
if ( r->ifindex != ifindex
|| r->rt_source == NM_IP_CONFIG_SOURCE_RTPROT_KERNEL
|| r->table_coerced)
continue;
/* if there are several default routes, find the one with the best metric */
m = nm_utils_ip_route_metric_normalize (addr_family, r->metric);
if (!route || m < route_metric) {
route = NMP_OBJECT_CAST_IP_ROUTE (plobj);
route_metric = m;
}
}
if (route) {
if (addr_family == AF_INET)
*((NMPlatformIP4Route *) out_route) = *((NMPlatformIP4Route *) route);
else
*((NMPlatformIP6Route *) out_route) = *((NMPlatformIP6Route *) route);
return TRUE;
}
return FALSE;
}
/*****************************************************************************/
static void
ensure_con_ip4_config (NMDevice *self)
{
@ -5648,14 +5564,13 @@ ip4_config_merge_and_apply (NMDevice *self,
NMConnection *connection;
gboolean success;
NMIP4Config *composite;
gboolean has_direct_route;
const guint32 default_route_metric = nm_device_get_ip4_route_metric (self);
guint32 gateway;
gboolean connection_has_default_route, connection_is_never_default;
gboolean ignore_auto_routes = FALSE;
gboolean ignore_auto_dns = FALSE;
gboolean auto_method = FALSE;
GSList *iter;
NMPlatformIP4Route default_route;
/* Merge all the configs into the composite config */
if (config) {
@ -5671,10 +5586,6 @@ ip4_config_merge_and_apply (NMDevice *self,
if (s_ip4) {
ignore_auto_routes = nm_setting_ip_config_get_ignore_auto_routes (s_ip4);
ignore_auto_dns = nm_setting_ip_config_get_ignore_auto_dns (s_ip4);
if (nm_streq0 (nm_setting_ip_config_get_method (s_ip4),
NM_SETTING_IP4_CONFIG_METHOD_AUTO))
auto_method = TRUE;
}
}
@ -5718,40 +5629,17 @@ ip4_config_merge_and_apply (NMDevice *self,
if (priv->con_ip4_config)
nm_ip4_config_merge (composite, priv->con_ip4_config, NM_IP_CONFIG_MERGE_DEFAULT);
/* Add the default route.
*
* We keep track of the default route of a device in a private field.
* NMDevice needs to know the default route at this point, because the gateway
* might require a direct route (see below).
*
* But also, we don't want to add the default route to priv->ip4_config,
* because the default route from the setting might not be the same that
* NMDefaultRouteManager eventually configures (because the it might
* tweak the effective metric).
*/
/* unless we come to a different conclusion below, we have no default route and
* the route is assumed. */
priv->default_route.v4_has = FALSE;
priv->default_route.v4_is_assumed = TRUE;
/* Add the default route... */
if (!commit) {
/* during a non-commit event, we always pickup whatever is configured. */
goto END_ADD_DEFAULT_ROUTE;
}
/* a generated-assumed connection detects the default route from the platform,
* but if the IP method is automatic we need to update the default route to
* maintain connectivity.
*/
if (nm_device_sys_iface_state_is_external (self) && !auto_method)
/* for external connections, we always pickup whatever is configured. */
if (nm_device_sys_iface_state_is_external (self))
goto END_ADD_DEFAULT_ROUTE;
/* At this point, we treat assumed and non-assumed connections alike.
* For assumed connections we do that because we still manage RA and DHCP
* leases for them, so we must extend/update the default route on commits.
*/
connection_has_default_route
= nm_utils_connection_has_default_route (connection, AF_INET, &connection_is_never_default);
@ -5763,9 +5651,8 @@ ip4_config_merge_and_apply (NMDevice *self,
goto END_ADD_DEFAULT_ROUTE;
}
/* we are about to commit (for a non-assumed connection). Enforce whatever we have
* configured. */
priv->default_route.v4_is_assumed = FALSE;
nm_clear_nmp_object (&priv->default_route4);
nm_clear_nmp_object (&priv->default_routegw4);
if (!connection_has_default_route)
goto END_ADD_DEFAULT_ROUTE;
@ -5780,38 +5667,26 @@ ip4_config_merge_and_apply (NMDevice *self,
&& nm_device_get_device_type (self) != NM_DEVICE_TYPE_MODEM)
goto END_ADD_DEFAULT_ROUTE;
has_direct_route = ( gateway == 0
|| nm_ip4_config_destination_is_direct (composite, gateway, 32)
|| nm_ip4_config_get_direct_route_for_host (composite, gateway));
priv->default_route.v4_has = TRUE;
memset (&priv->default_route.v4, 0, sizeof (priv->default_route.v4));
priv->default_route.v4.rt_source = NM_IP_CONFIG_SOURCE_USER;
priv->default_route.v4.gateway = gateway;
priv->default_route.v4.metric = route_metric_with_penalty (self, default_route_metric);
priv->default_route.v4.mss = nm_ip4_config_get_mss (composite);
if (!has_direct_route) {
NMPlatformIP4Route r = priv->default_route.v4;
memset (&default_route, 0, sizeof (default_route));
default_route.rt_source = NM_IP_CONFIG_SOURCE_USER;
default_route.gateway = gateway;
default_route.metric = route_metric_with_penalty (self, default_route_metric);
default_route.mss = nm_ip4_config_get_mss (composite);
nm_clear_nmp_object (&priv->default_route4);
nm_ip4_config_add_route (composite, &default_route, &priv->default_route4);
if (!( gateway == 0
|| nm_ip4_config_destination_is_direct (composite, gateway, 32)
|| nm_ip4_config_get_direct_route_for_host (composite, gateway))) {
/* add a direct route to the gateway */
r.network = gateway;
r.plen = 32;
r.gateway = 0;
nm_ip4_config_add_route (composite, &r, NULL);
default_route.network = gateway;
default_route.plen = 32;
default_route.gateway = 0;
nm_clear_nmp_object (&priv->default_routegw4);
nm_ip4_config_add_route (composite, &default_route, &priv->default_routegw4);
}
END_ADD_DEFAULT_ROUTE:
if (priv->default_route.v4_is_assumed) {
/* If above does not explicitly assign a default route, we always pick up the
* default route based on what is currently configured.
* That means that even managed connections with never-default, can
* get a default route (if configured externally).
*/
priv->default_route.v4_has = _device_get_default_route_from_platform (self, AF_INET, (NMPlatformIPRoute *) &priv->default_route.v4);
}
if (commit) {
if (NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit)
NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit (self, composite);
@ -6369,14 +6244,13 @@ ip6_config_merge_and_apply (NMDevice *self,
NMConnection *connection;
gboolean success;
NMIP6Config *composite;
gboolean has_direct_route;
const struct in6_addr *gateway;
gboolean connection_has_default_route, connection_is_never_default;
gboolean ignore_auto_routes = FALSE;
gboolean ignore_auto_dns = FALSE;
gboolean auto_method = FALSE;
const char *token = NULL;
GSList *iter;
NMPlatformIP6Route default_route;
/* Apply ignore-auto-routes and ignore-auto-dns settings */
connection = nm_device_get_applied_connection (self);
@ -6391,11 +6265,6 @@ ip6_config_merge_and_apply (NMDevice *self,
if (nm_setting_ip6_config_get_addr_gen_mode (ip6) == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64)
token = nm_setting_ip6_config_get_token (ip6);
if (NM_IN_STRSET (nm_setting_ip_config_get_method (s_ip6),
NM_SETTING_IP6_CONFIG_METHOD_AUTO,
NM_SETTING_IP6_CONFIG_METHOD_DHCP))
auto_method = TRUE;
}
}
@ -6453,40 +6322,17 @@ ip6_config_merge_and_apply (NMDevice *self,
if (priv->con_ip6_config)
nm_ip6_config_merge (composite, priv->con_ip6_config, NM_IP_CONFIG_MERGE_DEFAULT);
/* Add the default route.
*
* We keep track of the default route of a device in a private field.
* NMDevice needs to know the default route at this point, because the gateway
* might require a direct route (see below).
*
* But also, we don't want to add the default route to priv->ip6_config,
* because the default route from the setting might not be the same that
* NMDefaultRouteManager eventually configures (because the it might
* tweak the effective metric).
*/
/* unless we come to a different conclusion below, we have no default route and
* the route is assumed. */
priv->default_route.v6_has = FALSE;
priv->default_route.v6_is_assumed = TRUE;
/* Add the default route... */
if (!commit) {
/* during a non-commit event, we always pickup whatever is configured. */
goto END_ADD_DEFAULT_ROUTE;
}
/* a generated-assumed connection detects the default route from the platform,
* but if the IP method is automatic we need to update the default route to
* maintain connectivity.
*/
if (nm_device_sys_iface_state_is_external (self) && !auto_method)
/* for external connections, we always pickup whatever is configured. */
if (nm_device_sys_iface_state_is_external (self))
goto END_ADD_DEFAULT_ROUTE;
/* At this point, we treat assumed and non-assumed connections alike.
* For assumed connections we do that because we still manage RA and DHCP
* leases for them, so we must extend/update the default route on commits.
*/
connection_has_default_route
= nm_utils_connection_has_default_route (connection, AF_INET6, &connection_is_never_default);
@ -6498,9 +6344,8 @@ ip6_config_merge_and_apply (NMDevice *self,
goto END_ADD_DEFAULT_ROUTE;
}
/* we are about to commit (for a non-assumed connection). Enforce whatever we have
* configured. */
priv->default_route.v6_is_assumed = FALSE;
nm_clear_nmp_object (&priv->default_route6);
nm_clear_nmp_object (&priv->default_routegw6);
if (!connection_has_default_route)
goto END_ADD_DEFAULT_ROUTE;
@ -6514,40 +6359,25 @@ ip6_config_merge_and_apply (NMDevice *self,
if (!gateway)
goto END_ADD_DEFAULT_ROUTE;
memset (&default_route, 0, sizeof (default_route));
default_route.rt_source = NM_IP_CONFIG_SOURCE_USER;
default_route.gateway = *gateway;
default_route.metric = route_metric_with_penalty (self,
nm_device_get_ip6_route_metric (self));
default_route.mss = nm_ip6_config_get_mss (composite);
nm_clear_nmp_object (&priv->default_route6);
nm_ip6_config_add_route (composite, &default_route, &priv->default_route6);
has_direct_route = nm_ip6_config_get_direct_route_for_host (composite, gateway) != NULL;
priv->default_route.v6_has = TRUE;
memset (&priv->default_route.v6, 0, sizeof (priv->default_route.v6));
priv->default_route.v6.rt_source = NM_IP_CONFIG_SOURCE_USER;
priv->default_route.v6.gateway = *gateway;
priv->default_route.v6.metric = route_metric_with_penalty (self,
nm_device_get_ip6_route_metric (self));
priv->default_route.v6.mss = nm_ip6_config_get_mss (composite);
if (!has_direct_route) {
NMPlatformIP6Route r = priv->default_route.v6;
if (!nm_ip6_config_get_direct_route_for_host (composite, gateway)) {
/* add a direct route to the gateway */
r.network = *gateway;
r.plen = 128;
r.gateway = in6addr_any;
nm_ip6_config_add_route (composite, &r, NULL);
default_route.network = *gateway;
default_route.plen = 128;
default_route.gateway = in6addr_any;
nm_clear_nmp_object (&priv->default_routegw6);
nm_ip6_config_add_route (composite, &default_route, &priv->default_routegw6);
}
END_ADD_DEFAULT_ROUTE:
if (priv->default_route.v6_is_assumed) {
/* If above does not explicitly assign a default route, we always pick up the
* default route based on what is currently configured.
* That means that even managed connections with never-default, can
* get a default route (if configured externally).
*/
priv->default_route.v6_has = _device_get_default_route_from_platform (self, AF_INET6, (NMPlatformIPRoute *) &priv->default_route.v6);
}
/* Allow setting MTU etc */
if (commit) {
NMUtilsIPv6IfaceId iid;
@ -8914,6 +8744,8 @@ _cleanup_ip4_pre (NMDevice *self, CleanupType cleanup_type)
_LOGD (LOGD_DEVICE, "clearing queued IP4 config change");
priv->queued_ip4_config_pending = FALSE;
nm_clear_nmp_object (&priv->default_route4);
nm_clear_nmp_object (&priv->default_routegw4);
dhcp4_cleanup (self, cleanup_type, FALSE);
arp_cleanup (self);
dnsmasq_cleanup (self);
@ -8931,6 +8763,8 @@ _cleanup_ip6_pre (NMDevice *self, CleanupType cleanup_type)
_LOGD (LOGD_DEVICE, "clearing queued IP6 config change");
priv->queued_ip6_config_pending = FALSE;
nm_clear_nmp_object (&priv->default_route6);
nm_clear_nmp_object (&priv->default_routegw6);
g_clear_object (&priv->dad6_ip6_config);
dhcp6_cleanup (self, cleanup_type, FALSE);
linklocal6_cleanup (self);
@ -9887,7 +9721,6 @@ nm_device_set_ip4_config (NMDevice *self,
NMIP4Config *old_config = NULL;
gboolean has_changes = FALSE;
gboolean success = TRUE;
gboolean def_route_changed;
int ip_ifindex = 0;
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
@ -9940,7 +9773,6 @@ nm_device_set_ip4_config (NMDevice *self,
g_clear_object (&priv->dev_ip4_config);
}
def_route_changed = nm_default_route_manager_ip4_update_default_route (nm_netns_get_default_route_manager (priv->netns), self);
concheck_periodic_update (self);
if (!nm_device_sys_iface_state_is_external_or_assume (self))
@ -9974,9 +9806,6 @@ nm_device_set_ip4_config (NMDevice *self,
}
nm_device_queue_recheck_assume (self);
} else if (def_route_changed) {
_LOGD (LOGD_IP4, "ip4-config: default route changed");
g_signal_emit (self, signals[IP4_CONFIG_CHANGED], 0, priv->ip4_config, priv->ip4_config);
}
return success;
@ -10059,7 +9888,6 @@ nm_device_set_ip6_config (NMDevice *self,
NMIP6Config *old_config = NULL;
gboolean has_changes = FALSE;
gboolean success = TRUE;
gboolean def_route_changed;
int ip_ifindex = 0;
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
@ -10110,8 +9938,6 @@ nm_device_set_ip6_config (NMDevice *self,
nm_exported_object_get_path (NM_EXPORTED_OBJECT (old_config)));
}
def_route_changed = nm_default_route_manager_ip6_update_default_route (nm_netns_get_default_route_manager (priv->netns), self);
if (has_changes) {
NMSettingsConnection *settings_connection;
@ -10141,9 +9967,6 @@ nm_device_set_ip6_config (NMDevice *self,
if (priv->ndisc)
ndisc_set_router_config (priv->ndisc, self);
} else if (def_route_changed) {
_LOGD (LOGD_IP6, "ip6-config: default route changed");
g_signal_emit (self, signals[IP6_CONFIG_CHANGED], 0, priv->ip6_config, priv->ip6_config);
}
return success;
@ -10798,6 +10621,12 @@ update_ip4_config (NMDevice *self, gboolean initial)
nm_ip4_config_intersect (priv->wwan_ip4_config, priv->ext_ip4_config);
for (iter = priv->vpn4_configs; iter; iter = iter->next)
nm_ip4_config_intersect (iter->data, priv->ext_ip4_config);
if ( priv->default_route4
&& !nm_ip4_config_nmpobj_lookup (priv->ext_ip4_config, priv->default_route4))
nm_clear_nmp_object (&priv->default_route4);
if ( priv->default_routegw4
&& !nm_ip4_config_nmpobj_lookup (priv->ext_ip4_config, priv->default_routegw4))
nm_clear_nmp_object (&priv->default_routegw4);
/* Remove parts from ext_ip4_config to only contain the information that
* was configured externally -- we already have the same configuration from
@ -10810,6 +10639,10 @@ update_ip4_config (NMDevice *self, gboolean initial)
nm_ip4_config_subtract (priv->ext_ip4_config, priv->wwan_ip4_config);
for (iter = priv->vpn4_configs; iter; iter = iter->next)
nm_ip4_config_subtract (priv->ext_ip4_config, iter->data);
if (priv->default_route4)
nm_ip4_config_nmpobj_remove (priv->ext_ip4_config, priv->default_route4);
if (priv->default_routegw4)
nm_ip4_config_nmpobj_remove (priv->ext_ip4_config, priv->default_routegw4);
ip4_config_merge_and_apply (self, NULL, FALSE);
}
@ -10870,6 +10703,12 @@ update_ip6_config (NMDevice *self, gboolean initial)
nm_ip6_config_intersect (priv->wwan_ip6_config, priv->ext_ip6_config);
for (iter = priv->vpn6_configs; iter; iter = iter->next)
nm_ip6_config_intersect (iter->data, priv->ext_ip6_config);
if ( priv->default_route6
&& !nm_ip6_config_nmpobj_lookup (priv->ext_ip6_config, priv->default_route6))
nm_clear_nmp_object (&priv->default_route6);
if ( priv->default_routegw6
&& !nm_ip6_config_nmpobj_lookup (priv->ext_ip6_config, priv->default_routegw6))
nm_clear_nmp_object (&priv->default_routegw6);
/* Remove parts from ext_ip6_config to only contain the information that
* was configured externally -- we already have the same configuration from
@ -10884,6 +10723,10 @@ update_ip6_config (NMDevice *self, gboolean initial)
nm_ip6_config_subtract (priv->ext_ip6_config, priv->wwan_ip6_config);
for (iter = priv->vpn6_configs; iter; iter = iter->next)
nm_ip6_config_subtract (priv->ext_ip6_config, iter->data);
if (priv->default_route6)
nm_ip6_config_nmpobj_remove (priv->ext_ip6_config, priv->default_route6);
if (priv->default_routegw6)
nm_ip6_config_nmpobj_remove (priv->ext_ip6_config, priv->default_routegw6);
ip6_config_merge_and_apply (self, FALSE);
}
@ -12118,16 +11961,6 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
if (cleanup_type == CLEANUP_TYPE_DECONFIGURE) {
_update_default_route (self, AF_INET, FALSE, FALSE);
_update_default_route (self, AF_INET6, FALSE, FALSE);
} else {
_update_default_route (self, AF_INET, priv->default_route.v4_has, TRUE);
_update_default_route (self, AF_INET6, priv->default_route.v6_has, TRUE);
}
_update_default_route (self, AF_INET, FALSE, TRUE);
_update_default_route (self, AF_INET6, FALSE, TRUE);
priv->v4_commit_first_time = TRUE;
priv->v6_commit_first_time = TRUE;
@ -12138,6 +11971,10 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type)
*/
nm_device_set_ip4_config (self, NULL, 0, TRUE);
nm_device_set_ip6_config (self, NULL, TRUE);
nm_clear_nmp_object (&priv->default_route4);
nm_clear_nmp_object (&priv->default_route6);
nm_clear_nmp_object (&priv->default_routegw4);
nm_clear_nmp_object (&priv->default_routegw6);
g_clear_object (&priv->proxy_config);
g_clear_object (&priv->con_ip4_config);
g_clear_object (&priv->dev_ip4_config);
@ -13819,9 +13656,6 @@ nm_device_init (NMDevice *self)
priv->ip6_saved_properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
priv->sys_iface_state = NM_DEVICE_SYS_IFACE_STATE_EXTERNAL;
priv->default_route.v4_is_assumed = TRUE;
priv->default_route.v6_is_assumed = TRUE;
priv->v4_commit_first_time = TRUE;
priv->v6_commit_first_time = TRUE;
}

View file

@ -710,8 +710,8 @@ gboolean nm_device_owns_iface (NMDevice *device, const char *iface);
NMConnection *nm_device_new_default_connection (NMDevice *self);
const NMPlatformIP4Route *nm_device_get_ip4_default_route (NMDevice *self, gboolean *out_is_assumed);
const NMPlatformIP6Route *nm_device_get_ip6_default_route (NMDevice *self, gboolean *out_is_assumed);
const NMPObject *nm_device_get_best_default_route (NMDevice *self,
int addr_family);
void nm_device_spawn_iface_helper (NMDevice *self);

View file

@ -91,8 +91,10 @@ get_ip4_rdns_domains (NMIP4Config *ip4)
nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, ip4, &address)
nm_utils_get_reverse_dns_domains_ip4 (address->address, address->plen, domains);
nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, ip4, &route)
nm_utils_get_reverse_dns_domains_ip4 (route->network, route->plen, domains);
nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, ip4, &route) {
if (!NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route))
nm_utils_get_reverse_dns_domains_ip4 (route->network, route->plen, domains);
}
/* Terminating NULL so we can use g_strfreev() to free it */
g_ptr_array_add (domains, NULL);
@ -119,8 +121,10 @@ get_ip6_rdns_domains (NMIP6Config *ip6)
nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, ip6, &address)
nm_utils_get_reverse_dns_domains_ip6 (&address->address, address->plen, domains);
nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, ip6, &route)
nm_utils_get_reverse_dns_domains_ip6 (&route->network, route->plen, domains);
nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, ip6, &route) {
if (!NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route))
nm_utils_get_reverse_dns_domains_ip6 (&route->network, route->plen, domains);
}
/* Terminating NULL so we can use g_strfreev() to free it */
g_ptr_array_add (domains, NULL);

File diff suppressed because it is too large Load diff

View file

@ -1,64 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager -- Network link manager
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2014 Red Hat, Inc.
*/
#ifndef __NETWORKMANAGER_DEFAULT_ROUTE_MANAGER_H__
#define __NETWORKMANAGER_DEFAULT_ROUTE_MANAGER_H__
#include "nm-connection.h"
#define NM_TYPE_DEFAULT_ROUTE_MANAGER (nm_default_route_manager_get_type ())
#define NM_DEFAULT_ROUTE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEFAULT_ROUTE_MANAGER, NMDefaultRouteManager))
#define NM_DEFAULT_ROUTE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEFAULT_ROUTE_MANAGER, NMDefaultRouteManagerClass))
#define NM_IS_DEFAULT_ROUTE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEFAULT_ROUTE_MANAGER))
#define NM_IS_DEFAULT_ROUTE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEFAULT_ROUTE_MANAGER))
#define NM_DEFAULT_ROUTE_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEFAULT_ROUTE_MANAGER, NMDefaultRouteManagerClass))
#define NM_DEFAULT_ROUTE_MANAGER_LOG_WITH_PTR "log-with-ptr"
#define NM_DEFAULT_ROUTE_MANAGER_PLATFORM "platform"
typedef struct _NMDefaultRouteManagerClass NMDefaultRouteManagerClass;
GType nm_default_route_manager_get_type (void);
NMDefaultRouteManager *nm_default_route_manager_new (gboolean log_with_ptr, NMPlatform *platform);
gboolean nm_default_route_manager_ip4_update_default_route (NMDefaultRouteManager *manager, gpointer source);
gboolean nm_default_route_manager_ip6_update_default_route (NMDefaultRouteManager *manager, gpointer source);
NMDevice *nm_default_route_manager_ip4_get_best_device (NMDefaultRouteManager *manager, const GSList *devices, gboolean fully_activated, NMDevice *preferred_device);
NMDevice *nm_default_route_manager_ip6_get_best_device (NMDefaultRouteManager *manager, const GSList *devices, gboolean fully_activated, NMDevice *preferred_device);
NMIP4Config *nm_default_route_manager_ip4_get_best_config (NMDefaultRouteManager *manager,
gboolean ignore_never_default,
const char **out_ip_iface,
NMActiveConnection **out_ac,
NMDevice **out_device,
NMVpnConnection **out_vpn);
NMIP6Config *nm_default_route_manager_ip6_get_best_config (NMDefaultRouteManager *manager,
gboolean ignore_never_default,
const char **out_ip_iface,
NMActiveConnection **out_ac,
NMDevice **out_device,
NMVpnConnection **out_vpn);
gboolean nm_default_route_manager_resync (NMDefaultRouteManager *self,
int af_family);
#endif /* NM_DEFAULT_ROUTE_MANAGER_H */

View file

@ -166,6 +166,8 @@ dump_ip4_to_props (NMIP4Config *ip4, GVariantBuilder *builder)
/* Static routes */
g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("aau"));
nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, ip4, &route) {
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route))
continue;
array[0] = route->network;
array[1] = route->plen;
array[2] = route->gateway;
@ -235,6 +237,8 @@ dump_ip6_to_props (NMIP6Config *ip6, GVariantBuilder *builder)
/* Static routes */
g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("a(ayuayu)"));
nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, ip6, &route) {
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route))
continue;
ip = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
&route->network,
sizeof (struct in6_addr), 1);

View file

@ -377,6 +377,7 @@ typedef struct {
GVariant *route_data_variant;
GVariant *routes_variant;
NMDedupMultiIndex *multi_idx;
const NMPObject *best_default_route;
union {
NMIPConfigDedupMultiIdxType idx_ip4_addresses_;
NMDedupMultiIdxType idx_ip4_addresses;
@ -471,6 +472,95 @@ nm_ip_config_iter_ip4_route_init (NMDedupMultiIter *ipconf_iter, const NMIP4Conf
/*****************************************************************************/
const NMPObject *
_nm_ip_config_best_default_route_find_better (const NMPObject *obj_cur, const NMPObject *obj_cmp)
{
int addr_family;
int c;
guint metric_cur, metric_cmp;
nm_assert ( !obj_cur
|| NM_IN_SET (NMP_OBJECT_GET_TYPE (obj_cur), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE));
nm_assert ( !obj_cmp
|| ( !obj_cur
&& NM_IN_SET (NMP_OBJECT_GET_TYPE (obj_cmp), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE))
|| NMP_OBJECT_GET_TYPE (obj_cur) == NMP_OBJECT_GET_TYPE (obj_cmp));
nm_assert ( !obj_cur
|| nm_ip_config_best_default_route_is (obj_cur));
/* assumes that @obj_cur is already the best default route (or NULL). It checks whether
* @obj_cmp is also a default route and returns the best of both. */
if ( obj_cmp
&& nm_ip_config_best_default_route_is (obj_cmp)) {
if (!obj_cur)
return obj_cmp;
addr_family = NMP_OBJECT_GET_CLASS (obj_cmp)->addr_family;
metric_cur = nm_utils_ip_route_metric_normalize (addr_family, NMP_OBJECT_CAST_IP_ROUTE (obj_cur)->metric);
metric_cmp = nm_utils_ip_route_metric_normalize (addr_family, NMP_OBJECT_CAST_IP_ROUTE (obj_cmp)->metric);
if (metric_cmp < metric_cur)
return obj_cmp;
if (metric_cmp == metric_cur) {
/* Routes have the same metric. We still want to deterministically
* prefer one or the other. It's important to consistently choose one
* or the other, so that the order doesn't matter how routes are added
* (and merged). */
c = nmp_object_cmp (obj_cur, obj_cmp);
if (c != 0)
return c < 0 ? obj_cur : obj_cmp;
/* as last resort, compare pointers. */
if (obj_cmp < obj_cur)
return obj_cmp;
}
}
return obj_cur;
}
gboolean
_nm_ip_config_best_default_route_set (const NMPObject **best_default_route, const NMPObject *new_candidate)
{
if (new_candidate == *best_default_route)
return FALSE;
nmp_object_ref (new_candidate);
nm_clear_nmp_object (best_default_route);
*best_default_route = new_candidate;
return TRUE;
}
gboolean
_nm_ip_config_best_default_route_merge (const NMPObject **best_default_route, const NMPObject *new_candidate)
{
new_candidate = _nm_ip_config_best_default_route_find_better (*best_default_route,
new_candidate);
return _nm_ip_config_best_default_route_set (best_default_route, new_candidate);
}
const NMPObject *
nm_ip4_config_best_default_route_get (const NMIP4Config *self)
{
g_return_val_if_fail (NM_IS_IP4_CONFIG (self), NULL);
return NM_IP4_CONFIG_GET_PRIVATE (self)->best_default_route;
}
const NMPObject *
_nm_ip4_config_best_default_route_find (const NMIP4Config *self)
{
NMDedupMultiIter ipconf_iter;
const NMPObject *new_best_default_route = NULL;
nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, self, NULL) {
new_best_default_route = _nm_ip_config_best_default_route_find_better (new_best_default_route,
ipconf_iter.current->obj);
}
return new_best_default_route;
}
/*****************************************************************************/
static void
_notify_addresses (NMIP4Config *self)
{
@ -487,6 +577,7 @@ _notify_routes (NMIP4Config *self)
{
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
nm_assert (priv->best_default_route == _nm_ip4_config_best_default_route_find (self));
nm_clear_g_variant (&priv->route_data_variant);
nm_clear_g_variant (&priv->routes_variant);
_notify (self, PROP_ROUTE_DATA);
@ -688,8 +779,6 @@ nm_ip4_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i
continue;
if (route->rt_source == NM_IP_CONFIG_SOURCE_RTPROT_KERNEL)
continue;
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route))
continue;
_add_route (self, plobj, NULL, NULL);
}
@ -1056,8 +1145,7 @@ nm_ip4_config_create_setting (const NMIP4Config *self)
nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, self, &route) {
NMIPRoute *s_route;
/* Ignore default route. */
if (!route->plen)
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route))
continue;
/* Ignore routes provided by external sources */
@ -1133,10 +1221,8 @@ nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src, NMIPConfigMergeFl
/* routes */
if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_ROUTES)) {
const NMPlatformIP4Route *route;
nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, src, &route)
_add_route (dst, NMP_OBJECT_UP_CAST (route), NULL, NULL);
nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, src, NULL)
_add_route (dst, ipconf_iter.current->obj, NULL, NULL);
}
if (dst_priv->route_metric == -1)
@ -1310,6 +1396,7 @@ nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src)
const NMPlatformIP4Route *r;
NMDedupMultiIter ipconf_iter;
gboolean changed;
gboolean changed_default_route;
g_return_if_fail (src != NULL);
g_return_if_fail (dst != NULL);
@ -1349,12 +1436,24 @@ nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src)
/* routes */
changed = FALSE;
changed_default_route = FALSE;
nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, src, &r) {
nm_auto_nmpobj const NMPObject *obj_old = NULL;
if (nm_dedup_multi_index_remove_obj (dst_priv->multi_idx,
&dst_priv->idx_ip4_routes,
NMP_OBJECT_UP_CAST (r),
NULL))
(gconstpointer *) &obj_old)) {
if (dst_priv->best_default_route == obj_old) {
nm_clear_nmp_object (&dst_priv->best_default_route);
changed_default_route = TRUE;
}
changed = TRUE;
}
}
if (changed_default_route) {
_nm_ip_config_best_default_route_set (&dst_priv->best_default_route,
_nm_ip4_config_best_default_route_find (dst));
}
if (changed)
_notify_routes (dst);
@ -1421,16 +1520,17 @@ nm_ip4_config_intersect (NMIP4Config *dst, const NMIP4Config *src)
NMDedupMultiIter ipconf_iter;
const NMPlatformIP4Address *a;
const NMPlatformIP4Route *r;
const NMPObject *new_best_default_route;
gboolean changed;
g_return_if_fail (src);
g_return_if_fail (dst);
g_object_freeze_notify (G_OBJECT (dst));
dst_priv = NM_IP4_CONFIG_GET_PRIVATE (dst);
src_priv = NM_IP4_CONFIG_GET_PRIVATE (src);
g_object_freeze_notify (G_OBJECT (dst));
/* addresses */
changed = FALSE;
nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, dst, &a) {
@ -1459,17 +1559,24 @@ nm_ip4_config_intersect (NMIP4Config *dst, const NMIP4Config *src)
/* routes */
changed = FALSE;
new_best_default_route = NULL;
nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, dst, &r) {
const NMPObject *o = NMP_OBJECT_UP_CAST (r);
if (nm_dedup_multi_index_lookup_obj (src_priv->multi_idx,
&src_priv->idx_ip4_routes,
NMP_OBJECT_UP_CAST (r)))
o)) {
new_best_default_route = _nm_ip_config_best_default_route_find_better (new_best_default_route, o);
continue;
}
if (nm_dedup_multi_index_remove_entry (dst_priv->multi_idx,
ipconf_iter.current) != 1)
nm_assert_not_reached ();
changed = TRUE;
}
if (_nm_ip_config_best_default_route_set (&dst_priv->best_default_route, new_best_default_route))
nm_assert (changed);
if (changed)
_notify_routes (dst);
@ -1509,6 +1616,7 @@ nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relev
const NMIP4ConfigPrivate *src_priv;
NMDedupMultiIter ipconf_iter_src, ipconf_iter_dst;
const NMDedupMultiHeadEntry *head_entry_src;
const NMPObject *new_best_default_route;
g_return_val_if_fail (src != NULL, FALSE);
g_return_val_if_fail (dst != NULL, FALSE);
@ -1627,19 +1735,25 @@ nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relev
}
if (!are_equal) {
has_minor_changes = TRUE;
new_best_default_route = NULL;
nm_dedup_multi_index_dirty_set_idx (dst_priv->multi_idx, &dst_priv->idx_ip4_routes);
nm_dedup_multi_iter_for_each (&ipconf_iter_src, head_entry_src) {
const NMPObject *o = ipconf_iter_src.current->obj;
const NMPObject *obj_new;
_nm_ip_config_add_obj (dst_priv->multi_idx,
&dst_priv->idx_ip4_routes_,
dst_priv->ifindex,
ipconf_iter_src.current->obj,
o,
NULL,
FALSE,
TRUE,
NULL,
NULL);
&obj_new);
new_best_default_route = _nm_ip_config_best_default_route_find_better (new_best_default_route, obj_new);
}
nm_dedup_multi_index_dirty_remove_idx (dst_priv->multi_idx, &dst_priv->idx_ip4_routes, FALSE);
_nm_ip_config_best_default_route_set (&dst_priv->best_default_route, new_best_default_route);
_notify_routes (dst);
}
@ -2028,18 +2142,12 @@ nm_ip4_config_add_address (NMIP4Config *self, const NMPlatformIP4Address *new)
void
_nmtst_ip4_config_del_address (NMIP4Config *self, guint i)
{
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
const NMPlatformIP4Address *a;
a = _nmtst_ip4_config_get_address (self, i);
g_return_if_fail (a);
if (nm_dedup_multi_index_remove_obj (priv->multi_idx,
&priv->idx_ip4_addresses,
NMP_OBJECT_UP_CAST (a),
NULL) != 1)
g_return_if_reached ();
_notify_addresses (self);
if (!nm_ip4_config_nmpobj_remove (self,
NMP_OBJECT_UP_CAST (a)))
g_assert_not_reached ();
}
guint
@ -2121,8 +2229,10 @@ nm_ip4_config_reset_routes (NMIP4Config *self)
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
if (nm_dedup_multi_index_remove_idx (priv->multi_idx,
&priv->idx_ip4_routes) > 0)
&priv->idx_ip4_routes) > 0) {
nm_clear_nmp_object (&priv->best_default_route);
_notify_routes (self);
}
}
static void
@ -2132,6 +2242,7 @@ _add_route (NMIP4Config *self,
const NMPObject **out_obj_new)
{
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
nm_auto_nmpobj const NMPObject *obj_old = NULL;
const NMPObject *obj_new_2;
nm_assert ((!new) != (!obj_new));
@ -2145,8 +2256,12 @@ _add_route (NMIP4Config *self,
(const NMPlatformObject *) new,
TRUE,
FALSE,
NULL,
&obj_old,
&obj_new_2)) {
if ( priv->best_default_route == obj_old
&& obj_old != obj_new_2)
nm_clear_nmp_object (&priv->best_default_route);
_nm_ip_config_best_default_route_merge (&priv->best_default_route, obj_new_2);
NM_SET_OUT (out_obj_new, nmp_object_ref (obj_new_2));
_notify_routes (self);
} else
@ -2172,7 +2287,7 @@ nm_ip4_config_add_route (NMIP4Config *self,
{
g_return_if_fail (self);
g_return_if_fail (new);
g_return_if_fail (new->plen > 0 && new->plen <= 32);
g_return_if_fail (new->plen <= 32);
g_return_if_fail (NM_IP4_CONFIG_GET_PRIVATE (self)->ifindex > 0);
_add_route (self, NULL, new, out_obj_new);
@ -2181,18 +2296,12 @@ nm_ip4_config_add_route (NMIP4Config *self,
void
_nmtst_ip4_config_del_route (NMIP4Config *self, guint i)
{
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
const NMPlatformIP4Route *r;
r = _nmtst_ip4_config_get_route (self, i);
g_return_if_fail (r);
if (nm_dedup_multi_index_remove_obj (priv->multi_idx,
&priv->idx_ip4_routes,
NMP_OBJECT_UP_CAST (r),
NULL) != 1)
g_return_if_reached ();
_notify_routes (self);
if (!nm_ip4_config_nmpobj_remove (self,
NMP_OBJECT_UP_CAST (r)))
g_assert_not_reached ();
}
guint
@ -2701,6 +2810,84 @@ nm_ip4_config_get_metered (const NMIP4Config *self)
/*****************************************************************************/
const NMPObject *
nm_ip4_config_nmpobj_lookup (const NMIP4Config *self, const NMPObject *needle)
{
const NMIP4ConfigPrivate *priv;
const NMDedupMultiIdxType *idx_type;
g_return_val_if_fail (NM_IS_IP4_CONFIG (self), NULL);
priv = NM_IP4_CONFIG_GET_PRIVATE (self);
switch (NMP_OBJECT_GET_TYPE (needle)) {
case NMP_OBJECT_TYPE_IP4_ADDRESS:
idx_type = &priv->idx_ip4_addresses;
break;
case NMP_OBJECT_TYPE_IP4_ROUTE:
idx_type = &priv->idx_ip4_routes;
break;
default:
g_return_val_if_reached (NULL);
}
return nm_dedup_multi_entry_get_obj (nm_dedup_multi_index_lookup_obj (priv->multi_idx,
idx_type,
needle));
}
gboolean
nm_ip4_config_nmpobj_remove (NMIP4Config *self,
const NMPObject *needle)
{
NMIP4ConfigPrivate *priv;
NMDedupMultiIdxType *idx_type;
nm_auto_nmpobj const NMPObject *obj_old = NULL;
guint n;
g_return_val_if_fail (NM_IS_IP4_CONFIG (self), FALSE);
priv = NM_IP4_CONFIG_GET_PRIVATE (self);
switch (NMP_OBJECT_GET_TYPE (needle)) {
case NMP_OBJECT_TYPE_IP4_ADDRESS:
idx_type = &priv->idx_ip4_addresses;
break;
case NMP_OBJECT_TYPE_IP4_ROUTE:
idx_type = &priv->idx_ip4_routes;
break;
default:
g_return_val_if_reached (FALSE);
}
n = nm_dedup_multi_index_remove_obj (priv->multi_idx,
idx_type,
needle,
(gconstpointer *) &obj_old);
if (n != 1) {
nm_assert (n == 0);
return FALSE;
}
nm_assert (NMP_OBJECT_GET_TYPE (obj_old) == NMP_OBJECT_GET_TYPE (needle));
switch (NMP_OBJECT_GET_TYPE (obj_old)) {
case NMP_OBJECT_TYPE_IP4_ADDRESS:
_notify_addresses (self);
break;
case NMP_OBJECT_TYPE_IP4_ROUTE:
if (priv->best_default_route == obj_old) {
_nm_ip_config_best_default_route_set (&priv->best_default_route,
_nm_ip4_config_best_default_route_find (self));
}
_notify_routes (self);
break;
default:
nm_assert_not_reached ();
}
return TRUE;
}
/*****************************************************************************/
static inline void
hash_u32 (GChecksum *sum, guint32 n)
{
@ -3056,6 +3243,8 @@ finalize (GObject *object)
NMIP4Config *self = NM_IP4_CONFIG (object);
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
nm_clear_nmp_object (&priv->best_default_route);
nm_dedup_multi_index_remove_idx (priv->multi_idx, &priv->idx_ip4_addresses);
nm_dedup_multi_index_remove_idx (priv->multi_idx, &priv->idx_ip4_routes);

View file

@ -75,6 +75,25 @@ nm_ip_config_iter_ip4_route_next (NMDedupMultiIter *ipconf_iter, const NMPlatfor
/*****************************************************************************/
static inline gboolean
nm_ip_config_best_default_route_is (const NMPObject *obj)
{
const NMPlatformIPRoute *r = NMP_OBJECT_CAST_IP_ROUTE (obj);
/* return whether @obj is considered a default-route, that is, a route
* as added by NetworkManager. E.g. if the route is not in the main-table,
* it's considered just like a regular route. */
return r
&& !r->table_coerced
&& NM_PLATFORM_IP_ROUTE_IS_DEFAULT (r);
}
const NMPObject *_nm_ip_config_best_default_route_find_better (const NMPObject *obj_cur, const NMPObject *obj_cmp);
gboolean _nm_ip_config_best_default_route_set (const NMPObject **best_default_route, const NMPObject *new_candidate);
gboolean _nm_ip_config_best_default_route_merge (const NMPObject **best_default_route, const NMPObject *new_candidate);
/*****************************************************************************/
gboolean nm_ip_config_obj_id_equal_ip4_address (const NMPlatformIP4Address *a,
const NMPlatformIP4Address *b);
gboolean nm_ip_config_obj_id_equal_ip6_address (const NMPlatformIP6Address *a,
@ -163,6 +182,9 @@ gboolean nm_ip4_config_has_gateway (const NMIP4Config *self);
guint32 nm_ip4_config_get_gateway (const NMIP4Config *self);
gint64 nm_ip4_config_get_route_metric (const NMIP4Config *self);
const NMPObject *nm_ip4_config_best_default_route_get (const NMIP4Config *self);
const NMPObject *_nm_ip4_config_best_default_route_find (const NMIP4Config *self);
const NMDedupMultiHeadEntry *nm_ip4_config_lookup_addresses (const NMIP4Config *self);
void nm_ip4_config_reset_addresses (NMIP4Config *self);
void nm_ip4_config_add_address (NMIP4Config *self, const NMPlatformIP4Address *address);
@ -234,6 +256,11 @@ NMIPConfigSource nm_ip4_config_get_mtu_source (const NMIP4Config *self);
void nm_ip4_config_set_metered (NMIP4Config *self, gboolean metered);
gboolean nm_ip4_config_get_metered (const NMIP4Config *self);
const NMPObject *nm_ip4_config_nmpobj_lookup (const NMIP4Config *self,
const NMPObject *needle);
gboolean nm_ip4_config_nmpobj_remove (NMIP4Config *self,
const NMPObject *needle);
void nm_ip4_config_hash (const NMIP4Config *self, GChecksum *sum, gboolean dns_only);
gboolean nm_ip4_config_equal (const NMIP4Config *a, const NMIP4Config *b);

View file

@ -72,6 +72,7 @@ typedef struct {
GVariant *route_data_variant;
GVariant *routes_variant;
NMDedupMultiIndex *multi_idx;
const NMPObject *best_default_route;
union {
NMIPConfigDedupMultiIdxType idx_ip6_addresses_;
NMDedupMultiIdxType idx_ip6_addresses;
@ -177,6 +178,29 @@ nm_ip_config_iter_ip6_route_init (NMDedupMultiIter *ipconf_iter, const NMIP6Conf
/*****************************************************************************/
const NMPObject *
nm_ip6_config_best_default_route_get (const NMIP6Config *self)
{
g_return_val_if_fail (NM_IS_IP6_CONFIG (self), NULL);
return NM_IP6_CONFIG_GET_PRIVATE (self)->best_default_route;
}
const NMPObject *
_nm_ip6_config_best_default_route_find (const NMIP6Config *self)
{
NMDedupMultiIter ipconf_iter;
const NMPObject *new_best_default_route = NULL;
nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, self, NULL) {
new_best_default_route = _nm_ip_config_best_default_route_find_better (new_best_default_route,
ipconf_iter.current->obj);
}
return new_best_default_route;
}
/*****************************************************************************/
static void
_notify_addresses (NMIP6Config *self)
{
@ -193,6 +217,7 @@ _notify_routes (NMIP6Config *self)
{
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self);
nm_assert (priv->best_default_route == _nm_ip6_config_best_default_route_find (self));
nm_clear_g_variant (&priv->route_data_variant);
nm_clear_g_variant (&priv->routes_variant);
_notify (self, PROP_ROUTE_DATA);
@ -478,8 +503,6 @@ nm_ip6_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i
continue;
if (route->rt_source == NM_IP_CONFIG_SOURCE_RTPROT_KERNEL)
continue;
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route))
continue;
_add_route (self, plobj, NULL, NULL);
}
@ -781,8 +804,7 @@ nm_ip6_config_create_setting (const NMIP6Config *self)
if (IN6_IS_ADDR_LINKLOCAL (&route->network))
continue;
/* Ignore default route. */
if (!route->plen)
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route))
continue;
/* Ignore routes provided by external sources */
@ -857,10 +879,8 @@ nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src, NMIPConfigMergeFl
/* routes */
if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_ROUTES)) {
const NMPlatformIP6Route *route;
nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, src, &route)
_add_route (dst, NMP_OBJECT_UP_CAST (route), NULL, NULL);
nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, src, NULL)
_add_route (dst, ipconf_iter.current->obj, NULL, NULL);
}
if (dst_priv->route_metric == -1)
@ -997,6 +1017,7 @@ nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src)
NMDedupMultiIter ipconf_iter;
const struct in6_addr *dst_tmp, *src_tmp;
gboolean changed;
gboolean changed_default_route;
g_return_if_fail (src != NULL);
g_return_if_fail (dst != NULL);
@ -1037,12 +1058,24 @@ nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src)
/* routes */
changed = FALSE;
changed_default_route = FALSE;
nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, src, &r) {
nm_auto_nmpobj const NMPObject *obj_old = NULL;
if (nm_dedup_multi_index_remove_obj (dst_priv->multi_idx,
&dst_priv->idx_ip6_routes,
NMP_OBJECT_UP_CAST (r),
NULL))
(gconstpointer *) &obj_old)) {
if (dst_priv->best_default_route == obj_old) {
nm_clear_nmp_object (&dst_priv->best_default_route);
changed_default_route = TRUE;
}
changed = TRUE;
}
}
if (changed_default_route) {
_nm_ip_config_best_default_route_set (&dst_priv->best_default_route,
_nm_ip6_config_best_default_route_find (dst));
}
if (changed)
_notify_routes (dst);
@ -1088,6 +1121,7 @@ nm_ip6_config_intersect (NMIP6Config *dst, const NMIP6Config *src)
const NMPlatformIP6Address *a;
const NMPlatformIP6Route *r;
gboolean changed;
const NMPObject *new_best_default_route;
g_return_if_fail (src);
g_return_if_fail (dst);
@ -1128,17 +1162,24 @@ nm_ip6_config_intersect (NMIP6Config *dst, const NMIP6Config *src)
/* routes */
changed = FALSE;
new_best_default_route = NULL;
nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, dst, &r) {
const NMPObject *o = NMP_OBJECT_UP_CAST (r);
if (nm_dedup_multi_index_lookup_obj (src_priv->multi_idx,
&src_priv->idx_ip6_routes,
NMP_OBJECT_UP_CAST (r)))
o)) {
new_best_default_route = _nm_ip_config_best_default_route_find_better (new_best_default_route, o);
continue;
}
if (nm_dedup_multi_index_remove_entry (dst_priv->multi_idx,
ipconf_iter.current) != 1)
nm_assert_not_reached ();
changed = TRUE;
}
if (_nm_ip_config_best_default_route_set (&dst_priv->best_default_route, new_best_default_route))
nm_assert (changed);
if (changed)
_notify_routes (dst);
@ -1175,6 +1216,7 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev
const NMIP6ConfigPrivate *src_priv;
NMDedupMultiIter ipconf_iter_src, ipconf_iter_dst;
const NMDedupMultiHeadEntry *head_entry_src;
const NMPObject *new_best_default_route;
g_return_val_if_fail (NM_IS_IP6_CONFIG (src), FALSE);
g_return_val_if_fail (NM_IS_IP6_CONFIG (dst), FALSE);
@ -1293,19 +1335,25 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev
}
if (!are_equal) {
has_minor_changes = TRUE;
new_best_default_route = NULL;
nm_dedup_multi_index_dirty_set_idx (dst_priv->multi_idx, &dst_priv->idx_ip6_routes);
nm_dedup_multi_iter_for_each (&ipconf_iter_src, head_entry_src) {
const NMPObject *o = ipconf_iter_src.current->obj;
const NMPObject *obj_new;
_nm_ip_config_add_obj (dst_priv->multi_idx,
&dst_priv->idx_ip6_routes_,
dst_priv->ifindex,
ipconf_iter_src.current->obj,
o,
NULL,
FALSE,
TRUE,
NULL,
NULL);
&obj_new);
new_best_default_route = _nm_ip_config_best_default_route_find_better (new_best_default_route, obj_new);
}
nm_dedup_multi_index_dirty_remove_idx (dst_priv->multi_idx, &dst_priv->idx_ip6_routes, FALSE);
_nm_ip_config_best_default_route_set (&dst_priv->best_default_route, new_best_default_route);
_notify_routes (dst);
}
@ -1631,18 +1679,12 @@ nm_ip6_config_add_address (NMIP6Config *self, const NMPlatformIP6Address *new)
void
_nmtst_ip6_config_del_address (NMIP6Config *self, guint i)
{
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self);
const NMPlatformIP6Address *a;
a = _nmtst_ip6_config_get_address (self, i);
g_return_if_fail (a);
if (nm_dedup_multi_index_remove_obj (priv->multi_idx,
&priv->idx_ip6_addresses,
NMP_OBJECT_UP_CAST (a),
NULL) != 1)
g_return_if_reached ();
_notify_addresses (self);
if (!nm_ip6_config_nmpobj_remove (self,
NMP_OBJECT_UP_CAST (a)))
g_assert_not_reached ();
}
guint
@ -1767,6 +1809,7 @@ nm_ip6_config_reset_routes_ndisc (NMIP6Config *self,
NMIP6ConfigPrivate *priv;
guint i;
gboolean changed = FALSE;
const NMPObject *new_best_default_route;
g_return_if_fail (NM_IS_IP6_CONFIG (self));
@ -1776,9 +1819,11 @@ nm_ip6_config_reset_routes_ndisc (NMIP6Config *self,
nm_dedup_multi_index_dirty_set_idx (priv->multi_idx, &priv->idx_ip6_routes);
new_best_default_route = NULL;
for (i = 0; i < routes_n; i++) {
const NMNDiscRoute *ndisc_route = &routes[i];
NMPObject obj;
const NMPObject *obj_new;
NMPlatformIP6Route *r;
nmp_object_stackinit (&obj, NMP_OBJECT_TYPE_IP6_ROUTE, NULL);
@ -1798,10 +1843,14 @@ nm_ip6_config_reset_routes_ndisc (NMIP6Config *self,
FALSE,
TRUE,
NULL,
NULL))
&obj_new))
changed = TRUE;
new_best_default_route = _nm_ip_config_best_default_route_find_better (new_best_default_route, obj_new);
}
if (_nm_ip_config_best_default_route_set (&priv->best_default_route, new_best_default_route))
changed = TRUE;
if (nm_dedup_multi_index_dirty_remove_idx (priv->multi_idx, &priv->idx_ip6_routes, FALSE) > 0)
changed = TRUE;
@ -1815,8 +1864,10 @@ nm_ip6_config_reset_routes (NMIP6Config *self)
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self);
if (nm_dedup_multi_index_remove_idx (priv->multi_idx,
&priv->idx_ip6_routes) > 0)
&priv->idx_ip6_routes) > 0) {
nm_clear_nmp_object (&priv->best_default_route);
_notify_routes (self);
}
}
static void
@ -1826,6 +1877,7 @@ _add_route (NMIP6Config *self,
const NMPObject **out_obj_new)
{
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self);
nm_auto_nmpobj const NMPObject *obj_old = NULL;
const NMPObject *obj_new_2;
nm_assert ((!new) != (!obj_new));
@ -1839,8 +1891,12 @@ _add_route (NMIP6Config *self,
(const NMPlatformObject *) new,
TRUE,
FALSE,
NULL,
&obj_old,
&obj_new_2)) {
if ( priv->best_default_route == obj_old
&& obj_old != obj_new_2)
nm_clear_nmp_object (&priv->best_default_route);
_nm_ip_config_best_default_route_merge (&priv->best_default_route, obj_new_2);
NM_SET_OUT (out_obj_new, nmp_object_ref (obj_new_2));
_notify_routes (self);
} else
@ -1866,7 +1922,7 @@ nm_ip6_config_add_route (NMIP6Config *self,
{
g_return_if_fail (self);
g_return_if_fail (new);
g_return_if_fail (new->plen > 0 && new->plen <= 128);
g_return_if_fail (new->plen <= 128);
g_return_if_fail (NM_IP6_CONFIG_GET_PRIVATE (self)->ifindex > 0);
_add_route (self, NULL, new, out_obj_new);
@ -1875,18 +1931,12 @@ nm_ip6_config_add_route (NMIP6Config *self,
void
_nmtst_ip6_config_del_route (NMIP6Config *self, guint i)
{
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self);
const NMPlatformIP6Route *r;
r = _nmtst_ip6_config_get_route (self, i);
g_return_if_fail (r);
if (nm_dedup_multi_index_remove_obj (priv->multi_idx,
&priv->idx_ip6_routes,
NMP_OBJECT_UP_CAST (r),
NULL) != 1)
g_return_if_reached ();
_notify_routes (self);
if (!nm_ip6_config_nmpobj_remove (self,
NMP_OBJECT_UP_CAST (r)))
g_assert_not_reached ();
}
guint
@ -2251,6 +2301,84 @@ nm_ip6_config_get_mss (const NMIP6Config *self)
/*****************************************************************************/
const NMPObject *
nm_ip6_config_nmpobj_lookup (const NMIP6Config *self, const NMPObject *needle)
{
const NMIP6ConfigPrivate *priv;
const NMDedupMultiIdxType *idx_type;
g_return_val_if_fail (NM_IS_IP6_CONFIG (self), NULL);
priv = NM_IP6_CONFIG_GET_PRIVATE (self);
switch (NMP_OBJECT_GET_TYPE (needle)) {
case NMP_OBJECT_TYPE_IP6_ADDRESS:
idx_type = &priv->idx_ip6_addresses;
break;
case NMP_OBJECT_TYPE_IP6_ROUTE:
idx_type = &priv->idx_ip6_routes;
break;
default:
g_return_val_if_reached (NULL);
}
return nm_dedup_multi_entry_get_obj (nm_dedup_multi_index_lookup_obj (priv->multi_idx,
idx_type,
needle));
}
gboolean
nm_ip6_config_nmpobj_remove (NMIP6Config *self,
const NMPObject *needle)
{
NMIP6ConfigPrivate *priv;
NMDedupMultiIdxType *idx_type;
nm_auto_nmpobj const NMPObject *obj_old = NULL;
guint n;
g_return_val_if_fail (NM_IS_IP6_CONFIG (self), FALSE);
priv = NM_IP6_CONFIG_GET_PRIVATE (self);
switch (NMP_OBJECT_GET_TYPE (needle)) {
case NMP_OBJECT_TYPE_IP6_ADDRESS:
idx_type = &priv->idx_ip6_addresses;
break;
case NMP_OBJECT_TYPE_IP6_ROUTE:
idx_type = &priv->idx_ip6_routes;
break;
default:
g_return_val_if_reached (FALSE);
}
n = nm_dedup_multi_index_remove_obj (priv->multi_idx,
idx_type,
needle,
(gconstpointer *) &obj_old);
if (n != 1) {
nm_assert (n == 0);
return FALSE;
}
nm_assert (NMP_OBJECT_GET_TYPE (obj_old) == NMP_OBJECT_GET_TYPE (needle));
switch (NMP_OBJECT_GET_TYPE (obj_old)) {
case NMP_OBJECT_TYPE_IP6_ADDRESS:
_notify_addresses (self);
break;
case NMP_OBJECT_TYPE_IP6_ROUTE:
if (priv->best_default_route == obj_old) {
_nm_ip_config_best_default_route_set (&priv->best_default_route,
_nm_ip6_config_best_default_route_find (self));
}
_notify_routes (self);
break;
default:
nm_assert_not_reached ();
}
return TRUE;
}
/*****************************************************************************/
static inline void
hash_u32 (GChecksum *sum, guint32 n)
{
@ -2611,6 +2739,8 @@ finalize (GObject *object)
NMIP6Config *self = NM_IP6_CONFIG (object);
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self);
nm_clear_nmp_object (&priv->best_default_route);
nm_dedup_multi_index_remove_idx (priv->multi_idx, &priv->idx_ip6_addresses);
nm_dedup_multi_index_remove_idx (priv->multi_idx, &priv->idx_ip6_routes);

View file

@ -127,6 +127,9 @@ void nm_ip6_config_set_gateway (NMIP6Config *self, const struct in6_addr *);
const struct in6_addr *nm_ip6_config_get_gateway (const NMIP6Config *self);
gint64 nm_ip6_config_get_route_metric (const NMIP6Config *self);
const NMPObject *nm_ip6_config_best_default_route_get (const NMIP6Config *self);
const NMPObject *_nm_ip6_config_best_default_route_find (const NMIP6Config *self);
const NMDedupMultiHeadEntry *nm_ip6_config_lookup_addresses (const NMIP6Config *self);
void nm_ip6_config_reset_addresses (NMIP6Config *self);
void nm_ip6_config_add_address (NMIP6Config *self, const NMPlatformIP6Address *address);
@ -184,6 +187,11 @@ gint nm_ip6_config_get_dns_priority (const NMIP6Config *self);
void nm_ip6_config_set_mss (NMIP6Config *self, guint32 mss);
guint32 nm_ip6_config_get_mss (const NMIP6Config *self);
const NMPObject *nm_ip6_config_nmpobj_lookup (const NMIP6Config *self,
const NMPObject *needle);
gboolean nm_ip6_config_nmpobj_remove (NMIP6Config *self,
const NMPObject *needle);
void nm_ip6_config_hash (const NMIP6Config *self, GChecksum *sum, gboolean dns_only);
gboolean nm_ip6_config_equal (const NMIP6Config *a, const NMIP6Config *b);

View file

@ -26,7 +26,6 @@
#include "platform/nm-platform.h"
#include "platform/nmp-netns.h"
#include "nm-default-route-manager.h"
#include "nm-core-internal.h"
#include "NetworkManagerUtils.h"
@ -39,7 +38,6 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE (
typedef struct {
NMPlatform *platform;
NMPNetns *platform_netns;
NMDefaultRouteManager *default_route_manager;
bool log_with_ptr;
} NMNetnsPrivate;
@ -80,12 +78,6 @@ nm_netns_get_multi_idx (NMNetns *self)
return nm_platform_get_multi_idx (NM_NETNS_GET_PRIVATE (self)->platform);
}
NMDefaultRouteManager *
nm_netns_get_default_route_manager (NMNetns *self)
{
return NM_NETNS_GET_PRIVATE (self)->default_route_manager;
}
/*****************************************************************************/
static void
@ -129,7 +121,6 @@ constructed (GObject *object)
log_with_ptr = nm_platform_get_log_with_ptr (priv->platform);
priv->platform_netns = nm_platform_netns_get (priv->platform);
priv->default_route_manager = nm_default_route_manager_new (log_with_ptr, priv->platform);
G_OBJECT_CLASS (nm_netns_parent_class)->constructed (object);
}
@ -148,7 +139,6 @@ dispose (GObject *object)
NMNetns *self = NM_NETNS (object);
NMNetnsPrivate *priv = NM_NETNS_GET_PRIVATE (self);
g_clear_object (&priv->default_route_manager);
g_clear_object (&priv->platform);
G_OBJECT_CLASS (nm_netns_parent_class)->dispose (object);

View file

@ -39,7 +39,6 @@ NMNetns *nm_netns_new (NMPlatform *platform);
NMPlatform *nm_netns_get_platform (NMNetns *self);
NMPNetns *nm_netns_get_platform_netns (NMNetns *self);
NMDefaultRouteManager *nm_netns_get_default_route_manager (NMNetns *self);
struct _NMDedupMultiIndex *nm_netns_get_multi_idx (NMNetns *self);

View file

@ -192,6 +192,8 @@ get_ip4_domains (GPtrArray *domains, NMIP4Config *ip4)
}
nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, ip4, &routes) {
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (routes))
continue;
cidr = g_strdup_printf ("%s/%u",
nm_utils_inet4_ntop (routes->network, NULL),
routes->plen);
@ -225,6 +227,8 @@ get_ip6_domains (GPtrArray *domains, NMIP6Config *ip6)
}
nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, ip6, &routes) {
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (routes))
continue;
cidr = g_strdup_printf ("%s/%u",
nm_utils_inet6_ntop (&routes->network, NULL),
routes->plen);

View file

@ -31,7 +31,6 @@
#include "NetworkManagerUtils.h"
#include "nm-act-request.h"
#include "devices/nm-device.h"
#include "nm-default-route-manager.h"
#include "nm-setting-ip4-config.h"
#include "nm-setting-connection.h"
#include "platform/nm-platform.h"
@ -375,25 +374,81 @@ device_ip6_subnet_needed (NMDevice *device,
/*****************************************************************************/
static NMDevice *
get_best_ip4_device (NMPolicy *self, gboolean fully_activated)
get_best_ip_device (NMPolicy *self,
int addr_family,
gboolean fully_activated)
{
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
const GSList *iter;
NMDevice *best_device;
NMDevice *prev_device;
guint32 best_metric = G_MAXUINT32;
gboolean best_is_fully_activated = FALSE;
return nm_default_route_manager_ip4_get_best_device (nm_netns_get_default_route_manager (priv->netns),
nm_manager_get_devices (priv->manager),
fully_activated,
priv->default_device4);
}
nm_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6));
static NMDevice *
get_best_ip6_device (NMPolicy *self, gboolean fully_activated)
{
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
/* we prefer the current device in case of identical metric.
* Hence, try that one first.*/
best_device = NULL;
prev_device = addr_family == AF_INET
? (fully_activated ? priv->default_device4 : priv->activating_device4)
: (fully_activated ? priv->default_device6 : priv->activating_device6);
return nm_default_route_manager_ip6_get_best_device (nm_netns_get_default_route_manager (priv->netns),
nm_manager_get_devices (priv->manager),
fully_activated,
priv->default_device6);
for (iter = nm_manager_get_devices (priv->manager); iter; iter = iter->next) {
NMDevice *device = NM_DEVICE (iter->data);
NMDeviceState state;
const NMPObject *r;
NMConnection *connection;
guint32 metric;
gboolean is_fully_activated;
state = nm_device_get_state (device);
if ( state <= NM_DEVICE_STATE_DISCONNECTED
|| state >= NM_DEVICE_STATE_DEACTIVATING)
continue;
if (nm_device_sys_iface_state_is_external (device))
continue;
r = nm_device_get_best_default_route (device, addr_family);
if (r) {
/* XXX: the best route might have rt_source NM_IP_CONFIG_SOURCE_VPN,
* which means it was injected by a VPN, not added by device.
*
* In this case, is it really the best device? Why do we even need the best
* device?? */
metric = nm_utils_ip_route_metric_normalize (addr_family,
NMP_OBJECT_CAST_IP_ROUTE (r)->metric);
is_fully_activated = TRUE;
} else if ( !fully_activated
&& (connection = nm_device_get_applied_connection (device))
&& nm_utils_connection_has_default_route (connection, addr_family, NULL)) {
metric = nm_utils_ip_route_metric_normalize (addr_family,
nm_device_get_ip_route_metric (device, addr_family));
is_fully_activated = FALSE;
} else
continue;
if ( !best_device
|| (!best_is_fully_activated && is_fully_activated)
|| ( metric < best_metric
|| (metric == best_metric && device == prev_device))) {
best_device = device;
best_metric = metric;
best_is_fully_activated = is_fully_activated;
}
}
if ( !fully_activated
&& best_device
&& best_is_fully_activated) {
/* There's only a best activating device if the best device
* among all activating and already-activated devices is a
* still-activating one. */
return NULL;
}
return best_device;
}
static gboolean
@ -782,20 +837,83 @@ update_default_ac (NMPolicy *self,
set_active_func (best, TRUE);
}
static NMIP4Config *
get_best_ip4_config (NMPolicy *self,
gboolean ignore_never_default,
const char **out_ip_iface,
NMActiveConnection **out_ac,
NMDevice **out_device,
NMVpnConnection **out_vpn)
static gpointer
get_best_ip_config (NMPolicy *self,
int addr_family,
const char **out_ip_iface,
NMActiveConnection **out_ac,
NMDevice **out_device,
NMVpnConnection **out_vpn)
{
return nm_default_route_manager_ip4_get_best_config (nm_netns_get_default_route_manager (NM_POLICY_GET_PRIVATE (self)->netns),
ignore_never_default,
out_ip_iface,
out_ac,
out_device,
out_vpn);
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
NMDevice *device;
gpointer conf;
const GSList *iter;
nm_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6));
for (iter = nm_manager_get_active_connections (priv->manager); iter; iter = iter->next) {
NMActiveConnection *active = NM_ACTIVE_CONNECTION (iter->data);
NMVpnConnection *candidate;
NMVpnConnectionState vpn_state;
if (!NM_IS_VPN_CONNECTION (active))
continue;
candidate = NM_VPN_CONNECTION (active);
vpn_state = nm_vpn_connection_get_vpn_state (candidate);
if (vpn_state != NM_VPN_CONNECTION_STATE_ACTIVATED)
continue;
if (addr_family == AF_INET)
conf = nm_vpn_connection_get_ip4_config (candidate);
else
conf = nm_vpn_connection_get_ip6_config (candidate);
if (!conf)
continue;
if (addr_family == AF_INET) {
if (!nm_ip4_config_best_default_route_get (conf))
continue;
} else {
if (!nm_ip6_config_best_default_route_get (conf))
continue;
}
/* FIXME: in case of multiple VPN candidates, choose the one with the
* best metric. */
NM_SET_OUT (out_device, NULL);
NM_SET_OUT (out_vpn, candidate);
NM_SET_OUT (out_ac, active);
NM_SET_OUT (out_ip_iface, nm_vpn_connection_get_ip_iface (candidate, TRUE));
return conf;
}
device = get_best_ip_device (self, addr_family, TRUE);
if (device) {
NMActRequest *req;
if (addr_family == AF_INET)
conf = nm_device_get_ip4_config (device);
else
conf = nm_device_get_ip6_config (device);
req = nm_device_get_act_request (device);
if (conf && req) {
NM_SET_OUT (out_device, device);
NM_SET_OUT (out_vpn, NULL);
NM_SET_OUT (out_ac, NM_ACTIVE_CONNECTION (req));
NM_SET_OUT (out_ip_iface, nm_device_get_ip_iface (device));
return conf;
}
}
NM_SET_OUT (out_device, NULL);
NM_SET_OUT (out_vpn, NULL);
NM_SET_OUT (out_ac, NULL);
NM_SET_OUT (out_ip_iface, NULL);
return NULL;
}
static void
@ -806,7 +924,7 @@ update_ip4_dns (NMPolicy *self, NMDnsManager *dns_mgr)
NMVpnConnection *vpn = NULL;
NMDnsIPConfigType dns_type = NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE;
ip4_config = get_best_ip4_config (self, TRUE, &ip_iface, NULL, NULL, &vpn);
ip4_config = get_best_ip_config (self, AF_INET, &ip_iface, NULL, NULL, &vpn);
if (ip4_config) {
if (vpn)
dns_type = NM_DNS_IP_CONFIG_TYPE_VPN;
@ -830,7 +948,7 @@ update_ip4_routing (NMPolicy *self, gboolean force_update)
/* Note that we might have an IPv4 VPN tunneled over an IPv6-only device,
* so we can get (vpn != NULL && best == NULL).
*/
if (!get_best_ip4_config (self, FALSE, &ip_iface, &best_ac, &best, &vpn)) {
if (!get_best_ip_config (self, AF_INET, &ip_iface, &best_ac, &best, &vpn)) {
if (nm_clear_g_object (&priv->default_device4)) {
_LOGt (LOGD_DNS, "set-default-device-4: %p", NULL);
_notify (self, PROP_DEFAULT_IP4_DEVICE);
@ -873,22 +991,6 @@ update_ip4_routing (NMPolicy *self, gboolean force_update)
_notify (self, PROP_DEFAULT_IP4_DEVICE);
}
static NMIP6Config *
get_best_ip6_config (NMPolicy *self,
gboolean ignore_never_default,
const char **out_ip_iface,
NMActiveConnection **out_ac,
NMDevice **out_device,
NMVpnConnection **out_vpn)
{
return nm_default_route_manager_ip6_get_best_config (nm_netns_get_default_route_manager (NM_POLICY_GET_PRIVATE (self)->netns),
ignore_never_default,
out_ip_iface,
out_ac,
out_device,
out_vpn);
}
static void
update_ip6_dns_delegation (NMPolicy *self)
{
@ -912,7 +1014,7 @@ update_ip6_dns (NMPolicy *self, NMDnsManager *dns_mgr)
NMVpnConnection *vpn = NULL;
NMDnsIPConfigType dns_type = NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE;
ip6_config = get_best_ip6_config (self, TRUE, &ip_iface, NULL, NULL, &vpn);
ip6_config = get_best_ip_config (self, AF_INET6, &ip_iface, NULL, NULL, &vpn);
if (ip6_config) {
if (vpn)
dns_type = NM_DNS_IP_CONFIG_TYPE_VPN;
@ -954,7 +1056,7 @@ update_ip6_routing (NMPolicy *self, gboolean force_update)
/* Note that we might have an IPv6 VPN tunneled over an IPv4-only device,
* so we can get (vpn != NULL && best == NULL).
*/
if (!get_best_ip6_config (self, FALSE, &ip_iface, &best_ac, &best, &vpn)) {
if (!get_best_ip_config (self, AF_INET6, &ip_iface, &best_ac, &best, &vpn)) {
if (nm_clear_g_object (&priv->default_device6)) {
_LOGt (LOGD_DNS, "set-default-device-6: %p", NULL);
_notify (self, PROP_DEFAULT_IP6_DEVICE);
@ -1024,8 +1126,8 @@ check_activating_devices (NMPolicy *self)
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
NMDevice *best4, *best6 = NULL;
best4 = get_best_ip4_device (self, FALSE);
best6 = get_best_ip6_device (self, FALSE);
best4 = get_best_ip_device (self, AF_INET, FALSE);
best6 = get_best_ip_device (self, AF_INET6, FALSE);
g_object_freeze_notify (G_OBJECT (self));

View file

@ -38,7 +38,6 @@ typedef struct _NMConfigData NMConfigData;
typedef struct _NMArpingManager NMArpingManager;
typedef struct _NMConnectionProvider NMConnectionProvider;
typedef struct _NMConnectivity NMConnectivity;
typedef struct _NMDefaultRouteManager NMDefaultRouteManager;
typedef struct _NMDevice NMDevice;
typedef struct _NMDhcp4Config NMDhcp4Config;
typedef struct _NMDhcp6Config NMDhcp6Config;

View file

@ -3697,11 +3697,6 @@ nm_platform_ip_route_sync (NMPlatform *self,
for (i = 0; i < plat_routes->len; i++) {
plat_o = plat_routes->pdata[i];
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (NMP_OBJECT_CAST_IP_ROUTE (plat_o))) {
/* don't delete default routes. */
continue;
}
if ( !routes_idx
|| !g_hash_table_lookup (routes_idx, plat_o)) {
if (!nm_platform_ip_route_delete (self, plat_o)) {

View file

@ -44,7 +44,6 @@
#include "settings/nm-agent-manager.h"
#include "nm-core-internal.h"
#include "nm-pacrunner-manager.h"
#include "nm-default-route-manager.h"
#include "nm-firewall-manager.h"
#include "nm-config.h"
#include "nm-vpn-plugin-info.h"
@ -498,9 +497,6 @@ _set_vpn_state (NMVpnConnection *self,
dispatcher_cleanup (self);
nm_default_route_manager_ip4_update_default_route (nm_netns_get_default_route_manager (priv->netns), self);
nm_default_route_manager_ip6_update_default_route (nm_netns_get_default_route_manager (priv->netns), self);
/* The connection gets destroyed by the VPN manager when it enters the
* disconnected/failed state, but we need to keep it around for a bit
* to send out signals and handle the dispatcher. So ref it.
@ -1167,9 +1163,6 @@ nm_vpn_connection_apply_config (NMVpnConnection *self)
nm_platform_link_set_mtu (nm_netns_get_platform (priv->netns), priv->ip_ifindex, priv->mtu);
}
nm_default_route_manager_ip4_update_default_route (nm_netns_get_default_route_manager (priv->netns), self);
nm_default_route_manager_ip6_update_default_route (nm_netns_get_default_route_manager (priv->netns), self);
_LOGI ("VPN connection: (IP Config Get) complete");
if (priv->vpn_state < STATE_PRE_UP)
_set_vpn_state (self, STATE_PRE_UP, NM_ACTIVE_CONNECTION_STATE_REASON_NONE, FALSE);
@ -1596,6 +1589,18 @@ nm_vpn_connection_ip4_config_get (NMVpnConnection *self, GVariant *dict)
nm_connection_get_setting_ip4_config (_get_applied_connection (self)),
route_metric);
if (!nm_ip4_config_get_never_default (config)) {
const NMPlatformIP4Route r = {
.ifindex = ip_ifindex,
.rt_source = NM_IP_CONFIG_SOURCE_VPN,
.gateway = nm_ip4_config_get_gateway (config),
.metric = route_metric,
.mss = nm_ip4_config_get_mss (config),
};
nm_ip4_config_add_route (config, &r, NULL);
}
if (priv->ip4_config) {
nm_ip4_config_replace (priv->ip4_config, config, NULL);
g_object_unref (config);
@ -1758,6 +1763,18 @@ next:
nm_connection_get_setting_ip6_config (_get_applied_connection (self)),
route_metric);
if (!nm_ip6_config_get_never_default (config)) {
const NMPlatformIP6Route r = {
.ifindex = ip_ifindex,
.rt_source = NM_IP_CONFIG_SOURCE_VPN,
.gateway = *(nm_ip6_config_get_gateway (config) ?: &in6addr_any),
.metric = route_metric,
.mss = nm_ip6_config_get_mss (config),
};
nm_ip6_config_add_route (config, &r, NULL);
}
if (priv->ip6_config) {
nm_ip6_config_replace (priv->ip6_config, config, NULL);
g_object_unref (config);