summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2017-10-04 15:21:21 +0200
committerThomas Haller <thaller@redhat.com>2017-10-09 22:57:04 +0200
commit1007b40441a9b85a150ec8f2a490d579ecbebbe8 (patch)
tree013d69c041917d570d0e4ce5e3a00b1ba3115469
parent2bdfc092d40daaf1af87a4cc2285caa63f35e9d3 (diff)
downloadNetworkManager-th/policy-routing-pt2-rh1436531.tar.gz
core: rework tracking of gateway/default-route in ip-configth/policy-routing-pt2-rh1436531
Instead of having 3 properties @gateway, @never_default and @has_gateway on NMIP4Config/NMIP6Config that determine the default-route, track the default-route as a regular route. The gateway setting is the configuration knob for the default-route. Since an NMIP4Config/NMIP6Config instance only has one gateway property, it cannot track more then one default-routes (see related bug rh#1445417). Especially with policy routing, it might be interesting to configure a default-route in multiple tables. Also, later it might be interesting to allow adding default-routes as regular static routes in a connection, so that the user can configure additional route parameters for the default-route or add default-routes in multiple tables. With this patch, default-routes now have a rt_source property according to their origin. Also, the previous commits of this branch broke handling of the default-route :) . That should be working now again.
-rw-r--r--src/devices/adsl/nm-device-adsl.c9
-rw-r--r--src/devices/nm-device-ethernet.c11
-rw-r--r--src/devices/nm-device-ppp.c18
-rw-r--r--src/devices/nm-device.c445
-rw-r--r--src/devices/wwan/nm-modem-broadband.c43
-rw-r--r--src/devices/wwan/nm-modem-ofono.c57
-rw-r--r--src/devices/wwan/nm-modem.c94
-rw-r--r--src/devices/wwan/nm-modem.h15
-rw-r--r--src/dhcp/nm-dhcp-dhclient-utils.c16
-rw-r--r--src/dhcp/nm-dhcp-dhclient-utils.h2
-rw-r--r--src/dhcp/nm-dhcp-dhclient.c17
-rw-r--r--src/dhcp/nm-dhcp-systemd.c19
-rw-r--r--src/dhcp/nm-dhcp-utils.c26
-rw-r--r--src/dhcp/tests/test-dhcp-dhclient.c13
-rw-r--r--src/dhcp/tests/test-dhcp-utils.c51
-rw-r--r--src/dns/nm-dns-systemd-resolved.c40
-rw-r--r--src/dnsmasq/nm-dnsmasq-manager.c2
-rw-r--r--src/ndisc/nm-ndisc.h5
-rw-r--r--src/nm-core-utils.h9
-rw-r--r--src/nm-dispatcher.c14
-rw-r--r--src/nm-iface-helper.c35
-rw-r--r--src/nm-ip4-config.c376
-rw-r--r--src/nm-ip4-config.h50
-rw-r--r--src/nm-ip6-config.c386
-rw-r--r--src/nm-ip6-config.h35
-rw-r--r--src/nm-types.h3
-rw-r--r--src/ppp/nm-ppp-manager-call.c16
-rw-r--r--src/ppp/nm-ppp-manager-call.h7
-rw-r--r--src/ppp/nm-ppp-manager.c94
-rw-r--r--src/ppp/nm-ppp-manager.h2
-rw-r--r--src/ppp/nm-ppp-plugin-api.h6
-rw-r--r--src/tests/test-ip4-config.c22
-rw-r--r--src/tests/test-ip6-config.c6
-rw-r--r--src/vpn/nm-vpn-connection.c51
34 files changed, 1100 insertions, 895 deletions
diff --git a/src/devices/adsl/nm-device-adsl.c b/src/devices/adsl/nm-device-adsl.c
index fe622bdf8b..feeb243d02 100644
--- a/src/devices/adsl/nm-device-adsl.c
+++ b/src/devices/adsl/nm-device-adsl.c
@@ -474,6 +474,15 @@ act_stage3_ip4_config_start (NMDevice *device,
}
priv->ppp_manager = nm_ppp_manager_create (ppp_iface, &err);
+
+ if (priv->ppp_manager) {
+ nm_ppp_manager_set_route_parameters (priv->ppp_manager,
+ nm_device_get_route_table (device, AF_INET, TRUE),
+ nm_device_get_route_metric (device, AF_INET),
+ nm_device_get_route_table (device, AF_INET6, TRUE),
+ nm_device_get_route_metric (device, AF_INET6));
+ }
+
if ( !priv->ppp_manager
|| !nm_ppp_manager_start (priv->ppp_manager, req,
nm_setting_adsl_get_username (s_adsl),
diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c
index cc46a65837..ca30a1e8e7 100644
--- a/src/devices/nm-device-ethernet.c
+++ b/src/devices/nm-device-ethernet.c
@@ -999,6 +999,7 @@ ppp_ip4_config (NMPPPManager *ppp_manager,
static NMActStageReturn
pppoe_stage3_ip4_config_start (NMDeviceEthernet *self, NMDeviceStateReason *out_failure_reason)
{
+ NMDevice *device = NM_DEVICE (self);
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
NMSettingPppoe *s_pppoe;
NMActRequest *req;
@@ -1010,9 +1011,17 @@ pppoe_stage3_ip4_config_start (NMDeviceEthernet *self, NMDeviceStateReason *out_
s_pppoe = (NMSettingPppoe *) nm_device_get_applied_setting ((NMDevice *) self, NM_TYPE_SETTING_PPPOE);
g_return_val_if_fail (s_pppoe, NM_ACT_STAGE_RETURN_FAILURE);
- priv->ppp_manager = nm_ppp_manager_create (nm_device_get_iface (NM_DEVICE (self)),
+ priv->ppp_manager = nm_ppp_manager_create (nm_device_get_iface (device),
&err);
+ if (priv->ppp_manager) {
+ nm_ppp_manager_set_route_parameters (priv->ppp_manager,
+ nm_device_get_route_table (device, AF_INET, TRUE),
+ nm_device_get_route_metric (device, AF_INET),
+ nm_device_get_route_table (device, AF_INET6, TRUE),
+ nm_device_get_route_metric (device, AF_INET6));
+ }
+
if ( !priv->ppp_manager
|| !nm_ppp_manager_start (priv->ppp_manager, req,
nm_setting_pppoe_get_username (s_pppoe),
diff --git a/src/devices/nm-device-ppp.c b/src/devices/nm-device-ppp.c
index 81db1dc0f7..09b25f50e2 100644
--- a/src/devices/nm-device-ppp.c
+++ b/src/devices/nm-device-ppp.c
@@ -138,7 +138,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason)
NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE (self);
NMSettingPppoe *s_pppoe;
NMActRequest *req;
- GError *err = NULL;
+ GError *error = NULL;
req = nm_device_get_act_request (NM_DEVICE (self));
g_return_val_if_fail (req, NM_ACT_STAGE_RETURN_FAILURE);
@@ -149,14 +149,22 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason)
g_clear_object (&priv->pending_ip4_config);
nm_clear_g_free (&priv->pending_ifname);
- priv->ppp_manager = nm_ppp_manager_create (nm_setting_pppoe_get_parent (s_pppoe), &err);
+ priv->ppp_manager = nm_ppp_manager_create (nm_setting_pppoe_get_parent (s_pppoe), &error);
+
+ if (priv->ppp_manager) {
+ nm_ppp_manager_set_route_parameters (priv->ppp_manager,
+ nm_device_get_route_table (device, AF_INET, TRUE),
+ nm_device_get_route_metric (device, AF_INET),
+ nm_device_get_route_table (device, AF_INET6, TRUE),
+ nm_device_get_route_metric (device, AF_INET6));
+ }
if ( !priv->ppp_manager
|| !nm_ppp_manager_start (priv->ppp_manager, req,
nm_setting_pppoe_get_username (s_pppoe),
- 30, 0, &err)) {
- _LOGW (LOGD_DEVICE | LOGD_PPP, "PPPoE failed to start: %s", err->message);
- g_error_free (err);
+ 30, 0, &error)) {
+ _LOGW (LOGD_DEVICE | LOGD_PPP, "PPPoE failed to start: %s", error->message);
+ g_error_free (error);
g_clear_object (&priv->ppp_manager);
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 8165c3fcf0..fd6f840a75 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -339,6 +339,9 @@ typedef struct _NMDevicePrivate {
bool v4_commit_first_time:1;
bool v6_commit_first_time:1;
+ bool default_route_metric_penalty_ip4_has:1;
+ bool default_route_metric_penalty_ip6_has:1;
+
NMDeviceSysIfaceState sys_iface_state:2;
bool v4_route_table_initalized:1;
@@ -366,11 +369,6 @@ typedef struct _NMDevicePrivate {
NMIP4Config * wwan_ip4_config; /* WWAN configuration */
GSList * vpn4_configs; /* VPNs which use this device */
- 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;
@@ -1665,24 +1663,35 @@ _get_route_metric_default (NMDevice *self)
return 11000;
}
-static guint32
-route_metric_with_penalty (NMDevice *self, guint32 metric)
+static gboolean
+default_route_metric_penalty_detect (NMDevice *self)
{
#if WITH_CONCHECK
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
- const guint32 PENALTY = 20000;
-
- /* Beware: for IPv6, a metric of 0 effectively means 1024.
- * Only pass a normalized IPv6 metric (nm_utils_ip6_route_metric_normalize). */
+ /* currently we don't differentiate between IPv4 and IPv6 when detecting
+ * connectivity. */
if ( priv->connectivity_state != NM_CONNECTIVITY_FULL
- && nm_connectivity_check_enabled (nm_connectivity_get ())) {
- if (metric >= G_MAXUINT32 - PENALTY)
- return G_MAXUINT32;
- return metric + PENALTY;
+ && nm_connectivity_check_enabled (nm_connectivity_get ())) {
+ return TRUE;
}
#endif
- return metric;
+
+ return FALSE;
+}
+
+static guint32
+default_route_metric_penalty_get (NMDevice *self, int addr_family)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+
+ nm_assert_addr_family (addr_family);
+
+ if ( addr_family == AF_INET
+ ? priv->default_route_metric_penalty_ip4_has
+ : priv->default_route_metric_penalty_ip6_has)
+ return 20000;
+ return 0;
}
guint32
@@ -1736,13 +1745,17 @@ nm_device_get_route_table (NMDevice *self,
int addr_family,
gboolean fallback_main)
{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+ NMDevicePrivate *priv;
NMConnection *connection;
NMSettingIPConfig *s_ip;
guint32 route_table = 0;
nm_assert_addr_family (addr_family);
+ g_return_val_if_fail (NM_IS_DEVICE (self), RT_TABLE_MAIN);
+
+ priv = NM_DEVICE_GET_PRIVATE (self);
+
/* the route table setting affects how we sync routes. We shall
* not change it while the device is active, hence, cache it. */
if (addr_family == AF_INET) {
@@ -1801,24 +1814,14 @@ nm_device_get_best_default_route (NMDevice *self,
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
- /* 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;
+ return priv->ip4_config ? nm_ip4_config_best_default_route_get (priv->ip4_config) : NULL;
case AF_INET6:
- return (priv->ip6_config ? nm_ip6_config_best_default_route_get (priv->ip6_config) : NULL)
- ?: priv->default_route6;
+ return priv->ip6_config ? nm_ip6_config_best_default_route_get (priv->ip6_config) : NULL;
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;
+ ?: (priv->ip6_config ? nm_ip6_config_best_default_route_get (priv->ip6_config) : NULL);
default:
g_return_val_if_reached (NULL);
}
@@ -5767,15 +5770,11 @@ ip4_config_merge_and_apply (NMDevice *self,
NMConnection *connection;
gboolean success;
NMIP4Config *composite;
- const guint32 default_route_metric = nm_device_get_route_metric (self, AF_INET);
- guint32 gateway;
- gboolean connection_has_default_route, connection_is_never_default;
gboolean ignore_auto_routes = FALSE;
gboolean ignore_auto_dns = FALSE;
+ gboolean ignore_default_routes = FALSE;
GSList *iter;
- NMPlatformIP4Route default_route;
gs_unref_ptrarray GPtrArray *ip4_dev_route_blacklist = NULL;
- gboolean add_default_route = TRUE;
/* Apply ignore-auto-routes and ignore-auto-dns settings */
connection = nm_device_get_applied_connection (self);
@@ -5785,6 +5784,7 @@ 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);
+ ignore_default_routes = nm_setting_ip_config_get_never_default (s_ip4);
}
}
@@ -5797,17 +5797,22 @@ ip4_config_merge_and_apply (NMDevice *self,
ensure_con_ip4_config (self);
}
+ if (commit)
+ priv->default_route_metric_penalty_ip4_has = default_route_metric_penalty_detect (self);
+
if (priv->dev_ip4_config) {
nm_ip4_config_merge (composite, priv->dev_ip4_config,
(ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0)
- | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0));
+ | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0)
+ | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0),
+ default_route_metric_penalty_get (self, AF_INET));
}
for (iter = priv->vpn4_configs; iter; iter = iter->next)
- nm_ip4_config_merge (composite, iter->data, NM_IP_CONFIG_MERGE_DEFAULT);
+ nm_ip4_config_merge (composite, iter->data, NM_IP_CONFIG_MERGE_DEFAULT, 0);
if (priv->ext_ip4_config)
- nm_ip4_config_merge (composite, priv->ext_ip4_config, NM_IP_CONFIG_MERGE_DEFAULT);
+ nm_ip4_config_merge (composite, priv->ext_ip4_config, NM_IP_CONFIG_MERGE_DEFAULT, 0);
/* Merge WWAN config *last* to ensure modem-given settings overwrite
* any external stuff set by pppd or other scripts.
@@ -5815,87 +5820,23 @@ ip4_config_merge_and_apply (NMDevice *self,
if (priv->wwan_ip4_config) {
nm_ip4_config_merge (composite, priv->wwan_ip4_config,
(ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0)
- | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0));
+ | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0)
+ | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0),
+ default_route_metric_penalty_get (self, AF_INET));
}
/* Merge user overrides into the composite config. For assumed connections,
* con_ip4_config is empty. */
- if (priv->con_ip4_config)
- nm_ip4_config_merge (composite, priv->con_ip4_config, NM_IP_CONFIG_MERGE_DEFAULT);
-
- /* Add the default route... */
-
- if (!commit) {
- /* during a non-commit event, we always pickup whatever is configured. */
- goto END_ADD_DEFAULT_ROUTE;
- }
-
- /* for external connections, we always pickup whatever is configured. */
- if (nm_device_sys_iface_state_is_external (self))
- goto END_ADD_DEFAULT_ROUTE;
-
- connection_has_default_route
- = nm_utils_connection_has_default_route (connection, AF_INET, &connection_is_never_default);
-
- if ( !priv->v4_commit_first_time
- && connection_is_never_default) {
- /* If the connection is explicitly configured as never-default, we enforce the (absence of the)
- * default-route only once. That allows the user to configure a connection as never-default,
- * but he can add default routes externally (via a dispatcher script) and NM will not interfere. */
- goto END_ADD_DEFAULT_ROUTE;
- }
-
- nm_clear_nmp_object (&priv->default_route4);
- nm_clear_nmp_object (&priv->default_routegw4);
-
- if (!connection_has_default_route)
- goto END_ADD_DEFAULT_ROUTE;
-
- if (!nm_ip4_config_get_num_addresses (composite)) {
- /* without addresses we can have no default route. */
- goto END_ADD_DEFAULT_ROUTE;
- }
-
- gateway = nm_ip4_config_get_gateway (composite);
- if ( !nm_ip4_config_has_gateway (composite)
- && nm_device_get_device_type (self) != NM_DEVICE_TYPE_MODEM)
- goto END_ADD_DEFAULT_ROUTE;
-
- add_default_route = FALSE;
-
- memset (&default_route, 0, sizeof (default_route));
- default_route.rt_source = NM_IP_CONFIG_SOURCE_USER;
- default_route.gateway = gateway;
- default_route.table_coerced = nm_platform_route_table_coerce (nm_device_get_route_table (self, AF_INET, TRUE));
- default_route.metric = route_metric_with_penalty (self, default_route_metric);
- 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 */
- 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 (add_default_route) {
- if (priv->default_route4)
- nm_ip4_config_add_route (composite, NMP_OBJECT_CAST_IP4_ROUTE (priv->default_route4), NULL);
- if (priv->default_routegw4)
- nm_ip4_config_add_route (composite, NMP_OBJECT_CAST_IP4_ROUTE (priv->default_routegw4), NULL);
+ if (priv->con_ip4_config) {
+ nm_ip4_config_merge (composite, priv->con_ip4_config, NM_IP_CONFIG_MERGE_DEFAULT,
+ default_route_metric_penalty_get (self, AF_INET));
}
if (commit) {
- nm_ip4_config_add_device_routes (composite,
- nm_device_get_route_table (self, AF_INET, TRUE),
- default_route_metric,
- &ip4_dev_route_blacklist);
+ nm_ip4_config_add_dependent_routes (composite,
+ nm_device_get_route_table (self, AF_INET, TRUE),
+ nm_device_get_route_metric (self, AF_INET),
+ &ip4_dev_route_blacklist);
}
if (commit) {
@@ -6481,15 +6422,11 @@ ip6_config_merge_and_apply (NMDevice *self,
NMConnection *connection;
gboolean success;
NMIP6Config *composite;
- const guint32 default_route_metric = nm_device_get_route_metric (self, AF_INET6);
- 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 ignore_default_routes = FALSE;
const char *token = NULL;
GSList *iter;
- NMPlatformIP6Route default_route;
- gboolean add_default_route = TRUE;
/* Apply ignore-auto-routes and ignore-auto-dns settings */
connection = nm_device_get_applied_connection (self);
@@ -6501,6 +6438,7 @@ ip6_config_merge_and_apply (NMDevice *self,
ignore_auto_routes = nm_setting_ip_config_get_ignore_auto_routes (s_ip6);
ignore_auto_dns = nm_setting_ip_config_get_ignore_auto_dns (s_ip6);
+ ignore_default_routes = nm_setting_ip_config_get_never_default (s_ip6);
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);
@@ -6520,23 +6458,30 @@ ip6_config_merge_and_apply (NMDevice *self,
ensure_con_ip6_config (self);
}
+ if (commit)
+ priv->default_route_metric_penalty_ip6_has = default_route_metric_penalty_detect (self);
+
/* Merge all the IP configs into the composite config */
if (priv->ac_ip6_config) {
nm_ip6_config_merge (composite, priv->ac_ip6_config,
(ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0)
- | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0));
+ | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0)
+ | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0),
+ default_route_metric_penalty_get (self, AF_INET6));
}
if (priv->dhcp6.ip6_config) {
nm_ip6_config_merge (composite, priv->dhcp6.ip6_config,
(ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0)
- | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0));
+ | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0)
+ | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0),
+ default_route_metric_penalty_get (self, AF_INET6));
}
for (iter = priv->vpn6_configs; iter; iter = iter->next)
- nm_ip6_config_merge (composite, iter->data, NM_IP_CONFIG_MERGE_DEFAULT);
+ nm_ip6_config_merge (composite, iter->data, NM_IP_CONFIG_MERGE_DEFAULT, 0);
if (priv->ext_ip6_config)
- nm_ip6_config_merge (composite, priv->ext_ip6_config, NM_IP_CONFIG_MERGE_DEFAULT);
+ nm_ip6_config_merge (composite, priv->ext_ip6_config, NM_IP_CONFIG_MERGE_DEFAULT, 0);
/* Merge WWAN config *last* to ensure modem-given settings overwrite
* any external stuff set by pppd or other scripts.
@@ -6544,7 +6489,9 @@ ip6_config_merge_and_apply (NMDevice *self,
if (priv->wwan_ip6_config) {
nm_ip6_config_merge (composite, priv->wwan_ip6_config,
(ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0)
- | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0));
+ | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0)
+ | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0),
+ default_route_metric_penalty_get (self, AF_INET6));
}
if (priv->rt6_temporary_not_available) {
@@ -6561,78 +6508,15 @@ ip6_config_merge_and_apply (NMDevice *self,
/* Merge user overrides into the composite config. For assumed connections,
* con_ip6_config is empty. */
- if (priv->con_ip6_config)
- nm_ip6_config_merge (composite, priv->con_ip6_config, NM_IP_CONFIG_MERGE_DEFAULT);
-
- /* Add the default route... */
-
- if (!commit) {
- /* during a non-commit event, we always pickup whatever is configured. */
- goto END_ADD_DEFAULT_ROUTE;
- }
-
- /* for external connections, we always pickup whatever is configured. */
- if (nm_device_sys_iface_state_is_external (self))
- goto END_ADD_DEFAULT_ROUTE;
-
- connection_has_default_route
- = nm_utils_connection_has_default_route (connection, AF_INET6, &connection_is_never_default);
-
- if ( !priv->v6_commit_first_time
- && connection_is_never_default) {
- /* If the connection is explicitly configured as never-default, we enforce the (absence of the)
- * default-route only once. That allows the user to configure a connection as never-default,
- * but he can add default routes externally (via a dispatcher script) and NM will not interfere. */
- goto END_ADD_DEFAULT_ROUTE;
- }
-
- nm_clear_nmp_object (&priv->default_route6);
- nm_clear_nmp_object (&priv->default_routegw6);
-
- if (!connection_has_default_route)
- goto END_ADD_DEFAULT_ROUTE;
-
- if (!nm_ip6_config_get_num_addresses (composite)) {
- /* without addresses we can have no default route. */
- goto END_ADD_DEFAULT_ROUTE;
- }
-
- gateway = nm_ip6_config_get_gateway (composite);
- if (!gateway)
- goto END_ADD_DEFAULT_ROUTE;
-
- add_default_route = FALSE;
-
- memset (&default_route, 0, sizeof (default_route));
- default_route.rt_source = NM_IP_CONFIG_SOURCE_USER;
- default_route.gateway = *gateway;
- default_route.table_coerced = nm_platform_route_table_coerce (nm_device_get_route_table (self, AF_INET6, TRUE));
- default_route.metric = route_metric_with_penalty (self, default_route_metric);
- nm_clear_nmp_object (&priv->default_route6);
- nm_ip6_config_add_route (composite, &default_route, &priv->default_route6);
-
- if (!nm_ip6_config_get_direct_route_for_host (composite, gateway)) {
- /* add a direct route to the gateway */
- 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 (add_default_route) {
- if (priv->default_route6)
- nm_ip6_config_add_route (composite, NMP_OBJECT_CAST_IP6_ROUTE (priv->default_route6), NULL);
- if (priv->default_routegw6)
- nm_ip6_config_add_route (composite, NMP_OBJECT_CAST_IP6_ROUTE (priv->default_routegw6), NULL);
+ if (priv->con_ip6_config) {
+ nm_ip6_config_merge (composite, priv->con_ip6_config, NM_IP_CONFIG_MERGE_DEFAULT,
+ default_route_metric_penalty_get (self, AF_INET6));
}
if (commit) {
- nm_ip6_config_add_device_routes (composite,
- nm_device_get_route_table (self, AF_INET6, TRUE),
- default_route_metric);
+ nm_ip6_config_add_dependent_routes (composite,
+ nm_device_get_route_table (self, AF_INET6, TRUE),
+ nm_device_get_route_metric (self, AF_INET6));
}
/* Allow setting MTU etc */
@@ -7477,14 +7361,6 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in
if (!priv->ac_ip6_config)
priv->ac_ip6_config = _ip6_config_new (self);
- if (changed & NM_NDISC_CONFIG_GATEWAYS) {
- /* Use the first gateway as ordered in neighbor discovery cache. */
- if (rdata->gateways_n)
- nm_ip6_config_set_gateway (priv->ac_ip6_config, &rdata->gateways[0].address);
- else
- nm_ip6_config_set_gateway (priv->ac_ip6_config, NULL);
- }
-
if (changed & NM_NDISC_CONFIG_ADDRESSES) {
guint8 plen;
guint32 ifa_flags;
@@ -7510,8 +7386,11 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in
ifa_flags);
}
- if (changed & NM_NDISC_CONFIG_ROUTES) {
+ if (NM_FLAGS_ANY (changed, NM_NDISC_CONFIG_ROUTES
+ | NM_NDISC_CONFIG_GATEWAYS)) {
nm_ip6_config_reset_routes_ndisc (priv->ac_ip6_config,
+ rdata->gateways,
+ rdata->gateways_n,
rdata->routes,
rdata->routes_n,
nm_device_get_route_table (self, AF_INET6, TRUE),
@@ -9016,8 +8895,6 @@ _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);
@@ -9035,8 +8912,6 @@ _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);
@@ -10631,7 +10506,7 @@ nm_device_start_ip_check (NMDevice *self)
NMSettingConnection *s_con;
guint timeout = 0;
const char *ping_binary = NULL;
- char buf[INET6_ADDRSTRLEN] = { 0 };
+ char buf[NM_UTILS_INET_ADDRSTRLEN];
NMLogDomain log_domain = LOGD_IP4;
/* Shouldn't be any active ping here, since IP_CHECK happens after the
@@ -10650,25 +10525,24 @@ nm_device_start_ip_check (NMDevice *self)
g_assert (s_con);
timeout = nm_setting_connection_get_gateway_ping_timeout (s_con);
+ buf[0] = '\0';
if (timeout) {
- if (priv->ip4_config && priv->ip4_state == IP_DONE) {
- guint gw = 0;
+ const NMPObject *gw;
- ping_binary = nm_utils_find_helper ("ping", "/usr/bin/ping", NULL);
- log_domain = LOGD_IP4;
-
- gw = nm_ip4_config_get_gateway (priv->ip4_config);
- if (gw && !inet_ntop (AF_INET, &gw, buf, sizeof (buf)))
- buf[0] = '\0';
+ if (priv->ip4_config && priv->ip4_state == IP_DONE) {
+ gw = nm_ip4_config_best_default_route_get (priv->ip4_config);
+ if (gw) {
+ nm_utils_inet4_ntop (NMP_OBJECT_CAST_IP4_ROUTE (gw)->gateway, buf);
+ ping_binary = nm_utils_find_helper ("ping", "/usr/bin/ping", NULL);
+ log_domain = LOGD_IP4;
+ }
} else if (priv->ip6_config && priv->ip6_state == IP_DONE) {
- const struct in6_addr *gw = NULL;
-
- ping_binary = nm_utils_find_helper ("ping6", "/usr/bin/ping6", NULL);
- log_domain = LOGD_IP6;
-
- gw = nm_ip6_config_get_gateway (priv->ip6_config);
- if (gw && !inet_ntop (AF_INET6, gw, buf, sizeof (buf)))
- buf[0] = '\0';
+ gw = nm_ip6_config_best_default_route_get (priv->ip6_config);
+ if (gw) {
+ nm_utils_inet6_ntop (&NMP_OBJECT_CAST_IP6_ROUTE (gw)->gateway, buf);
+ ping_binary = nm_utils_find_helper ("ping6", "/usr/bin/ping6", NULL);
+ log_domain = LOGD_IP6;
+ }
}
}
@@ -10884,12 +10758,18 @@ find_ip4_lease_config (NMDevice *self,
for (liter = leases; liter && !found; liter = liter->next) {
NMIP4Config *lease_config = liter->data;
const NMPlatformIP4Address *address = nm_ip4_config_get_first_address (lease_config);
- guint32 gateway = nm_ip4_config_get_gateway (lease_config);
+ const NMPObject *gw1, *gw2;
g_assert (address);
if (!nm_ip4_config_address_exists (ext_ip4_config, address))
continue;
- if (gateway != nm_ip4_config_get_gateway (ext_ip4_config))
+ gw1 = nm_ip4_config_best_default_route_get (lease_config);
+ if (!gw1)
+ continue;
+ gw2 = nm_ip4_config_best_default_route_get (ext_ip4_config);
+ if (!gw2)
+ continue;
+ if (NMP_OBJECT_CAST_IP4_ROUTE (gw1)->gateway != NMP_OBJECT_CAST_IP4_ROUTE (gw2)->gateway)
continue;
found = g_object_ref (lease_config);
}
@@ -10999,37 +10879,39 @@ update_ext_ip_config (NMDevice *self, int addr_family, gboolean initial, gboolea
* (addresses,routes) that is no longer present externally from the internal
* config. This way, we don't re-add addresses that were manually removed
* by the user. */
- if (priv->con_ip4_config)
- nm_ip4_config_intersect (priv->con_ip4_config, priv->ext_ip4_config);
- if (priv->dev_ip4_config)
- nm_ip4_config_intersect (priv->dev_ip4_config, priv->ext_ip4_config);
- if (priv->wwan_ip4_config)
- nm_ip4_config_intersect (priv->wwan_ip4_config, priv->ext_ip4_config);
+ if (priv->con_ip4_config) {
+ nm_ip4_config_intersect (priv->con_ip4_config, priv->ext_ip4_config,
+ default_route_metric_penalty_get (self, AF_INET));
+ }
+ if (priv->dev_ip4_config) {
+ nm_ip4_config_intersect (priv->dev_ip4_config, priv->ext_ip4_config,
+ default_route_metric_penalty_get (self, AF_INET));
+ }
+ if (priv->wwan_ip4_config) {
+ nm_ip4_config_intersect (priv->wwan_ip4_config, priv->ext_ip4_config,
+ default_route_metric_penalty_get (self, AF_INET));
+ }
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);
+ nm_ip4_config_intersect (iter->data, priv->ext_ip4_config, 0);
}
/* Remove parts from ext_ip4_config to only contain the information that
* was configured externally -- we already have the same configuration from
* internal origins. */
- if (priv->con_ip4_config)
- nm_ip4_config_subtract (priv->ext_ip4_config, priv->con_ip4_config);
- if (priv->dev_ip4_config)
- nm_ip4_config_subtract (priv->ext_ip4_config, priv->dev_ip4_config);
- if (priv->wwan_ip4_config)
- nm_ip4_config_subtract (priv->ext_ip4_config, priv->wwan_ip4_config);
+ if (priv->con_ip4_config) {
+ nm_ip4_config_subtract (priv->ext_ip4_config, priv->con_ip4_config,
+ default_route_metric_penalty_get (self, AF_INET));
+ }
+ if (priv->dev_ip4_config) {
+ nm_ip4_config_subtract (priv->ext_ip4_config, priv->dev_ip4_config,
+ default_route_metric_penalty_get (self, AF_INET));
+ }
+ if (priv->wwan_ip4_config) {
+ nm_ip4_config_subtract (priv->ext_ip4_config, priv->wwan_ip4_config,
+ default_route_metric_penalty_get (self, AF_INET));
+ }
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);
+ nm_ip4_config_subtract (priv->ext_ip4_config, iter->data, 0);
}
} else {
@@ -11051,41 +10933,47 @@ update_ext_ip_config (NMDevice *self, int addr_family, gboolean initial, gboolea
* (addresses,routes) that is no longer present externally from the internal
* config. This way, we don't re-add addresses that were manually removed
* by the user. */
- if (priv->con_ip6_config)
- nm_ip6_config_intersect (priv->con_ip6_config, priv->ext_ip6_config);
- if (priv->ac_ip6_config)
- nm_ip6_config_intersect (priv->ac_ip6_config, priv->ext_ip6_config);
- if (priv->dhcp6.ip6_config)
- nm_ip6_config_intersect (priv->dhcp6.ip6_config, priv->ext_ip6_config);
- if (priv->wwan_ip6_config)
- nm_ip6_config_intersect (priv->wwan_ip6_config, priv->ext_ip6_config);
+ if (priv->con_ip6_config) {
+ nm_ip6_config_intersect (priv->con_ip6_config, priv->ext_ip6_config,
+ default_route_metric_penalty_get (self, AF_INET6));
+ }
+ if (priv->ac_ip6_config) {
+ nm_ip6_config_intersect (priv->ac_ip6_config, priv->ext_ip6_config,
+ default_route_metric_penalty_get (self, AF_INET6));
+ }
+ if (priv->dhcp6.ip6_config) {
+ nm_ip6_config_intersect (priv->dhcp6.ip6_config, priv->ext_ip6_config,
+ default_route_metric_penalty_get (self, AF_INET6));
+ }
+ if (priv->wwan_ip6_config) {
+ nm_ip6_config_intersect (priv->wwan_ip6_config, priv->ext_ip6_config,
+ default_route_metric_penalty_get (self, AF_INET6));
+ }
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);
+ nm_ip6_config_intersect (iter->data, priv->ext_ip6_config, 0);
}
/* Remove parts from ext_ip6_config to only contain the information that
* was configured externally -- we already have the same configuration from
* internal origins. */
- if (priv->con_ip6_config)
- nm_ip6_config_subtract (priv->ext_ip6_config, priv->con_ip6_config);
- if (priv->ac_ip6_config)
- nm_ip6_config_subtract (priv->ext_ip6_config, priv->ac_ip6_config);
- if (priv->dhcp6.ip6_config)
- nm_ip6_config_subtract (priv->ext_ip6_config, priv->dhcp6.ip6_config);
- if (priv->wwan_ip6_config)
- nm_ip6_config_subtract (priv->ext_ip6_config, priv->wwan_ip6_config);
+ if (priv->con_ip6_config) {
+ nm_ip6_config_subtract (priv->ext_ip6_config, priv->con_ip6_config,
+ default_route_metric_penalty_get (self, AF_INET6));
+ }
+ if (priv->ac_ip6_config) {
+ nm_ip6_config_subtract (priv->ext_ip6_config, priv->ac_ip6_config,
+ default_route_metric_penalty_get (self, AF_INET6));
+ }
+ if (priv->dhcp6.ip6_config) {
+ nm_ip6_config_subtract (priv->ext_ip6_config, priv->dhcp6.ip6_config,
+ default_route_metric_penalty_get (self, AF_INET6));
+ }
+ if (priv->wwan_ip6_config) {
+ nm_ip6_config_subtract (priv->ext_ip6_config, priv->wwan_ip6_config,
+ default_route_metric_penalty_get (self, AF_INET6));
+ }
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);
+ nm_ip6_config_subtract (priv->ext_ip6_config, iter->data, 0);
}
}
@@ -12403,6 +12291,9 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type)
priv->v4_route_table_initalized = FALSE;
priv->v6_route_table_initalized = FALSE;
+ priv->default_route_metric_penalty_ip4_has = FALSE;
+ priv->default_route_metric_penalty_ip6_has = FALSE;
+
priv->linklocal6_dad_counter = 0;
/* Clean up IP configs; this does not actually deconfigure the
@@ -12410,10 +12301,6 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type)
*/
nm_device_set_ip4_config (self, NULL, TRUE, NULL);
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);
diff --git a/src/devices/wwan/nm-modem-broadband.c b/src/devices/wwan/nm-modem-broadband.c
index fbd29b1e24..3a289f533c 100644
--- a/src/devices/wwan/nm-modem-broadband.c
+++ b/src/devices/wwan/nm-modem-broadband.c
@@ -912,8 +912,24 @@ static_stage3_ip4_done (NMModemBroadband *self)
_LOGI (" address %s/%d", address_string, address.plen);
if (gw) {
- nm_ip4_config_set_gateway (config, gw);
- _LOGI (" gateway %s", gw_string);
+ guint32 ip4_route_table, ip4_route_metric;
+
+ nm_modem_get_route_parameters (NM_MODEM (self),
+ &ip4_route_table,
+ &ip4_route_metric,
+ NULL,
+ NULL);
+ {
+ const NMPlatformIP4Route r = {
+ .rt_source = NM_IP_CONFIG_SOURCE_WWAN,
+ .gateway = gw,
+ .table_coerced = nm_platform_route_table_coerce (ip4_route_table),
+ .metric = ip4_route_metric,
+ };
+
+ _LOGI (" gateway %s", gw_string);
+ nm_ip4_config_add_route (config, &r, NULL);
+ }
}
/* DNS servers */
@@ -1006,7 +1022,9 @@ stage3_ip6_done (NMModemBroadband *self)
address_string = mm_bearer_ip_config_get_gateway (self->_priv.ipv6_config);
if (address_string) {
- if (!inet_pton (AF_INET6, address_string, (void *) &(address.address))) {
+ guint32 ip6_route_table, ip6_route_metric;
+
+ if (inet_pton (AF_INET6, address_string, &address.address) != 1) {
error = g_error_new (NM_DEVICE_ERROR,
NM_DEVICE_ERROR_INVALID_CONNECTION,
"(%s) retrieving IPv6 configuration failed: invalid gateway given '%s'",
@@ -1014,8 +1032,23 @@ stage3_ip6_done (NMModemBroadband *self)
address_string);
goto out;
}
- _LOGI (" gateway %s", address_string);
- nm_ip6_config_set_gateway (config, &address.address);
+
+ nm_modem_get_route_parameters (NM_MODEM (self),
+ NULL,
+ NULL,
+ &ip6_route_table,
+ &ip6_route_metric);
+ {
+ const NMPlatformIP6Route r = {
+ .rt_source = NM_IP_CONFIG_SOURCE_WWAN,
+ .gateway = address.address,
+ .table_coerced = nm_platform_route_table_coerce (ip6_route_table),
+ .metric = ip6_route_metric,
+ };
+
+ _LOGI (" gateway %s", address_string);
+ nm_ip6_config_add_route (config, &r, NULL);
+ }
} else if (ip_method == NM_MODEM_IP_METHOD_STATIC) {
/* Gateway required for the 'static' method */
error = g_error_new (NM_DEVICE_ERROR,
diff --git a/src/devices/wwan/nm-modem-ofono.c b/src/devices/wwan/nm-modem-ofono.c
index a689550cf2..1fe6debcba 100644
--- a/src/devices/wwan/nm-modem-ofono.c
+++ b/src/devices/wwan/nm-modem-ofono.c
@@ -833,6 +833,7 @@ context_property_changed (GDBusProxy *proxy,
const gchar *s, *addr_s;
const gchar **array, **iter;
guint32 address_network, gateway_network;
+ guint32 ip4_route_table, ip4_route_metric;
guint prefix = 0;
_LOGD ("PropertyChanged: %s", property);
@@ -938,16 +939,30 @@ context_property_changed (GDBusProxy *proxy,
nm_ip4_config_add_address (priv->ip4_config, &addr);
- if (g_variant_lookup (v_dict, "Gateway", "&s", &s)) {
- if ( s
- && nm_utils_parse_inaddr_bin (AF_INET, s, &gateway_network)) {
- _LOGI ("Gateway: %s", s);
- nm_ip4_config_set_gateway (priv->ip4_config, gateway_network);
- } else {
+ if ( g_variant_lookup (v_dict, "Gateway", "&s", &s)
+ && s) {
+
+ if (!nm_utils_parse_inaddr_bin (AF_INET, s, &gateway_network)) {
_LOGW ("invalid 'Gateway': %s", s);
goto out;
}
- nm_ip4_config_set_gateway (priv->ip4_config, gateway_network);
+
+ nm_modem_get_route_parameters (NM_MODEM (self),
+ &ip4_route_table,
+ &ip4_route_metric,
+ NULL,
+ NULL);
+ {
+ const NMPlatformIP4Route r = {
+ .rt_source = NM_IP_CONFIG_SOURCE_WWAN,
+ .gateway = gateway_network,
+ .table_coerced = nm_platform_route_table_coerce (ip4_route_table),
+ .metric = ip4_route_metric,
+ };
+
+ _LOGI ("Gateway: %s", s);
+ nm_ip4_config_add_route (priv->ip4_config, &r, NULL);
+ }
} else {
_LOGW ("Settings 'Gateway' missing");
goto out;
@@ -981,17 +996,23 @@ context_property_changed (GDBusProxy *proxy,
_LOGI ("MessageProxy: %s", s);
if ( s
&& nm_utils_parse_inaddr_bin (AF_INET, s, &address_network)) {
- const NMPlatformIP4Route mms_route = {
- .network = address_network,
- .plen = 32,
- .gateway = gateway_network,
- .metric = 1,
- };
-
- /* FIXME: does not handle ipv4.route-table setting and always adds the
- * route to RT_TABLE_MAIN table. */
-
- nm_ip4_config_add_route (priv->ip4_config, &mms_route, NULL);
+ nm_modem_get_route_parameters (NM_MODEM (self),
+ &ip4_route_table,
+ &ip4_route_metric,
+ NULL,
+ NULL);
+
+ {
+ const NMPlatformIP4Route mms_route = {
+ .network = address_network,
+ .plen = 32,
+ .gateway = gateway_network,
+ .table_coerced = nm_platform_route_table_coerce (ip4_route_table),
+ .metric = ip4_route_metric,
+ };
+
+ nm_ip4_config_add_route (priv->ip4_config, &mms_route, NULL);
+ }
} else {
_LOGW ("invalid MessageProxy: %s", s);
}
diff --git a/src/devices/wwan/nm-modem.c b/src/devices/wwan/nm-modem.c
index c3f370475f..77495b62d8 100644
--- a/src/devices/wwan/nm-modem.c
+++ b/src/devices/wwan/nm-modem.c
@@ -26,6 +26,7 @@
#include <fcntl.h>
#include <string.h>
#include <termios.h>
+#include <linux/rtnetlink.h>
#include "nm-core-internal.h"
#include "platform/nm-platform.h"
@@ -97,6 +98,11 @@ typedef struct _NMModemPrivate {
guint32 mm_ip_timeout;
+ guint32 ip4_route_table;
+ guint32 ip4_route_metric;
+ guint32 ip6_route_table;
+ guint32 ip6_route_metric;
+
/* PPP stats */
guint32 in_bytes;
guint32 out_bytes;
@@ -610,6 +616,14 @@ ppp_stage3_ip_config_start (NMModem *self,
priv->ppp_manager = nm_ppp_manager_create (priv->data_port, &error);
+ if (priv->ppp_manager) {
+ nm_ppp_manager_set_route_parameters (priv->ppp_manager,
+ priv->ip4_route_table,
+ priv->ip4_route_metric,
+ priv->ip6_route_table,
+ priv->ip6_route_metric);
+ }
+
if ( !priv->ppp_manager
|| !nm_ppp_manager_start (priv->ppp_manager, req, ppp_name,
ip_timeout, baud_override, &error)) {
@@ -706,6 +720,8 @@ nm_modem_ip4_pre_commit (NMModem *modem,
{
NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (modem);
+ nm_modem_set_route_parameters_from_device (modem, device);
+
/* If the modem has an ethernet-type data interface (ie, not PPP and thus
* not point-to-point) and IP config has a /32 prefix, then we assume that
* ARP will be pointless and we turn it off.
@@ -1400,6 +1416,76 @@ nm_modem_get_iid (NMModem *self, NMUtilsIPv6IfaceId *out_iid)
/*****************************************************************************/
void
+nm_modem_get_route_parameters (NMModem *self,
+ guint32 *out_ip4_route_table,
+ guint32 *out_ip4_route_metric,
+ guint32 *out_ip6_route_table,
+ guint32 *out_ip6_route_metric)
+{
+ NMModemPrivate *priv;
+
+ g_return_if_fail (NM_IS_MODEM (self));
+
+ priv = NM_MODEM_GET_PRIVATE (self);
+ NM_SET_OUT (out_ip4_route_table, priv->ip4_route_table);
+ NM_SET_OUT (out_ip4_route_metric, priv->ip4_route_metric);
+ NM_SET_OUT (out_ip6_route_table, priv->ip6_route_table);
+ NM_SET_OUT (out_ip6_route_metric, priv->ip6_route_metric);
+}
+
+void
+nm_modem_set_route_parameters (NMModem *self,
+ guint32 ip4_route_table,
+ guint32 ip4_route_metric,
+ guint32 ip6_route_table,
+ guint32 ip6_route_metric)
+{
+ NMModemPrivate *priv;
+
+ g_return_if_fail (NM_IS_MODEM (self));
+
+ priv = NM_MODEM_GET_PRIVATE (self);
+ if ( priv->ip4_route_table != ip4_route_table
+ || priv->ip4_route_metric != ip4_route_metric
+ || priv->ip6_route_table != ip6_route_table
+ || priv->ip6_route_metric != ip6_route_metric) {
+ priv->ip4_route_table = ip4_route_table;
+ priv->ip4_route_metric = ip4_route_metric;
+ priv->ip6_route_table = ip6_route_table;
+ priv->ip6_route_metric = ip6_route_metric;
+
+ _LOGT ("route-parameters: table-v4: %u, metric-v4: %u, table-v6: %u, metric-v6: %u",
+ priv->ip4_route_table,
+ priv->ip4_route_metric,
+ priv->ip6_route_table,
+ priv->ip6_route_metric);
+ }
+
+ if (priv->ppp_manager) {
+ nm_ppp_manager_set_route_parameters (priv->ppp_manager,
+ priv->ip4_route_table,
+ priv->ip4_route_metric,
+ priv->ip6_route_table,
+ priv->ip6_route_metric);
+ }
+}
+
+void
+nm_modem_set_route_parameters_from_device (NMModem *self,
+ NMDevice *device)
+{
+ g_return_if_fail (NM_IS_DEVICE (device));
+
+ nm_modem_set_route_parameters (self,
+ nm_device_get_route_table (device, AF_INET, TRUE),
+ nm_device_get_route_metric (device, AF_INET),
+ nm_device_get_route_table (device, AF_INET6, TRUE),
+ nm_device_get_route_metric (device, AF_INET6));
+}
+
+/*****************************************************************************/
+
+void
nm_modem_get_capabilities (NMModem *self,
NMDeviceModemCapabilities *modem_caps,
NMDeviceModemCapabilities *current_caps)
@@ -1533,7 +1619,15 @@ set_property (GObject *object, guint prop_id,
static void
nm_modem_init (NMModem *self)
{
+ NMModemPrivate *priv;
+
self->_priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_MODEM, NMModemPrivate);
+ priv = self->_priv;
+
+ priv->ip4_route_table = RT_TABLE_MAIN;
+ priv->ip4_route_metric = 700;
+ priv->ip6_route_table = RT_TABLE_MAIN;
+ priv->ip6_route_metric = 700;
}
static void
diff --git a/src/devices/wwan/nm-modem.h b/src/devices/wwan/nm-modem.h
index c6efda951d..9546e4a12e 100644
--- a/src/devices/wwan/nm-modem.h
+++ b/src/devices/wwan/nm-modem.h
@@ -187,6 +187,21 @@ gboolean nm_modem_complete_connection (NMModem *self,
const GSList *existing_connections,
GError **error);
+void nm_modem_get_route_parameters (NMModem *self,
+ guint32 *out_ip4_route_table,
+ guint32 *out_ip4_route_metric,
+ guint32 *out_ip6_route_table,
+ guint32 *out_ip6_route_metric);
+
+void nm_modem_set_route_parameters (NMModem *self,
+ guint32 ip4_route_table,
+ guint32 ip4_route_metric,
+ guint32 ip6_route_table,
+ guint32 ip6_route_metric);
+
+void nm_modem_set_route_parameters_from_device (NMModem *modem,
+ NMDevice *device);
+
NMActStageReturn nm_modem_act_stage1_prepare (NMModem *modem,
NMActRequest *req,
NMDeviceStateReason *out_failure_reason);
diff --git a/src/dhcp/nm-dhcp-dhclient-utils.c b/src/dhcp/nm-dhcp-dhclient-utils.c
index 6e32ae73b7..a82d78733b 100644
--- a/src/dhcp/nm-dhcp-dhclient-utils.c
+++ b/src/dhcp/nm-dhcp-dhclient-utils.c
@@ -689,6 +689,8 @@ lease_validity_span (const char *str_expire, GDateTime *now)
* @addr_family: whether to read IPv4 or IPv6 leases
* @iface: the interface name to match leases with
* @ifindex: interface index of @iface
+ * @route_table: the route table for the default route.
+ * @route_metric: the route metric for the default route.
* @contents: the contents of a dhclient leasefile
* @now: the current UTC date/time; pass %NULL to automatically use current
* UTC time. Testcases may need a different value for 'now'
@@ -704,6 +706,8 @@ nm_dhcp_dhclient_read_lease_ip_configs (NMDedupMultiIndex *multi_idx,
int addr_family,
const char *iface,
int ifindex,
+ guint32 route_table,
+ guint32 route_metric,
const char *contents,
GDateTime *now)
{
@@ -814,7 +818,17 @@ nm_dhcp_dhclient_read_lease_ip_configs (NMDedupMultiIndex *multi_idx,
ip4 = nm_ip4_config_new (multi_idx, ifindex);
nm_ip4_config_add_address (ip4, &address);
- nm_ip4_config_set_gateway (ip4, gw);
+
+ {
+ const NMPlatformIP4Route r = {
+ .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
+ .gateway = gw,
+ .table_coerced = nm_platform_route_table_coerce (route_table),
+ .metric = route_metric,
+ };
+
+ nm_ip4_config_add_route (ip4, &r, NULL);
+ }
value = g_hash_table_lookup (hash, "option domain-name-servers");
if (value) {
diff --git a/src/dhcp/nm-dhcp-dhclient-utils.h b/src/dhcp/nm-dhcp-dhclient-utils.h
index a5dc9c2b62..94de196362 100644
--- a/src/dhcp/nm-dhcp-dhclient-utils.h
+++ b/src/dhcp/nm-dhcp-dhclient-utils.h
@@ -47,6 +47,8 @@ GSList *nm_dhcp_dhclient_read_lease_ip_configs (struct _NMDedupMultiIndex *multi
int addr_family,
const char *iface,
int ifindex,
+ guint32 route_table,
+ guint32 route_metric,
const char *contents,
GDateTime *now);
diff --git a/src/dhcp/nm-dhcp-dhclient.c b/src/dhcp/nm-dhcp-dhclient.c
index 6259fb5b17..74d920a8da 100644
--- a/src/dhcp/nm-dhcp-dhclient.c
+++ b/src/dhcp/nm-dhcp-dhclient.c
@@ -167,9 +167,8 @@ nm_dhcp_dhclient_get_lease_ip_configs (NMDedupMultiIndex *multi_idx,
guint32 route_table,
guint32 route_metric)
{
- char *contents = NULL;
- char *leasefile;
- GSList *leases = NULL;
+ gs_free char *contents = NULL;
+ gs_free char *leasefile = NULL;
leasefile = get_dhclient_leasefile (addr_family, iface, uuid, NULL);
if (!leasefile)
@@ -178,13 +177,11 @@ nm_dhcp_dhclient_get_lease_ip_configs (NMDedupMultiIndex *multi_idx,
if ( g_file_test (leasefile, G_FILE_TEST_EXISTS)
&& g_file_get_contents (leasefile, &contents, NULL, NULL)
&& contents
- && contents[0])
- leases = nm_dhcp_dhclient_read_lease_ip_configs (multi_idx, addr_family, iface, ifindex, contents, NULL);
-
- g_free (leasefile);
- g_free (contents);
-
- return leases;
+ && contents[0]) {
+ return nm_dhcp_dhclient_read_lease_ip_configs (multi_idx, addr_family, iface, ifindex,
+ route_table, route_metric, contents, NULL);
+ }
+ return NULL;
}
static gboolean
diff --git a/src/dhcp/nm-dhcp-systemd.c b/src/dhcp/nm-dhcp-systemd.c
index 5e0370db55..c8c90304c8 100644
--- a/src/dhcp/nm-dhcp-systemd.c
+++ b/src/dhcp/nm-dhcp-systemd.c
@@ -243,6 +243,8 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx,
gsize data_len;
gboolean metered = FALSE;
gboolean static_default_gateway = FALSE;
+ gboolean gateway_has = FALSE;
+ in_addr_t gateway = 0;
g_return_val_if_fail (lease != NULL, NULL);
@@ -369,7 +371,8 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx,
} else {
if (!static_default_gateway) {
static_default_gateway = TRUE;
- nm_ip4_config_set_gateway (ip4_config, route.gateway);
+ gateway_has = TRUE;
+ gateway = route.gateway;
s = nm_utils_inet4_ntop (route.gateway, NULL);
LOG_LEASE (LOGD_DHCP4, "gateway %s", s);
@@ -390,13 +393,25 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx,
if (!static_default_gateway) {
r = sd_dhcp_lease_get_router (lease, &tmp_addr);
if (r == 0) {
- nm_ip4_config_set_gateway (ip4_config, tmp_addr.s_addr);
+ gateway_has = TRUE;
+ gateway = tmp_addr.s_addr;
s = nm_utils_inet4_ntop (tmp_addr.s_addr, NULL);
LOG_LEASE (LOGD_DHCP4, "gateway %s", s);
add_option (options, dhcp4_requests, SD_DHCP_OPTION_ROUTER, s);
}
}
+ if (gateway_has) {
+ const NMPlatformIP4Route rt = {
+ .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
+ .gateway = gateway,
+ .table_coerced = nm_platform_route_table_coerce (route_table),
+ .metric = route_metric,
+ };
+
+ nm_ip4_config_add_route (ip4_config, &rt, NULL);
+ }
+
/* MTU */
r = sd_dhcp_lease_get_mtu (lease, &mtu);
if (r == 0 && mtu) {
diff --git a/src/dhcp/nm-dhcp-utils.c b/src/dhcp/nm-dhcp-utils.c
index 9e1e75a470..4b2d57b90f 100644
--- a/src/dhcp/nm-dhcp-utils.c
+++ b/src/dhcp/nm-dhcp-utils.c
@@ -405,7 +405,8 @@ nm_dhcp_utils_ip4_config_from_options (NMDedupMultiIndex *multi_idx,
in_addr_t addr;
NMPlatformIP4Address address;
char *str = NULL;
- guint32 gwaddr = 0;
+ gboolean gateway_has = FALSE;
+ guint32 gateway = 0;
guint8 plen = 0;
g_return_val_if_fail (options != NULL, NULL);
@@ -434,12 +435,12 @@ nm_dhcp_utils_ip4_config_from_options (NMDedupMultiIndex *multi_idx,
/* Routes: if the server returns classless static routes, we MUST ignore
* the 'static_routes' option.
*/
- if (!ip4_process_classless_routes (iface, options, route_table, route_metric, ip4_config, &gwaddr))
+ if (!ip4_process_classless_routes (iface, options, route_table, route_metric, ip4_config, &gateway))
process_classful_routes (iface, options, route_table, route_metric, ip4_config);
- if (gwaddr) {
- _LOG2I (LOGD_DHCP4, iface, " gateway %s", nm_utils_inet4_ntop (gwaddr, NULL));
- nm_ip4_config_set_gateway (ip4_config, gwaddr);
+ if (gateway) {
+ _LOG2I (LOGD_DHCP4, iface, " gateway %s", nm_utils_inet4_ntop (gateway, NULL));
+ gateway_has = TRUE;
} else {
/* If the gateway wasn't provided as a classless static route with a
* subnet length of 0, try to find it using the old-style 'routers' option.
@@ -451,9 +452,9 @@ nm_dhcp_utils_ip4_config_from_options (NMDedupMultiIndex *multi_idx,
for (s = routers; *s; s++) {
/* FIXME: how to handle multiple routers? */
- if (inet_pton (AF_INET, *s, &gwaddr) > 0) {
- nm_ip4_config_set_gateway (ip4_config, gwaddr);
+ if (inet_pton (AF_INET, *s, &gateway) > 0) {
_LOG2I (LOGD_DHCP4, iface, " gateway %s", *s);
+ gateway_has = TRUE;
break;
} else
_LOG2W (LOGD_DHCP4, iface, "ignoring invalid gateway '%s'", *s);
@@ -462,6 +463,17 @@ nm_dhcp_utils_ip4_config_from_options (NMDedupMultiIndex *multi_idx,
}
}
+ if (gateway_has) {
+ const NMPlatformIP4Route r = {
+ .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
+ .gateway = gateway,
+ .table_coerced = nm_platform_route_table_coerce (route_table),
+ .metric = route_metric,
+ };
+
+ nm_ip4_config_add_route (ip4_config, &r, NULL);
+ }
+
str = g_hash_table_lookup (options, "dhcp_lease_time");
if (str) {
address.lifetime = address.preferred = strtoul (str, NULL, 10);
diff --git a/src/dhcp/tests/test-dhcp-dhclient.c b/src/dhcp/tests/test-dhcp-dhclient.c
index a338c13394..f2e1f32157 100644
--- a/src/dhcp/tests/test-dhcp-dhclient.c
+++ b/src/dhcp/tests/test-dhcp-dhclient.c
@@ -23,6 +23,7 @@
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
+#include <linux/rtnetlink.h>
#include "nm-utils/nm-dedup-multi.h"
@@ -38,6 +39,8 @@
#define DEBUG 1
static const int IFINDEX = 5;
+static const guint32 ROUTE_TABLE = RT_TABLE_MAIN;
+static const guint32 ROUTE_METRIC = 100;
static void
test_config (const char *orig,
@@ -912,7 +915,7 @@ test_read_lease_ip4_config_basic (void)
/* Date from before the least expiration */
now = g_date_time_new_utc (2013, 11, 1, 19, 55, 32);
- leases = nm_dhcp_dhclient_read_lease_ip_configs (multi_idx, AF_INET, "wlan0", IFINDEX, contents, now);
+ leases = nm_dhcp_dhclient_read_lease_ip_configs (multi_idx, AF_INET, "wlan0", IFINDEX, ROUTE_TABLE, ROUTE_METRIC, contents, now);
g_assert_cmpint (g_slist_length (leases), ==, 2);
/* IP4Config #1 */
@@ -929,7 +932,7 @@ test_read_lease_ip4_config_basic (void)
/* Gateway */
expected_addr = nmtst_inet4_from_string ("192.168.1.1");
- g_assert_cmpint (nm_ip4_config_get_gateway (config), ==, expected_addr);
+ g_assert_cmpint (nmtst_ip4_config_get_gateway (config), ==, expected_addr);
/* DNS */
g_assert_cmpint (nm_ip4_config_get_num_nameservers (config), ==, 1);
@@ -952,7 +955,7 @@ test_read_lease_ip4_config_basic (void)
/* Gateway */
expected_addr = nmtst_inet4_from_string ("10.77.52.254");
- g_assert_cmpint (nm_ip4_config_get_gateway (config), ==, expected_addr);
+ g_assert_cmpint (nmtst_ip4_config_get_gateway (config), ==, expected_addr);
/* DNS */
g_assert_cmpint (nm_ip4_config_get_num_nameservers (config), ==, 2);
@@ -987,7 +990,7 @@ test_read_lease_ip4_config_expired (void)
/* Date from *after* the lease expiration */
now = g_date_time_new_utc (2013, 12, 1, 19, 55, 32);
- leases = nm_dhcp_dhclient_read_lease_ip_configs (multi_idx, AF_INET, "wlan0", IFINDEX, contents, now);
+ leases = nm_dhcp_dhclient_read_lease_ip_configs (multi_idx, AF_INET, "wlan0", IFINDEX, ROUTE_TABLE, ROUTE_METRIC, contents, now);
g_assert (leases == NULL);
g_date_time_unref (now);
@@ -1010,7 +1013,7 @@ test_read_lease_ip4_config_expect_failure (gconstpointer user_data)
/* Date from before the least expiration */
now = g_date_time_new_utc (2013, 11, 1, 1, 1, 1);
- leases = nm_dhcp_dhclient_read_lease_ip_configs (multi_idx, AF_INET, "wlan0", IFINDEX, contents, now);
+ leases = nm_dhcp_dhclient_read_lease_ip_configs (multi_idx, AF_INET, "wlan0", IFINDEX, ROUTE_TABLE, ROUTE_METRIC, contents, now);
g_assert (leases == NULL);
g_date_time_unref (now);
diff --git a/src/dhcp/tests/test-dhcp-utils.c b/src/dhcp/tests/test-dhcp-utils.c
index 1ffadcd810..1419b2648d 100644
--- a/src/dhcp/tests/test-dhcp-utils.c
+++ b/src/dhcp/tests/test-dhcp-utils.c
@@ -114,7 +114,7 @@ test_generic_options (void)
/* Gateway */
g_assert (inet_pton (AF_INET, expected_gw, &tmp) > 0);
- g_assert (nm_ip4_config_get_gateway (ip4_config) == tmp);
+ g_assert (nmtst_ip4_config_get_gateway (ip4_config) == tmp);
g_assert_cmpint (nm_ip4_config_get_num_wins (ip4_config), ==, 0);
@@ -133,7 +133,7 @@ test_generic_options (void)
g_assert (nm_ip4_config_get_nameserver (ip4_config, 1) == tmp);
/* Routes */
- g_assert_cmpint (nm_ip4_config_get_num_routes (ip4_config), ==, 2);
+ g_assert_cmpint (nm_ip4_config_get_num_routes (ip4_config), ==, 3);
/* Route #1 */
route = _nmtst_ip4_config_get_route (ip4_config, 0);
@@ -146,13 +146,17 @@ test_generic_options (void)
/* Route #2 */
route = _nmtst_ip4_config_get_route (ip4_config, 1);
- g_assert (inet_pton (AF_INET, expected_route2_dest, &tmp) > 0);
- g_assert (route->network == tmp);
- g_assert (inet_pton (AF_INET, expected_route2_gw, &tmp) > 0);
- g_assert (route->gateway == tmp);
+ g_assert (route->network == nmtst_inet4_from_string (expected_route2_dest));
+ g_assert (route->gateway == nmtst_inet4_from_string (expected_route2_gw));
g_assert_cmpint (route->plen, ==, 32);
g_assert_cmpint (route->metric, ==, 0);
+ route = _nmtst_ip4_config_get_route (ip4_config, 2);
+ g_assert (route->network == nmtst_inet4_from_string ("0.0.0.0"));
+ g_assert (route->gateway == nmtst_inet4_from_string ("192.168.1.1"));
+ g_assert_cmpint (route->plen, ==, 0);
+ g_assert_cmpint (route->metric, ==, 0);
+
g_hash_table_destroy (options);
}
@@ -238,7 +242,7 @@ ip4_test_gateway (NMIP4Config *ip4_config, const char *expected_gw)
g_assert_cmpint (nm_ip4_config_get_num_addresses (ip4_config), ==, 1);
g_assert (inet_pton (AF_INET, expected_gw, &tmp) > 0);
- g_assert (nm_ip4_config_get_gateway (ip4_config) == tmp);
+ g_assert (nmtst_ip4_config_get_gateway (ip4_config) == tmp);
}
static void
@@ -261,9 +265,10 @@ test_classless_static_routes_1 (void)
ip4_config = _ip4_config_from_options (1, "eth0", options, 0);
/* IP4 routes */
- g_assert_cmpint (nm_ip4_config_get_num_routes (ip4_config), ==, 2);
+ g_assert_cmpint (nm_ip4_config_get_num_routes (ip4_config), ==, 3);
ip4_test_route (ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
ip4_test_route (ip4_config, 1, expected_route2_dest, expected_route2_gw, 8);
+ ip4_test_route (ip4_config, 2, "0.0.0.0", "192.168.1.1", 0);
g_hash_table_destroy (options);
}
@@ -288,9 +293,10 @@ test_classless_static_routes_2 (void)
ip4_config = _ip4_config_from_options (1, "eth0", options, 0);
/* IP4 routes */
- g_assert_cmpint (nm_ip4_config_get_num_routes (ip4_config), ==, 2);
+ g_assert_cmpint (nm_ip4_config_get_num_routes (ip4_config), ==, 3);
ip4_test_route (ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
ip4_test_route (ip4_config, 1, expected_route2_dest, expected_route2_gw, 8);
+ ip4_test_route (ip4_config, 2, "0.0.0.0", expected_route1_gw, 0);
g_hash_table_destroy (options);
}
@@ -316,9 +322,10 @@ test_fedora_dhclient_classless_static_routes (void)
ip4_config = _ip4_config_from_options (1, "eth0", options, 0);
/* IP4 routes */
- g_assert_cmpint (nm_ip4_config_get_num_routes (ip4_config), ==, 2);
+ g_assert_cmpint (nm_ip4_config_get_num_routes (ip4_config), ==, 3);
ip4_test_route (ip4_config, 0, expected_route1_dest, expected_route1_gw, 25);
ip4_test_route (ip4_config, 1, expected_route2_dest, expected_route2_gw, 7);
+ ip4_test_route (ip4_config, 2, "0.0.0.0", expected_route1_gw, 0);
/* Gateway */
ip4_test_gateway (ip4_config, expected_gateway);
@@ -348,8 +355,9 @@ test_dhclient_invalid_classless_routes_1 (void)
g_test_assert_expected_messages ();
/* IP4 routes */
- g_assert_cmpint (nm_ip4_config_get_num_routes (ip4_config), ==, 1);
+ g_assert_cmpint (nm_ip4_config_get_num_routes (ip4_config), ==, 2);
ip4_test_route (ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
+ ip4_test_route (ip4_config, 1, "0.0.0.0", expected_route1_gw, 0);
g_hash_table_destroy (options);
}
@@ -380,9 +388,10 @@ test_dhcpcd_invalid_classless_routes_1 (void)
/* Test falling back to old-style static routes if the classless static
* routes are invalid.
*/
- g_assert_cmpint (nm_ip4_config_get_num_routes (ip4_config), ==, 2);
+ g_assert_cmpint (nm_ip4_config_get_num_routes (ip4_config), ==, 3);
ip4_test_route (ip4_config, 0, expected_route1_dest, expected_route1_gw, 32);
ip4_test_route (ip4_config, 1, expected_route2_dest, expected_route2_gw, 32);
+ ip4_test_route (ip4_config, 2, "0.0.0.0", "192.168.1.1", 0);
g_hash_table_destroy (options);
}
@@ -412,9 +421,10 @@ test_dhclient_invalid_classless_routes_2 (void)
/* Test falling back to old-style static routes if the classless static
* routes are invalid.
*/
- g_assert_cmpint (nm_ip4_config_get_num_routes (ip4_config), ==, 2);
+ g_assert_cmpint (nm_ip4_config_get_num_routes (ip4_config), ==, 3);
ip4_test_route (ip4_config, 0, expected_route1_dest, expected_route1_gw, 32);
ip4_test_route (ip4_config, 1, expected_route2_dest, expected_route2_gw, 32);
+ ip4_test_route (ip4_config, 2, "0.0.0.0", "192.168.1.1", 0);
g_hash_table_destroy (options);
}
@@ -446,9 +456,10 @@ test_dhcpcd_invalid_classless_routes_2 (void)
*/
/* Routes */
- g_assert_cmpint (nm_ip4_config_get_num_routes (ip4_config), ==, 2);
+ g_assert_cmpint (nm_ip4_config_get_num_routes (ip4_config), ==, 3);
ip4_test_route (ip4_config, 0, expected_route1_dest, expected_route1_gw, 32);
ip4_test_route (ip4_config, 1, expected_route2_dest, expected_route2_gw, 32);
+ ip4_test_route (ip4_config, 2, "0.0.0.0", "192.168.1.1", 0);
g_hash_table_destroy (options);
}
@@ -474,8 +485,9 @@ test_dhclient_invalid_classless_routes_3 (void)
g_test_assert_expected_messages ();
/* IP4 routes */
- g_assert_cmpint (nm_ip4_config_get_num_routes (ip4_config), ==, 1);
+ g_assert_cmpint (nm_ip4_config_get_num_routes (ip4_config), ==, 2);
ip4_test_route (ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
+ ip4_test_route (ip4_config, 1, "0.0.0.0", expected_route1_gw, 0);
g_hash_table_destroy (options);
}
@@ -501,8 +513,9 @@ test_dhcpcd_invalid_classless_routes_3 (void)
g_test_assert_expected_messages ();
/* IP4 routes */
- g_assert_cmpint (nm_ip4_config_get_num_routes (ip4_config), ==, 1);
+ g_assert_cmpint (nm_ip4_config_get_num_routes (ip4_config), ==, 2);
ip4_test_route (ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
+ ip4_test_route (ip4_config, 1, "0.0.0.0", expected_route1_gw, 0);
g_hash_table_destroy (options);
}
@@ -525,8 +538,9 @@ test_dhclient_gw_in_classless_routes (void)
ip4_config = _ip4_config_from_options (1, "eth0", options, 0);
/* IP4 routes */
- g_assert_cmpint (nm_ip4_config_get_num_routes (ip4_config), ==, 1);
+ g_assert_cmpint (nm_ip4_config_get_num_routes (ip4_config), ==, 2);
ip4_test_route (ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
+ ip4_test_route (ip4_config, 1, "0.0.0.0", "192.2.3.4", 0);
/* Gateway */
ip4_test_gateway (ip4_config, expected_gateway);
@@ -552,8 +566,9 @@ test_dhcpcd_gw_in_classless_routes (void)
ip4_config = _ip4_config_from_options (1, "eth0", options, 0);
/* IP4 routes */
- g_assert_cmpint (nm_ip4_config_get_num_routes (ip4_config), ==, 1);
+ g_assert_cmpint (nm_ip4_config_get_num_routes (ip4_config), ==, 2);
ip4_test_route (ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
+ ip4_test_route (ip4_config, 1, "0.0.0.0", "192.2.3.4", 0);
/* Gateway */
ip4_test_gateway (ip4_config, expected_gateway);
diff --git a/src/dns/nm-dns-systemd-resolved.c b/src/dns/nm-dns-systemd-resolved.c
index e7e71489fc..315f2c4d0d 100644
--- a/src/dns/nm-dns-systemd-resolved.c
+++ b/src/dns/nm-dns-systemd-resolved.c
@@ -136,16 +136,6 @@ add_interface_configuration (NMDnsSystemdResolved *self,
}
static void
-add_domain (GVariantBuilder *domains,
- const char *domain,
- gboolean never_default)
-{
- /* If this link is never the default (e.g. only used for resources on this
- * network) add a routing domain. */
- g_variant_builder_add (domains, "(sb)", domain, never_default);
-}
-
-static void
update_add_ip_config (NMDnsSystemdResolved *self,
GVariantBuilder *dns,
GVariantBuilder *domains,
@@ -154,7 +144,7 @@ update_add_ip_config (NMDnsSystemdResolved *self,
int addr_family;
gsize addr_size;
guint i, n;
- gboolean never_default;
+ gboolean route_only;
if (NM_IS_IP4_CONFIG (config))
addr_family = AF_INET;
@@ -188,31 +178,33 @@ update_add_ip_config (NMDnsSystemdResolved *self,
g_variant_builder_close (dns);
}
- never_default = addr_family == AF_INET
- ? nm_ip4_config_get_never_default (config)
- : nm_ip6_config_get_never_default (config);
+ /* If this link is never the default (e.g. only used for resources on this
+ * network) add a routing domain. */
+ route_only = addr_family == AF_INET
+ ? !nm_ip4_config_best_default_route_get (config)
+ : !nm_ip6_config_best_default_route_get (config);
n = addr_family == AF_INET
? nm_ip4_config_get_num_searches (config)
: nm_ip6_config_get_num_searches (config);
if (n > 0) {
for (i = 0; i < n; i++) {
- add_domain (domains,
- addr_family == AF_INET
- ? nm_ip4_config_get_search (config, i)
- : nm_ip6_config_get_search (config, i),
- never_default);
+ g_variant_builder_add (domains, "(sb)",
+ addr_family == AF_INET
+ ? nm_ip4_config_get_search (config, i)
+ : nm_ip6_config_get_search (config, i),
+ route_only);
}
} else {
n = addr_family == AF_INET
? nm_ip4_config_get_num_domains (config)
: nm_ip6_config_get_num_domains (config);
for (i = 0; i < n; i++) {
- add_domain (domains,
- addr_family == AF_INET
- ? nm_ip4_config_get_domain (config, i)
- : nm_ip6_config_get_domain (config, i),
- never_default);
+ g_variant_builder_add (domains, "(sb)",
+ addr_family == AF_INET
+ ? nm_ip4_config_get_domain (config, i)
+ : nm_ip6_config_get_domain (config, i),
+ route_only);
}
}
}
diff --git a/src/dnsmasq/nm-dnsmasq-manager.c b/src/dnsmasq/nm-dnsmasq-manager.c
index 3296cd0e73..4ac1e7c350 100644
--- a/src/dnsmasq/nm-dnsmasq-manager.c
+++ b/src/dnsmasq/nm-dnsmasq-manager.c
@@ -221,7 +221,7 @@ create_dm_cmd_line (const char *iface,
nm_cmd_line_add_string (cmd, s->str);
g_string_truncate (s, 0);
- if (!nm_ip4_config_get_never_default (ip4_config)) {
+ if (nm_ip4_config_best_default_route_get (ip4_config)) {
g_string_append (s, "--dhcp-option=option:router,");
g_string_append (s, localaddr);
nm_cmd_line_add_string (cmd, s->str);
diff --git a/src/ndisc/nm-ndisc.h b/src/ndisc/nm-ndisc.h
index db19db0021..8b5f2bd5b1 100644
--- a/src/ndisc/nm-ndisc.h
+++ b/src/ndisc/nm-ndisc.h
@@ -62,12 +62,13 @@ typedef enum {
NM_NDISC_PREFERENCE_HIGH
} NMNDiscPreference;
-typedef struct {
+struct _NMNDiscGateway {
struct in6_addr address;
guint32 timestamp;
guint32 lifetime;
NMNDiscPreference preference;
-} NMNDiscGateway;
+};
+typedef struct _NMNDiscGateway NMNDiscGateway;
struct _NMNDiscAddress {
struct in6_addr address;
diff --git a/src/nm-core-utils.h b/src/nm-core-utils.h
index 21ff111a33..5fc5fe159b 100644
--- a/src/nm-core-utils.h
+++ b/src/nm-core-utils.h
@@ -169,6 +169,15 @@ nm_utils_ip_route_metric_normalize (int addr_family, guint32 metric)
return addr_family == AF_INET6 ? nm_utils_ip6_route_metric_normalize (metric) : metric;
}
+static inline guint32
+nm_utils_ip_route_metric_penalize (int addr_family, guint32 metric, guint32 penalty)
+{
+ metric = nm_utils_ip_route_metric_normalize (addr_family, metric);
+ if (metric < G_MAXUINT32 - penalty)
+ return metric + penalty;
+ return G_MAXUINT32;
+}
+
int nm_utils_modprobe (GError **error, gboolean suppress_error_loggin, const char *arg1, ...) G_GNUC_NULL_TERMINATED;
guint64 nm_utils_get_start_time_for_pid (pid_t pid, char *out_state, pid_t *out_ppid);
diff --git a/src/nm-dispatcher.c b/src/nm-dispatcher.c
index b5b11812e0..237afdefe7 100644
--- a/src/nm-dispatcher.c
+++ b/src/nm-dispatcher.c
@@ -124,9 +124,14 @@ dump_ip4_to_props (NMIP4Config *ip4, GVariantBuilder *builder)
g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("aau"));
first = TRUE;
nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, ip4, &addr) {
+ const NMPObject *default_route;
+
array[0] = addr->address;
array[1] = addr->plen;
- array[2] = first ? nm_ip4_config_get_gateway (ip4) : 0;
+ array[2] = ( first
+ && (default_route = nm_ip4_config_best_default_route_get (ip4)))
+ ? NMP_OBJECT_CAST_IP4_ROUTE (default_route)->gateway
+ : (guint32) 0;
g_variant_builder_add (&int_builder, "@au",
g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
array, 3, sizeof (guint32)));
@@ -197,12 +202,15 @@ dump_ip6_to_props (NMIP6Config *ip6, GVariantBuilder *builder)
first = TRUE;
nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, ip6, &addr) {
+ const NMPObject *default_route;
+
ip = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
&addr->address,
sizeof (struct in6_addr), 1);
gw = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
- first
- ? (nm_ip6_config_get_gateway (ip6) ?: &in6addr_any)
+ ( first
+ && (default_route = nm_ip6_config_best_default_route_get (ip6)))
+ ? &NMP_OBJECT_CAST_IP6_ROUTE (default_route)->gateway
: &in6addr_any,
sizeof (struct in6_addr), 1);
g_variant_builder_add (&int_builder, "(@ayu@ay)", ip, addr->plen, gw);
diff --git a/src/nm-iface-helper.c b/src/nm-iface-helper.c
index 4c21f40e12..4be92bfb44 100644
--- a/src/nm-iface-helper.c
+++ b/src/nm-iface-helper.c
@@ -122,13 +122,13 @@ dhcp4_state_changed (NMDhcpClient *client,
existing = nm_ip4_config_capture (nm_platform_get_multi_idx (NM_PLATFORM_GET),
NM_PLATFORM_GET, gl.ifindex, FALSE);
if (last_config)
- nm_ip4_config_subtract (existing, last_config);
+ nm_ip4_config_subtract (existing, last_config, 0);
- nm_ip4_config_merge (existing, ip4_config, NM_IP_CONFIG_MERGE_DEFAULT);
- nm_ip4_config_add_device_routes (existing,
- RT_TABLE_MAIN,
- global_opt.priority_v4,
- &ip4_dev_route_blacklist);
+ nm_ip4_config_merge (existing, ip4_config, NM_IP_CONFIG_MERGE_DEFAULT, 0);
+ nm_ip4_config_add_dependent_routes (existing,
+ RT_TABLE_MAIN,
+ global_opt.priority_v4,
+ &ip4_dev_route_blacklist);
if (!nm_ip4_config_commit (existing,
NM_PLATFORM_GET,
NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN))
@@ -168,20 +168,12 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in
existing = nm_ip6_config_capture (nm_platform_get_multi_idx (NM_PLATFORM_GET),
NM_PLATFORM_GET, gl.ifindex, FALSE, global_opt.tempaddr);
if (ndisc_config)
- nm_ip6_config_subtract (existing, ndisc_config);
+ nm_ip6_config_subtract (existing, ndisc_config, 0);
else {
ndisc_config = nm_ip6_config_new (nm_platform_get_multi_idx (NM_PLATFORM_GET),
gl.ifindex);
}
- if (changed & NM_NDISC_CONFIG_GATEWAYS) {
- /* Use the first gateway as ordered in neighbor discovery cache. */
- if (rdata->gateways_n)
- nm_ip6_config_set_gateway (ndisc_config, &rdata->gateways[0].address);
- else
- nm_ip6_config_set_gateway (ndisc_config, NULL);
- }
-
if (changed & NM_NDISC_CONFIG_ADDRESSES) {
guint8 plen;
guint32 ifa_flags;
@@ -207,8 +199,11 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in
ifa_flags);
}
- if (changed & NM_NDISC_CONFIG_ROUTES) {
+ if (NM_FLAGS_ANY (changed, NM_NDISC_CONFIG_ROUTES
+ | NM_NDISC_CONFIG_GATEWAYS)) {
nm_ip6_config_reset_routes_ndisc (ndisc_config,
+ rdata->gateways,
+ rdata->gateways_n,
rdata->routes,
rdata->routes_n,
RT_TABLE_MAIN,
@@ -229,10 +224,10 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in
nm_platform_sysctl_set (NM_PLATFORM_GET, NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_ip6_property_path (global_opt.ifname, "mtu")), val);
}
- nm_ip6_config_merge (existing, ndisc_config, NM_IP_CONFIG_MERGE_DEFAULT);
- nm_ip6_config_add_device_routes (existing,
- RT_TABLE_MAIN,
- global_opt.priority_v6);
+ nm_ip6_config_merge (existing, ndisc_config, NM_IP_CONFIG_MERGE_DEFAULT, 0);
+ nm_ip6_config_add_dependent_routes (existing,
+ RT_TABLE_MAIN,
+ global_opt.priority_v6);
if (!nm_ip6_config_commit (existing,
NM_PLATFORM_GET,
NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN,
diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c
index b80ff8cc11..add841e1e6 100644
--- a/src/nm-ip4-config.c
+++ b/src/nm-ip4-config.c
@@ -287,10 +287,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMIP4Config,
);
typedef struct {
- bool never_default:1;
bool metered:1;
- bool has_gateway:1;
- guint32 gateway;
guint32 mtu;
int ifindex;
NMIPConfigSource mtu_source;
@@ -489,6 +486,19 @@ _nm_ip4_config_best_default_route_find (const NMIP4Config *self)
return new_best_default_route;
}
+in_addr_t
+nmtst_ip4_config_get_gateway (NMIP4Config *config)
+{
+ const NMPObject *rt;
+
+ g_assert (NM_IS_IP4_CONFIG (config));
+
+ rt = nm_ip4_config_best_default_route_get (config);
+ if (!rt)
+ return 0;
+ return NMP_OBJECT_CAST_IP4_ROUTE (rt)->gateway;
+}
+
/*****************************************************************************/
static void
@@ -575,9 +585,6 @@ nm_ip4_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i
{
NMIP4Config *self;
NMIP4ConfigPrivate *priv;
- guint32 lowest_metric;
- guint32 old_gateway = 0;
- gboolean old_has_gateway = FALSE;
const NMDedupMultiHeadEntry *head_entry;
NMDedupMultiIter iter;
const NMPObject *plobj = NULL;
@@ -614,6 +621,7 @@ nm_ip4_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i
sort_captured_addresses,
NULL);
has_addresses = TRUE;
+ _notify_addresses (self);
}
head_entry = nm_platform_lookup_addrroute (platform,
@@ -621,31 +629,15 @@ nm_ip4_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i
ifindex);
/* Extract gateway from default route */
- old_gateway = priv->gateway;
- old_has_gateway = priv->has_gateway;
-
- lowest_metric = G_MAXUINT32;
- priv->has_gateway = FALSE;
- nmp_cache_iter_for_each (&iter, head_entry, &plobj) {
- const NMPlatformIP4Route *route = NMP_OBJECT_CAST_IP4_ROUTE (plobj);
-
- if ( !route->table_coerced
- && NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)
- && route->rt_source != NM_IP_CONFIG_SOURCE_RTPROT_KERNEL) {
- if (route->metric < lowest_metric) {
- priv->gateway = route->gateway;
- lowest_metric = route->metric;
- }
- priv->has_gateway = TRUE;
- }
-
+ nmp_cache_iter_for_each (&iter, head_entry, &plobj)
_add_route (self, plobj, NULL, NULL);
- }
/* If the interface has the default route, and has IPv4 addresses, capture
* nameservers from /etc/resolv.conf.
*/
- if (has_addresses && priv->has_gateway && capture_resolv_conf) {
+ if ( has_addresses
+ && priv->best_default_route
+ && capture_resolv_conf) {
gs_free char *rc_contents = NULL;
if (g_file_get_contents (_PATH_RESCONF, &rc_contents, NULL, NULL)) {
@@ -657,25 +649,19 @@ nm_ip4_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i
}
}
- /* actually, nobody should be connected to the signal, just to be sure, notify */
- _notify_addresses (self);
- _notify_routes (self);
- if ( priv->gateway != old_gateway
- || priv->has_gateway != old_has_gateway)
- _notify (self, PROP_GATEWAY);
-
return self;
}
void
-nm_ip4_config_add_device_routes (NMIP4Config *self,
- guint32 route_table,
- guint32 route_metric,
- GPtrArray **out_ip4_dev_route_blacklist)
+nm_ip4_config_add_dependent_routes (NMIP4Config *self,
+ guint32 route_table,
+ guint32 route_metric,
+ GPtrArray **out_ip4_dev_route_blacklist)
{
const NMIP4ConfigPrivate *priv;
GPtrArray *ip4_dev_route_blacklist = NULL;
- const NMPlatformIP4Address *addr;
+ const NMPlatformIP4Address *my_addr;
+ const NMPlatformIP4Route *my_route;
int ifindex;
NMDedupMultiIter iter;
@@ -689,18 +675,18 @@ nm_ip4_config_add_device_routes (NMIP4Config *self,
/* For IPv6 slaac, we explicitly add the device-routes (onlink) to NMIP6Config.
* As we don't do that for IPv4 (and manual IPv6 addresses), add them explicitly. */
- nm_ip_config_iter_ip4_address_for_each (&iter, self, &addr) {
+ nm_ip_config_iter_ip4_address_for_each (&iter, self, &my_addr) {
nm_auto_nmpobj NMPObject *r = NULL;
NMPlatformIP4Route *route;
in_addr_t network;
- if (addr->plen == 0)
+ if (my_addr->plen == 0)
continue;
- nm_assert (addr->plen <= 32);
+ nm_assert (my_addr->plen <= 32);
/* The destination network depends on the peer-address. */
- network = nm_utils_ip4_address_clear_host_address (addr->peer_address, addr->plen);
+ network = nm_utils_ip4_address_clear_host_address (my_addr->peer_address, my_addr->plen);
if (_ipv4_is_zeronet (network)) {
/* Kernel doesn't add device-routes for destinations that
@@ -714,8 +700,8 @@ nm_ip4_config_add_device_routes (NMIP4Config *self,
route->ifindex = ifindex;
route->rt_source = NM_IP_CONFIG_SOURCE_KERNEL;
route->network = network;
- route->plen = addr->plen;
- route->pref_src = addr->address;
+ route->plen = my_addr->plen;
+ route->pref_src = my_addr->address;
route->table_coerced = nm_platform_route_table_coerce (route_table);
route->metric = route_metric;
route->scope_inv = nm_platform_route_scope_inv (NM_RT_SCOPE_LINK);
@@ -755,6 +741,27 @@ nm_ip4_config_add_device_routes (NMIP4Config *self,
}
}
+again:
+ nm_ip_config_iter_ip4_route_for_each (&iter, self, &my_route) {
+ NMPlatformIP4Route rt;
+
+ if ( !NM_PLATFORM_IP_ROUTE_IS_DEFAULT (my_route)
+ || my_route->gateway == 0
+ || NM_IS_IP_CONFIG_SOURCE_RTPROT (my_route->rt_source)
+ || nm_ip4_config_get_direct_route_for_host (self,
+ my_route->gateway,
+ nm_platform_route_table_uncoerce (my_route->table_coerced, TRUE)))
+ continue;
+
+ rt = *my_route;
+ rt.network = my_route->gateway;
+ rt.plen = 32;
+ rt.gateway = 0;
+ _add_route (self, NULL, &rt, NULL);
+ /* adding the route might have invalidated the iteration. Start again. */
+ goto again;
+ }
+
NM_SET_OUT (out_ip4_dev_route_blacklist, ip4_dev_route_blacklist);
}
@@ -848,6 +855,8 @@ nm_ip4_config_merge_setting (NMIP4Config *self,
NMIP4ConfigPrivate *priv;
guint naddresses, nroutes, nnameservers, nsearches;
int i, priority;
+ const char *gateway_str;
+ guint32 gateway_bin;
if (!setting)
return;
@@ -864,15 +873,18 @@ nm_ip4_config_merge_setting (NMIP4Config *self,
nsearches = nm_setting_ip_config_get_num_dns_searches (setting);
/* Gateway */
- if (nm_setting_ip_config_get_never_default (setting))
- nm_ip4_config_set_never_default (self, TRUE);
- else if (nm_setting_ip_config_get_ignore_auto_routes (setting))
- nm_ip4_config_set_never_default (self, FALSE);
- if (nm_setting_ip_config_get_gateway (setting)) {
- guint32 gateway;
+ if ( !nm_setting_ip_config_get_never_default (setting)
+ && (gateway_str = nm_setting_ip_config_get_gateway (setting))
+ && inet_pton (AF_INET, gateway_str, &gateway_bin) == 1
+ && gateway_bin) {
+ const NMPlatformIP4Route r = {
+ .rt_source = NM_IP_CONFIG_SOURCE_USER,
+ .gateway = gateway_bin,
+ .table_coerced = nm_platform_route_table_coerce (route_table),
+ .metric = route_metric,
+ };
- inet_pton (AF_INET, nm_setting_ip_config_get_gateway (setting), &gateway);
- nm_ip4_config_set_gateway (self, gateway);
+ _add_route (self, NULL, &r, NULL);
}
/* Addresses */
@@ -961,8 +973,8 @@ nm_ip4_config_merge_setting (NMIP4Config *self,
NMSetting *
nm_ip4_config_create_setting (const NMIP4Config *self)
{
+ const NMIP4ConfigPrivate *priv;
NMSettingIPConfig *s_ip4;
- guint32 gateway;
guint nnameservers, nsearches, noptions;
const char *method = NULL;
int i;
@@ -979,7 +991,8 @@ nm_ip4_config_create_setting (const NMIP4Config *self)
return NM_SETTING (s_ip4);
}
- gateway = nm_ip4_config_get_gateway (self);
+ priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+
nnameservers = nm_ip4_config_get_num_nameservers (self);
nsearches = nm_ip4_config_get_num_searches (self);
noptions = nm_ip4_config_get_num_dns_options (self);
@@ -1007,10 +1020,12 @@ nm_ip4_config_create_setting (const NMIP4Config *self)
}
/* Gateway */
- if ( nm_ip4_config_has_gateway (self)
+ if ( priv->best_default_route
&& nm_setting_ip_config_get_num_addresses (s_ip4) > 0) {
g_object_set (s_ip4,
- NM_SETTING_IP_CONFIG_GATEWAY, nm_utils_inet4_ntop (gateway, NULL),
+ NM_SETTING_IP_CONFIG_GATEWAY,
+ nm_utils_inet4_ntop (NMP_OBJECT_CAST_IP4_ROUTE (priv->best_default_route)->gateway,
+ NULL),
NULL);
}
@@ -1070,7 +1085,10 @@ nm_ip4_config_create_setting (const NMIP4Config *self)
/*****************************************************************************/
void
-nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src, NMIPConfigMergeFlags merge_flags)
+nm_ip4_config_merge (NMIP4Config *dst,
+ const NMIP4Config *src,
+ NMIPConfigMergeFlags merge_flags,
+ guint32 default_route_metric_penalty)
{
NMIP4ConfigPrivate *dst_priv;
const NMIP4ConfigPrivate *src_priv;
@@ -1096,14 +1114,24 @@ nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src, NMIPConfigMergeFl
nm_ip4_config_add_nameserver (dst, nm_ip4_config_get_nameserver (src, i));
}
- /* default gateway */
- if (nm_ip4_config_has_gateway (src))
- nm_ip4_config_set_gateway (dst, nm_ip4_config_get_gateway (src));
-
/* routes */
if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_ROUTES)) {
- nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, src, NULL)
+ const NMPlatformIP4Route *r_src;
+
+ nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, src, &r_src) {
+ if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (r_src)) {
+ if (NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES))
+ continue;
+ if (default_route_metric_penalty) {
+ NMPlatformIP4Route r = *r_src;
+
+ r.metric = nm_utils_ip_route_metric_penalize (AF_INET, r.metric, default_route_metric_penalty);
+ _add_route (dst, NULL, &r, NULL);
+ continue;
+ }
+ }
_add_route (dst, ipconf_iter.current->obj, NULL, NULL);
+ }
}
/* domains */
@@ -1255,11 +1283,17 @@ _wins_get_index (const NMIP4Config *self, guint32 wins_server)
* nm_ip4_config_subtract:
* @dst: config from which to remove everything in @src
* @src: config to remove from @dst
+ * @default_route_metric_penalty: pretend that on source we applied
+ * a route penalty on the default-route. It means, for default routes
+ * we don't remove routes that match exactly, but those with a lower
+ * metric (with the penalty removed).
*
* Removes everything in @src from @dst.
*/
void
-nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src)
+nm_ip4_config_subtract (NMIP4Config *dst,
+ const NMIP4Config *src,
+ guint32 default_route_metric_penalty)
{
NMIP4ConfigPrivate *dst_priv;
guint i;
@@ -1296,23 +1330,31 @@ nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src)
nm_ip4_config_del_nameserver (dst, idx);
}
- /* default gateway */
- if ( (nm_ip4_config_has_gateway (src) == nm_ip4_config_has_gateway (dst))
- && (nm_ip4_config_get_gateway (src) == nm_ip4_config_get_gateway (dst)))
- nm_ip4_config_unset_gateway (dst);
-
- if (!nm_ip4_config_get_num_addresses (dst))
- nm_ip4_config_unset_gateway (dst);
-
/* routes */
changed = FALSE;
changed_default_route = FALSE;
nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, src, &r) {
+ const NMPObject *o_src = NMP_OBJECT_UP_CAST (r);
+ NMPObject o_lookup_copy;
+ const NMPObject *o_lookup;
nm_auto_nmpobj const NMPObject *obj_old = NULL;
+ if ( NM_PLATFORM_IP_ROUTE_IS_DEFAULT (r)
+ && default_route_metric_penalty) {
+ NMPlatformIP4Route *rr;
+
+ /* the default route was penalized when merging it to the combined ip-config.
+ * When subtracting the routes, we must re-do that process when comparing
+ * the routes. */
+ o_lookup = nmp_object_stackinit_obj (&o_lookup_copy, o_src);
+ rr = NMP_OBJECT_CAST_IP4_ROUTE (&o_lookup_copy);
+ rr->metric = nm_utils_ip_route_metric_penalize (AF_INET, rr->metric, default_route_metric_penalty);
+ } else
+ o_lookup = o_src;
+
if (nm_dedup_multi_index_remove_obj (dst_priv->multi_idx,
&dst_priv->idx_ip4_routes,
- NMP_OBJECT_UP_CAST (r),
+ o_lookup,
(gconstpointer *) &obj_old)) {
if (dst_priv->best_default_route == obj_old) {
nm_clear_nmp_object (&dst_priv->best_default_route);
@@ -1322,8 +1364,9 @@ nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src)
}
}
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 (_nm_ip_config_best_default_route_set (&dst_priv->best_default_route,
+ _nm_ip4_config_best_default_route_find (dst)))
+ _notify (dst, PROP_GATEWAY);
}
if (changed)
_notify_routes (dst);
@@ -1379,7 +1422,9 @@ nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src)
}
void
-nm_ip4_config_intersect (NMIP4Config *dst, const NMIP4Config *src)
+nm_ip4_config_intersect (NMIP4Config *dst,
+ const NMIP4Config *src,
+ guint32 default_route_metric_penalty)
{
NMIP4ConfigPrivate *dst_priv;
const NMIP4ConfigPrivate *src_priv;
@@ -1415,23 +1460,31 @@ nm_ip4_config_intersect (NMIP4Config *dst, const NMIP4Config *src)
/* ignore nameservers */
- /* default gateway */
- if ( !nm_ip4_config_get_num_addresses (dst)
- || (nm_ip4_config_has_gateway (src) != nm_ip4_config_has_gateway (dst))
- || (nm_ip4_config_get_gateway (src) != nm_ip4_config_get_gateway (dst))) {
- nm_ip4_config_unset_gateway (dst);
- }
-
/* 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);
+ const NMPObject *o_dst = NMP_OBJECT_UP_CAST (r);
+ const NMPObject *o_lookup;
+ NMPObject o_lookup_copy;
+
+ if ( NM_PLATFORM_IP_ROUTE_IS_DEFAULT (r)
+ && default_route_metric_penalty) {
+ NMPlatformIP4Route *rr;
+
+ /* the default route was penalized when merging it to the combined ip-config.
+ * When intersecting the routes, we must re-do that process when comparing
+ * the routes. */
+ o_lookup = nmp_object_stackinit_obj (&o_lookup_copy, o_dst);
+ rr = NMP_OBJECT_CAST_IP4_ROUTE (&o_lookup_copy);
+ rr->metric = nm_utils_ip_route_metric_penalize (AF_INET, rr->metric, default_route_metric_penalty);
+ } else
+ o_lookup = o_dst;
if (nm_dedup_multi_index_lookup_obj (src_priv->multi_idx,
&src_priv->idx_ip4_routes,
- o)) {
- new_best_default_route = _nm_ip_config_best_default_route_find_better (new_best_default_route, o);
+ o_lookup)) {
+ new_best_default_route = _nm_ip_config_best_default_route_find_better (new_best_default_route, o_dst);
continue;
}
@@ -1440,8 +1493,10 @@ nm_ip4_config_intersect (NMIP4Config *dst, const NMIP4Config *src)
nm_assert_not_reached ();
changed = TRUE;
}
- if (_nm_ip_config_best_default_route_set (&dst_priv->best_default_route, new_best_default_route))
+ if (_nm_ip_config_best_default_route_set (&dst_priv->best_default_route, new_best_default_route)) {
nm_assert (changed);
+ _notify (dst, PROP_GATEWAY);
+ }
if (changed)
_notify_routes (dst);
@@ -1502,22 +1557,6 @@ nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relev
has_minor_changes = TRUE;
}
- /* never_default */
- if (src_priv->never_default != dst_priv->never_default) {
- dst_priv->never_default = src_priv->never_default;
- has_minor_changes = TRUE;
- }
-
- /* default gateway */
- if ( src_priv->gateway != dst_priv->gateway
- || src_priv->has_gateway != dst_priv->has_gateway) {
- if (src_priv->has_gateway)
- nm_ip4_config_set_gateway (dst, src_priv->gateway);
- else
- nm_ip4_config_unset_gateway (dst);
- has_relevant_changes = TRUE;
- }
-
/* addresses */
head_entry_src = nm_ip4_config_lookup_addresses (src);
nm_dedup_multi_iter_init (&ipconf_iter_src, head_entry_src);
@@ -1615,7 +1654,8 @@ nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relev
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);
+ if (_nm_ip_config_best_default_route_set (&dst_priv->best_default_route, new_best_default_route))
+ _notify (dst, PROP_GATEWAY);
_notify_routes (dst);
}
@@ -1794,12 +1834,6 @@ nm_ip4_config_dump (const NMIP4Config *self, const char *detail)
nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, self, &address)
g_message (" a: %s", nm_platform_ip4_address_to_string (address, NULL, 0));
- /* default gateway */
- if (nm_ip4_config_has_gateway (self)) {
- tmp = nm_ip4_config_get_gateway (self);
- g_message (" gw: %s", nm_utils_inet4_ntop (tmp, NULL));
- }
-
/* nameservers */
for (i = 0; i < nm_ip4_config_get_num_nameservers (self); i++) {
tmp = nm_ip4_config_get_nameserver (self, i);
@@ -1840,102 +1874,9 @@ nm_ip4_config_dump (const NMIP4Config *self, const char *detail)
g_message (" wins: %s", nm_utils_inet4_ntop (tmp, NULL));
}
- g_message (" n-dflt: %d", nm_ip4_config_get_never_default (self));
g_message (" mtrd: %d", (int) nm_ip4_config_get_metered (self));
}
-gboolean
-nm_ip4_config_destination_is_direct (const NMIP4Config *self, guint32 network, guint8 plen)
-{
- const NMPlatformIP4Address *item;
- in_addr_t peer_network;
- NMDedupMultiIter iter;
-
- nm_ip_config_iter_ip4_address_for_each (&iter, self, &item) {
- if (item->plen > plen)
- continue;
-
- peer_network = nm_utils_ip4_address_clear_host_address (item->peer_address, item->plen);
- if (_ipv4_is_zeronet (peer_network))
- continue;
-
- if (peer_network != nm_utils_ip4_address_clear_host_address (network, item->plen))
- continue;
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-/*****************************************************************************/
-
-void
-nm_ip4_config_set_never_default (NMIP4Config *self, gboolean never_default)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
-
- priv->never_default = never_default;
-}
-
-gboolean
-nm_ip4_config_get_never_default (const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
-
- return priv->never_default;
-}
-
-void
-nm_ip4_config_set_gateway (NMIP4Config *self, guint32 gateway)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
-
- if (priv->gateway != gateway || !priv->has_gateway) {
- priv->gateway = gateway;
- priv->has_gateway = TRUE;
- _notify (self, PROP_GATEWAY);
- }
-}
-
-void
-nm_ip4_config_unset_gateway (NMIP4Config *self)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
-
- if (priv->has_gateway) {
- priv->gateway = 0;
- priv->has_gateway = FALSE;
- _notify (self, PROP_GATEWAY);
- }
-}
-
-/**
- * nm_ip4_config_has_gateway:
- * @self: the #NMIP4Config object
- *
- * NetworkManager's handling of default-routes is limited and usually a default-route
- * cannot have gateway 0.0.0.0. For peer-to-peer routes, we still want to
- * support that, so we need to differenciate between no-default-route and a
- * on-link-default route. Hence nm_ip4_config_has_gateway().
- *
- * Returns: whether the object has a gateway explicitly set. */
-gboolean
-nm_ip4_config_has_gateway (const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
-
- return priv->has_gateway;
-}
-
-guint32
-nm_ip4_config_get_gateway (const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
-
- return priv->gateway;
-}
-
/*****************************************************************************/
void
@@ -2108,8 +2049,9 @@ _add_route (NMIP4Config *self,
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));
+ if (_nm_ip_config_best_default_route_merge (&priv->best_default_route, obj_new_2))
+ _notify (self, PROP_GATEWAY);
_notify_routes (self);
} else
NM_SET_OUT (out_obj_new, nmp_object_ref (obj_new_2));
@@ -2178,7 +2120,9 @@ _nmtst_ip4_config_get_route (const NMIP4Config *self, guint i)
}
const NMPlatformIP4Route *
-nm_ip4_config_get_direct_route_for_host (const NMIP4Config *self, guint32 host)
+nm_ip4_config_get_direct_route_for_host (const NMIP4Config *self,
+ in_addr_t host,
+ guint32 route_table)
{
const NMPlatformIP4Route *best_route = NULL;
const NMPlatformIP4Route *item;
@@ -2193,6 +2137,9 @@ nm_ip4_config_get_direct_route_for_host (const NMIP4Config *self, guint32 host)
if (best_route && best_route->plen > item->plen)
continue;
+ if (nm_platform_route_table_uncoerce (item->table_coerced, TRUE) != route_table)
+ continue;
+
if (nm_utils_ip4_address_clear_host_address (host, item->plen) != nm_utils_ip4_address_clear_host_address (item->network, item->plen))
continue;
@@ -2704,8 +2651,9 @@ nm_ip4_config_nmpobj_remove (NMIP4Config *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));
+ if (_nm_ip_config_best_default_route_set (&priv->best_default_route,
+ _nm_ip4_config_best_default_route_find (self)))
+ _notify (self, PROP_GATEWAY);
}
_notify_routes (self);
break;
@@ -2736,9 +2684,6 @@ nm_ip4_config_hash (const NMIP4Config *self, GChecksum *sum, gboolean dns_only)
g_return_if_fail (sum);
if (!dns_only) {
- hash_u32 (sum, nm_ip4_config_has_gateway (self));
- hash_u32 (sum, nm_ip4_config_get_gateway (self));
-
nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, self, &address) {
hash_u32 (sum, address->address);
hash_u32 (sum, address->plen);
@@ -2893,7 +2838,10 @@ get_property (GObject *object, guint prop_id,
const guint32 dbus_addr[3] = {
address->address,
address->plen,
- i == 0 ? priv->gateway : 0,
+ ( i == 0
+ && priv->best_default_route)
+ ? NMP_OBJECT_CAST_IP4_ROUTE (priv->best_default_route)->gateway
+ : (guint32) 0,
};
g_variant_builder_add (&builder_legacy, "@au",
@@ -2978,9 +2926,11 @@ out_routes_cached:
priv->routes_variant);
break;
case PROP_GATEWAY:
- if (priv->has_gateway)
- g_value_set_string (value, nm_utils_inet4_ntop (priv->gateway, NULL));
- else
+ if (priv->best_default_route) {
+ g_value_set_string (value,
+ nm_utils_inet4_ntop (NMP_OBJECT_CAST_IP4_ROUTE (priv->best_default_route)->gateway,
+ NULL));
+ } else
g_value_set_string (value, NULL);
break;
case PROP_NAMESERVERS:
diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h
index 775869cd20..978471df29 100644
--- a/src/nm-ip4-config.h
+++ b/src/nm-ip4-config.h
@@ -80,12 +80,16 @@ 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 whether @obj is considered a default-route.
+ *
+ * NMIP4Config/NMIP6Config tracks the (best) default-route explicitly, because
+ * at various places we act differently depending on whether there is a default-route
+ * configured.
+ *
+ * Note that this only considers the main routing table. */
return r
- && !r->table_coerced
- && NM_PLATFORM_IP_ROUTE_IS_DEFAULT (r);
+ && NM_PLATFORM_IP_ROUTE_IS_DEFAULT (r)
+ && nm_platform_route_table_is_main (r->table_coerced);
}
const NMPObject *_nm_ip_config_best_default_route_find_better (const NMPObject *obj_cur, const NMPObject *obj_cmp);
@@ -151,10 +155,10 @@ NMDedupMultiIndex *nm_ip4_config_get_multi_idx (const NMIP4Config *self);
NMIP4Config *nm_ip4_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int ifindex, gboolean capture_resolv_conf);
-void nm_ip4_config_add_device_routes (NMIP4Config *self,
- guint32 route_table,
- guint32 route_metric,
- GPtrArray **out_ip4_dev_route_blacklist);
+void nm_ip4_config_add_dependent_routes (NMIP4Config *self,
+ guint32 route_table,
+ guint32 route_metric,
+ GPtrArray **out_ip4_dev_route_blacklist);
gboolean nm_ip4_config_commit (const NMIP4Config *self,
NMPlatform *platform,
@@ -167,24 +171,24 @@ void nm_ip4_config_merge_setting (NMIP4Config *self,
NMSetting *nm_ip4_config_create_setting (const NMIP4Config *self);
-void nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src, NMIPConfigMergeFlags merge_flags);
-void nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src);
-void nm_ip4_config_intersect (NMIP4Config *dst, const NMIP4Config *src);
+void nm_ip4_config_merge (NMIP4Config *dst,
+ const NMIP4Config *src,
+ NMIPConfigMergeFlags merge_flags,
+ guint32 default_route_metric_penalty);
+void nm_ip4_config_subtract (NMIP4Config *dst,
+ const NMIP4Config *src,
+ guint32 default_route_metric_penalty);
+void nm_ip4_config_intersect (NMIP4Config *dst,
+ const NMIP4Config *src,
+ guint32 default_route_metric_penalty);
gboolean nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relevant_changes);
-gboolean nm_ip4_config_destination_is_direct (const NMIP4Config *self, guint32 dest, guint8 plen);
void nm_ip4_config_dump (const NMIP4Config *self, const char *detail);
-
-void nm_ip4_config_set_never_default (NMIP4Config *self, gboolean never_default);
-gboolean nm_ip4_config_get_never_default (const NMIP4Config *self);
-void nm_ip4_config_set_gateway (NMIP4Config *self, guint32 gateway);
-void nm_ip4_config_unset_gateway (NMIP4Config *self);
-gboolean nm_ip4_config_has_gateway (const NMIP4Config *self);
-guint32 nm_ip4_config_get_gateway (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);
+in_addr_t nmtst_ip4_config_get_gateway (NMIP4Config *config);
+
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);
@@ -203,7 +207,9 @@ void _nmtst_ip4_config_del_route (NMIP4Config *self, guint i);
guint nm_ip4_config_get_num_routes (const NMIP4Config *self);
const NMPlatformIP4Route *_nmtst_ip4_config_get_route (const NMIP4Config *self, guint i);
-const NMPlatformIP4Route *nm_ip4_config_get_direct_route_for_host (const NMIP4Config *self, guint32 host);
+const NMPlatformIP4Route *nm_ip4_config_get_direct_route_for_host (const NMIP4Config *self,
+ in_addr_t host,
+ guint32 route_table);
void nm_ip4_config_reset_nameservers (NMIP4Config *self);
void nm_ip4_config_add_nameserver (NMIP4Config *self, guint32 nameserver);
diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c
index 75c1515acb..15fad285f8 100644
--- a/src/nm-ip6-config.c
+++ b/src/nm-ip6-config.c
@@ -58,11 +58,9 @@ _route_valid (const NMPlatformIP6Route *r)
/*****************************************************************************/
typedef struct {
- bool never_default:1;
int ifindex;
int dns_priority;
NMSettingIP6ConfigPrivacy privacy;
- struct in6_addr gateway;
GArray *nameservers;
GPtrArray *domains;
GPtrArray *searches;
@@ -202,6 +200,22 @@ _nm_ip6_config_best_default_route_find (const NMIP6Config *self)
return new_best_default_route;
}
+const struct in6_addr *
+nmtst_ip6_config_get_gateway (const NMIP6Config *self)
+{
+ const NMPObject *rt;
+ const struct in6_addr *r;
+
+ g_assert (NM_IS_IP6_CONFIG (self));
+
+ rt = nm_ip6_config_best_default_route_get (self);
+ if (!rt)
+ return NULL;
+
+ r = &NMP_OBJECT_CAST_IP6_ROUTE (rt)->gateway;
+ return IN6_IS_ADDR_UNSPECIFIED (r) ? NULL : r;
+}
+
/*****************************************************************************/
static void
@@ -372,9 +386,6 @@ nm_ip6_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i
{
NMIP6Config *self;
NMIP6ConfigPrivate *priv;
- guint32 lowest_metric = G_MAXUINT32;
- struct in6_addr old_gateway = IN6ADDR_ANY_INIT;
- gboolean has_gateway;
const NMDedupMultiHeadEntry *head_entry;
NMDedupMultiIter iter;
const NMPObject *plobj = NULL;
@@ -411,37 +422,22 @@ nm_ip6_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i
nm_dedup_multi_head_entry_sort (head_entry,
sort_captured_addresses,
GINT_TO_POINTER (use_temporary));
+ _notify_addresses (self);
}
head_entry = nm_platform_lookup_addrroute (platform,
NMP_OBJECT_TYPE_IP6_ROUTE,
ifindex);
- /* Extract gateway from default route */
- old_gateway = priv->gateway;
-
- lowest_metric = G_MAXUINT32;
- has_gateway = FALSE;
- nmp_cache_iter_for_each (&iter, head_entry, &plobj) {
- const NMPlatformIP6Route *route = NMP_OBJECT_CAST_IP6_ROUTE (plobj);
-
- if ( !route->table_coerced
- && NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)
- && route->rt_source != NM_IP_CONFIG_SOURCE_RTPROT_KERNEL) {
- if (route->metric < lowest_metric) {
- priv->gateway = route->gateway;
- lowest_metric = route->metric;
- }
- has_gateway = TRUE;
- }
-
+ nmp_cache_iter_for_each (&iter, head_entry, &plobj)
_add_route (self, plobj, NULL, NULL);
- }
/* If the interface has the default route, and has IPv6 addresses, capture
* nameservers from /etc/resolv.conf.
*/
- if (has_addresses && has_gateway && capture_resolv_conf) {
+ if ( has_addresses
+ && priv->best_default_route
+ && capture_resolv_conf) {
gs_free char *rc_contents = NULL;
if (g_file_get_contents (_PATH_RESCONF, &rc_contents, NULL, NULL)) {
@@ -453,22 +449,17 @@ nm_ip6_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i
}
}
- /* actually, nobody should be connected to the signal, just to be sure, notify */
- _notify_addresses (self);
- _notify_routes (self);
- if (!IN6_ARE_ADDR_EQUAL (&priv->gateway, &old_gateway))
- _notify (self, PROP_GATEWAY);
-
return self;
}
void
-nm_ip6_config_add_device_routes (NMIP6Config *self,
- guint32 route_table,
- guint32 route_metric)
+nm_ip6_config_add_dependent_routes (NMIP6Config *self,
+ guint32 route_table,
+ guint32 route_metric)
{
const NMIP6ConfigPrivate *priv;
- const NMPlatformIP6Address *addr;
+ const NMPlatformIP6Address *my_addr;
+ const NMPlatformIP6Route *my_route;
int ifindex;
NMDedupMultiIter iter;
@@ -484,21 +475,21 @@ nm_ip6_config_add_device_routes (NMIP6Config *self,
*
* For manually added IPv6 routes, add the device routes explicitly. */
- nm_ip_config_iter_ip6_address_for_each (&iter, self, &addr) {
+ nm_ip_config_iter_ip6_address_for_each (&iter, self, &my_addr) {
NMPObject *r;
NMPlatformIP6Route *route;
gboolean has_peer;
int routes_n, routes_i;
- if (NM_FLAGS_HAS (addr->n_ifa_flags, IFA_F_NOPREFIXROUTE))
+ if (NM_FLAGS_HAS (my_addr->n_ifa_flags, IFA_F_NOPREFIXROUTE))
continue;
- has_peer = !IN6_IS_ADDR_UNSPECIFIED (&addr->peer_address);
+ has_peer = !IN6_IS_ADDR_UNSPECIFIED (&my_addr->peer_address);
/* If we have an IPv6 peer, we add two /128 routes
* (unless, both addresses are identical). */
routes_n = ( has_peer
- && !IN6_ARE_ADDR_EQUAL (&addr->address, &addr->peer_address))
+ && !IN6_ARE_ADDR_EQUAL (&my_addr->address, &my_addr->peer_address))
? 2 : 1;
for (routes_i = 0; routes_i < routes_n; routes_i++) {
@@ -513,13 +504,13 @@ nm_ip6_config_add_device_routes (NMIP6Config *self,
if (has_peer) {
if (routes_i == 0)
- route->network = addr->address;
+ route->network = my_addr->address;
else
- route->network = addr->peer_address;
+ route->network = my_addr->peer_address;
route->plen = 128;
} else {
- nm_utils_ip6_address_clear_host_address (&route->network, &addr->address, addr->plen);
- route->plen = addr->plen;
+ nm_utils_ip6_address_clear_host_address (&route->network, &my_addr->address, my_addr->plen);
+ route->plen = my_addr->plen;
}
nm_platform_ip_route_normalize (AF_INET6, (NMPlatformIPRoute *) route);
@@ -533,6 +524,27 @@ nm_ip6_config_add_device_routes (NMIP6Config *self,
_add_route (self, r, NULL, NULL);
}
}
+
+again:
+ nm_ip_config_iter_ip6_route_for_each (&iter, self, &my_route) {
+ NMPlatformIP6Route rt;
+
+ if ( !NM_PLATFORM_IP_ROUTE_IS_DEFAULT (my_route)
+ || IN6_IS_ADDR_UNSPECIFIED (&my_route->gateway)
+ || NM_IS_IP_CONFIG_SOURCE_RTPROT (my_route->rt_source)
+ || nm_ip6_config_get_direct_route_for_host (self,
+ &my_route->gateway,
+ nm_platform_route_table_uncoerce (my_route->table_coerced, TRUE)))
+ continue;
+
+ rt = *my_route;
+ rt.network = my_route->gateway;
+ rt.plen = 128;
+ rt.gateway = in6addr_any;
+ _add_route (self, NULL, &rt, NULL);
+ /* adding the route might have invalidated the iteration. Start again. */
+ goto again;
+ }
}
gboolean
@@ -644,6 +656,7 @@ nm_ip6_config_merge_setting (NMIP6Config *self,
NMIP6ConfigPrivate *priv;
guint naddresses, nroutes, nnameservers, nsearches;
const char *gateway_str;
+ struct in6_addr gateway_bin;
int i, priority;
if (!setting)
@@ -661,16 +674,18 @@ nm_ip6_config_merge_setting (NMIP6Config *self,
g_object_freeze_notify (G_OBJECT (self));
/* Gateway */
- if (nm_setting_ip_config_get_never_default (setting))
- nm_ip6_config_set_never_default (self, TRUE);
- else if (nm_setting_ip_config_get_ignore_auto_routes (setting))
- nm_ip6_config_set_never_default (self, FALSE);
- gateway_str = nm_setting_ip_config_get_gateway (setting);
- if (gateway_str) {
- struct in6_addr gateway;
+ if ( !nm_setting_ip_config_get_never_default (setting)
+ && (gateway_str = nm_setting_ip_config_get_gateway (setting))
+ && inet_pton (AF_INET6, gateway_str, &gateway_bin) == 1
+ && !IN6_IS_ADDR_UNSPECIFIED (&gateway_bin)) {
+ const NMPlatformIP6Route r = {
+ .rt_source = NM_IP_CONFIG_SOURCE_USER,
+ .gateway = gateway_bin,
+ .table_coerced = nm_platform_route_table_coerce (route_table),
+ .metric = route_metric,
+ };
- inet_pton (AF_INET6, gateway_str, &gateway);
- nm_ip6_config_set_gateway (self, &gateway);
+ _add_route (self, NULL, &r, NULL);
}
/* Addresses */
@@ -753,8 +768,8 @@ nm_ip6_config_merge_setting (NMIP6Config *self,
NMSetting *
nm_ip6_config_create_setting (const NMIP6Config *self)
{
+ const NMIP6ConfigPrivate *priv;
NMSettingIPConfig *s_ip6;
- const struct in6_addr *gateway;
guint nnameservers, nsearches, noptions;
const char *method = NULL;
int i;
@@ -771,7 +786,8 @@ nm_ip6_config_create_setting (const NMIP6Config *self)
return NM_SETTING (s_ip6);
}
- gateway = nm_ip6_config_get_gateway (self);
+ priv = NM_IP6_CONFIG_GET_PRIVATE (self);
+
nnameservers = nm_ip6_config_get_num_nameservers (self);
nsearches = nm_ip6_config_get_num_searches (self);
noptions = nm_ip6_config_get_num_dns_options (self);
@@ -803,10 +819,12 @@ nm_ip6_config_create_setting (const NMIP6Config *self)
}
/* Gateway */
- if ( gateway
+ if ( priv->best_default_route
&& nm_setting_ip_config_get_num_addresses (s_ip6) > 0) {
g_object_set (s_ip6,
- NM_SETTING_IP_CONFIG_GATEWAY, nm_utils_inet6_ntop (gateway, NULL),
+ NM_SETTING_IP_CONFIG_GATEWAY,
+ nm_utils_inet6_ntop (&NMP_OBJECT_CAST_IP6_ROUTE (priv->best_default_route)->gateway,
+ NULL),
NULL);
}
@@ -869,7 +887,10 @@ nm_ip6_config_create_setting (const NMIP6Config *self)
/*****************************************************************************/
void
-nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src, NMIPConfigMergeFlags merge_flags)
+nm_ip6_config_merge (NMIP6Config *dst,
+ const NMIP6Config *src,
+ NMIPConfigMergeFlags merge_flags,
+ guint32 default_route_metric_penalty)
{
NMIP6ConfigPrivate *dst_priv;
const NMIP6ConfigPrivate *src_priv;
@@ -895,14 +916,24 @@ nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src, NMIPConfigMergeFl
nm_ip6_config_add_nameserver (dst, nm_ip6_config_get_nameserver (src, i));
}
- /* default gateway */
- if (nm_ip6_config_get_gateway (src))
- nm_ip6_config_set_gateway (dst, nm_ip6_config_get_gateway (src));
-
/* routes */
if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_ROUTES)) {
- nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, src, NULL)
+ const NMPlatformIP6Route *r_src;
+
+ nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, src, &r_src) {
+ if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (r_src)) {
+ if (NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES))
+ continue;
+ if (default_route_metric_penalty) {
+ NMPlatformIP6Route r = *r_src;
+
+ r.metric = nm_utils_ip_route_metric_penalize (AF_INET6, r.metric, default_route_metric_penalty);
+ _add_route (dst, NULL, &r, NULL);
+ continue;
+ }
+ }
_add_route (dst, ipconf_iter.current->obj, NULL, NULL);
+ }
}
/* domains */
@@ -930,25 +961,6 @@ nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src, NMIPConfigMergeFl
g_object_thaw_notify (G_OBJECT (dst));
}
-gboolean
-nm_ip6_config_destination_is_direct (const NMIP6Config *self, const struct in6_addr *network, guint8 plen)
-{
- const NMPlatformIP6Address *item;
- NMDedupMultiIter iter;
-
- nm_assert (network);
- nm_assert (plen <= 128);
-
- nm_ip_config_iter_ip6_address_for_each (&iter, self, &item) {
- if ( item->plen <= plen
- && !NM_FLAGS_HAS (item->n_ifa_flags, IFA_F_NOPREFIXROUTE)
- && nm_utils_ip6_address_same_prefix (&item->address, network, item->plen))
- return TRUE;
- }
-
- return FALSE;
-}
-
/*****************************************************************************/
static int
@@ -1017,11 +1029,17 @@ _dns_options_get_index (const NMIP6Config *self, const char *option)
* nm_ip6_config_subtract:
* @dst: config from which to remove everything in @src
* @src: config to remove from @dst
- *
+ * @default_route_metric_penalty: pretend that on source we applied
+ * a route penalty on the default-route. It means, for default routes
+ * we don't remove routes that match exactly, but those with a lower
+ * metric (with the penalty removed).
+*
* Removes everything in @src from @dst.
*/
void
-nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src)
+nm_ip6_config_subtract (NMIP6Config *dst,
+ const NMIP6Config *src,
+ guint32 default_route_metric_penalty)
{
NMIP6ConfigPrivate *dst_priv;
guint i;
@@ -1029,7 +1047,6 @@ nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src)
const NMPlatformIP6Address *a;
const NMPlatformIP6Route *r;
NMDedupMultiIter ipconf_iter;
- const struct in6_addr *dst_tmp, *src_tmp;
gboolean changed;
gboolean changed_default_route;
@@ -1059,24 +1076,31 @@ nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src)
nm_ip6_config_del_nameserver (dst, idx);
}
- /* default gateway */
- src_tmp = nm_ip6_config_get_gateway (src);
- dst_tmp = nm_ip6_config_get_gateway (dst);
- if (src_tmp && dst_tmp && IN6_ARE_ADDR_EQUAL (src_tmp, dst_tmp))
- nm_ip6_config_set_gateway (dst, NULL);
-
- if (!nm_ip6_config_get_num_addresses (dst))
- nm_ip6_config_set_gateway (dst, NULL);
-
/* routes */
changed = FALSE;
changed_default_route = FALSE;
nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, src, &r) {
+ const NMPObject *o_src = NMP_OBJECT_UP_CAST (r);
+ NMPObject o_lookup_copy;
+ const NMPObject *o_lookup;
nm_auto_nmpobj const NMPObject *obj_old = NULL;
+ if ( NM_PLATFORM_IP_ROUTE_IS_DEFAULT (r)
+ && default_route_metric_penalty) {
+ NMPlatformIP6Route *rr;
+
+ /* the default route was penalized when merging it to the combined ip-config.
+ * When subtracting the routes, we must re-do that process when comparing
+ * the routes. */
+ o_lookup = nmp_object_stackinit_obj (&o_lookup_copy, o_src);
+ rr = NMP_OBJECT_CAST_IP6_ROUTE (&o_lookup_copy);
+ rr->metric = nm_utils_ip_route_metric_penalize (AF_INET6, rr->metric, default_route_metric_penalty);
+ } else
+ o_lookup = o_src;
+
if (nm_dedup_multi_index_remove_obj (dst_priv->multi_idx,
&dst_priv->idx_ip6_routes,
- NMP_OBJECT_UP_CAST (r),
+ o_lookup,
(gconstpointer *) &obj_old)) {
if (dst_priv->best_default_route == obj_old) {
nm_clear_nmp_object (&dst_priv->best_default_route);
@@ -1086,8 +1110,9 @@ nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src)
}
}
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 (_nm_ip_config_best_default_route_set (&dst_priv->best_default_route,
+ _nm_ip6_config_best_default_route_find (dst)))
+ _notify (dst, PROP_GATEWAY);
}
if (changed)
_notify_routes (dst);
@@ -1121,11 +1146,12 @@ nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src)
}
void
-nm_ip6_config_intersect (NMIP6Config *dst, const NMIP6Config *src)
+nm_ip6_config_intersect (NMIP6Config *dst,
+ const NMIP6Config *src,
+ guint32 default_route_metric_penalty)
{
NMIP6ConfigPrivate *dst_priv;
const NMIP6ConfigPrivate *src_priv;
- const struct in6_addr *dst_tmp, *src_tmp;
NMDedupMultiIter ipconf_iter;
const NMPlatformIP6Address *a;
const NMPlatformIP6Route *r;
@@ -1158,26 +1184,31 @@ nm_ip6_config_intersect (NMIP6Config *dst, const NMIP6Config *src)
/* ignore nameservers */
- /* default gateway */
- dst_tmp = nm_ip6_config_get_gateway (dst);
- if (dst_tmp) {
- src_tmp = nm_ip6_config_get_gateway (src);
- if ( !nm_ip6_config_get_num_addresses (dst)
- || !src_tmp
- || !IN6_ARE_ADDR_EQUAL (src_tmp, dst_tmp))
- nm_ip6_config_set_gateway (dst, NULL);
- }
-
/* 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);
+ const NMPObject *o_dst = NMP_OBJECT_UP_CAST (r);
+ const NMPObject *o_lookup;
+ NMPObject o_lookup_copy;
+
+ if ( NM_PLATFORM_IP_ROUTE_IS_DEFAULT (r)
+ && default_route_metric_penalty) {
+ NMPlatformIP6Route *rr;
+
+ /* the default route was penalized when merging it to the combined ip-config.
+ * When intersecting the routes, we must re-do that process when comparing
+ * the routes. */
+ o_lookup = nmp_object_stackinit_obj (&o_lookup_copy, o_dst);
+ rr = NMP_OBJECT_CAST_IP6_ROUTE (&o_lookup_copy);
+ rr->metric = nm_utils_ip_route_metric_penalize (AF_INET6, rr->metric, default_route_metric_penalty);
+ } else
+ o_lookup = o_dst;
if (nm_dedup_multi_index_lookup_obj (src_priv->multi_idx,
&src_priv->idx_ip6_routes,
- o)) {
- new_best_default_route = _nm_ip_config_best_default_route_find_better (new_best_default_route, o);
+ o_lookup)) {
+ new_best_default_route = _nm_ip_config_best_default_route_find_better (new_best_default_route, o_dst);
continue;
}
@@ -1186,8 +1217,10 @@ nm_ip6_config_intersect (NMIP6Config *dst, const NMIP6Config *src)
nm_assert_not_reached ();
changed = TRUE;
}
- if (_nm_ip_config_best_default_route_set (&dst_priv->best_default_route, new_best_default_route))
+ if (_nm_ip_config_best_default_route_set (&dst_priv->best_default_route, new_best_default_route)) {
nm_assert (changed);
+ _notify (dst, PROP_GATEWAY);
+ }
if (changed)
_notify_routes (dst);
@@ -1247,18 +1280,6 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev
has_minor_changes = TRUE;
}
- /* never_default */
- if (src_priv->never_default != dst_priv->never_default) {
- dst_priv->never_default = src_priv->never_default;
- has_minor_changes = TRUE;
- }
-
- /* default gateway */
- if (!IN6_ARE_ADDR_EQUAL (&src_priv->gateway, &dst_priv->gateway)) {
- nm_ip6_config_set_gateway (dst, &src_priv->gateway);
- has_relevant_changes = TRUE;
- }
-
/* addresses */
head_entry_src = nm_ip6_config_lookup_addresses (src);
nm_dedup_multi_iter_init (&ipconf_iter_src, head_entry_src);
@@ -1357,7 +1378,8 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev
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);
+ if (_nm_ip_config_best_default_route_set (&dst_priv->best_default_route, new_best_default_route))
+ _notify (dst, PROP_GATEWAY);
_notify_routes (dst);
}
@@ -1484,11 +1506,6 @@ nm_ip6_config_dump (const NMIP6Config *self, const char *detail)
nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, self, &address)
g_message (" a: %s", nm_platform_ip6_address_to_string (address, NULL, 0));
- /* default gateway */
- tmp = nm_ip6_config_get_gateway (self);
- if (tmp)
- g_message (" gw: %s", nm_utils_inet6_ntop (tmp, NULL));
-
/* nameservers */
for (i = 0; i < nm_ip6_config_get_num_nameservers (self); i++) {
tmp = nm_ip6_config_get_nameserver (self, i);
@@ -1512,51 +1529,6 @@ nm_ip6_config_dump (const NMIP6Config *self, const char *detail)
g_message (" dnsopt: %s", nm_ip6_config_get_dns_option (self, i));
g_message (" dnspri: %d", nm_ip6_config_get_dns_priority (self));
-
- g_message (" n-dflt: %d", nm_ip6_config_get_never_default (self));
-}
-
-/*****************************************************************************/
-
-void
-nm_ip6_config_set_never_default (NMIP6Config *self, gboolean never_default)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self);
-
- priv->never_default = never_default;
-}
-
-gboolean
-nm_ip6_config_get_never_default (const NMIP6Config *self)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self);
-
- return priv->never_default;
-}
-
-void
-nm_ip6_config_set_gateway (NMIP6Config *self, const struct in6_addr *gateway)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self);
-
- if (gateway) {
- if (IN6_ARE_ADDR_EQUAL (&priv->gateway, gateway))
- return;
- priv->gateway = *gateway;
- } else {
- if (IN6_IS_ADDR_UNSPECIFIED (&priv->gateway))
- return;
- memset (&priv->gateway, 0, sizeof (priv->gateway));
- }
- _notify (self, PROP_GATEWAY);
-}
-
-const struct in6_addr *
-nm_ip6_config_get_gateway (const NMIP6Config *self)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self);
-
- return IN6_IS_ADDR_UNSPECIFIED (&priv->gateway) ? NULL : &priv->gateway;
}
/*****************************************************************************/
@@ -1809,6 +1781,8 @@ _lookup_route (const NMIP6Config *self,
void
nm_ip6_config_reset_routes_ndisc (NMIP6Config *self,
+ const NMNDiscGateway *gateways,
+ guint gateways_n,
const NMNDiscRoute *routes,
guint routes_n,
guint32 route_table,
@@ -1857,12 +1831,38 @@ nm_ip6_config_reset_routes_ndisc (NMIP6Config *self,
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;
+ /* Use the first gateway as ordered in neighbor discovery cache. */
+ if (gateways_n) {
+ const NMPObject *obj_new;
+ const NMPlatformIP6Route r = {
+ .rt_source = NM_IP_CONFIG_SOURCE_NDISC,
+ .ifindex = priv->ifindex,
+ .gateway = gateways[0].address,
+ .table_coerced = nm_platform_route_table_coerce (route_table),
+ .metric = route_metric,
+ };
+
+ if (_nm_ip_config_add_obj (priv->multi_idx,
+ &priv->idx_ip6_routes_,
+ priv->ifindex,
+ NULL,
+ (const NMPlatformObject *) &r,
+ FALSE,
+ TRUE,
+ 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_dedup_multi_index_dirty_remove_idx (priv->multi_idx, &priv->idx_ip6_routes, FALSE) > 0)
changed = TRUE;
+ if (_nm_ip_config_best_default_route_set (&priv->best_default_route, new_best_default_route)) {
+ changed = TRUE;
+ _notify (self, PROP_GATEWAY);
+ }
+
if (changed)
_notify_routes (self);
}
@@ -1905,8 +1905,9 @@ _add_route (NMIP6Config *self,
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));
+ if (_nm_ip_config_best_default_route_merge (&priv->best_default_route, obj_new_2))
+ _notify (self, PROP_GATEWAY);
_notify_routes (self);
} else
NM_SET_OUT (out_obj_new, nmp_object_ref (obj_new_2));
@@ -1975,7 +1976,9 @@ _nmtst_ip6_config_get_route (const NMIP6Config *self, guint i)
}
const NMPlatformIP6Route *
-nm_ip6_config_get_direct_route_for_host (const NMIP6Config *self, const struct in6_addr *host)
+nm_ip6_config_get_direct_route_for_host (const NMIP6Config *self,
+ const struct in6_addr *host,
+ guint32 route_table)
{
const NMPlatformIP6Route *best_route = NULL;
const NMPlatformIP6Route *item;
@@ -1990,6 +1993,9 @@ nm_ip6_config_get_direct_route_for_host (const NMIP6Config *self, const struct i
if (best_route && best_route->plen > item->plen)
continue;
+ if (nm_platform_route_table_uncoerce (item->table_coerced, TRUE) != route_table)
+ continue;
+
if (!nm_utils_ip6_address_same_prefix (host, &item->network, item->plen))
continue;
@@ -2357,8 +2363,9 @@ nm_ip6_config_nmpobj_remove (NMIP6Config *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));
+ if (_nm_ip_config_best_default_route_set (&priv->best_default_route,
+ _nm_ip6_config_best_default_route_find (self)))
+ _notify (self, PROP_GATEWAY);
}
_notify_routes (self);
break;
@@ -2398,8 +2405,6 @@ nm_ip6_config_hash (const NMIP6Config *self, GChecksum *sum, gboolean dns_only)
g_return_if_fail (sum);
if (dns_only == FALSE) {
- hash_in6addr (sum, nm_ip6_config_get_gateway (self));
-
nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, self, &address) {
hash_in6addr (sum, &address->address);
hash_u32 (sum, address->plen);
@@ -2558,9 +2563,10 @@ get_property (GObject *object, guint prop_id,
&address->address, 16, 1),
address->plen,
g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
- i == 0
- ? (nm_ip6_config_get_gateway (self) ?: &in6addr_any)
- : &in6addr_any,
+ ( i == 0
+ && priv->best_default_route)
+ ? &NMP_OBJECT_CAST_IP6_ROUTE (priv->best_default_route)->gateway
+ : &in6addr_any,
16, 1));
}
}
@@ -2636,9 +2642,11 @@ out_routes_cached:
priv->routes_variant);
break;
case PROP_GATEWAY:
- if (!IN6_IS_ADDR_UNSPECIFIED (&priv->gateway))
- g_value_set_string (value, nm_utils_inet6_ntop (&priv->gateway, NULL));
- else
+ if (priv->best_default_route) {
+ g_value_set_string (value,
+ nm_utils_inet6_ntop (&NMP_OBJECT_CAST_IP6_ROUTE (priv->best_default_route)->gateway,
+ NULL));
+ } else
g_value_set_string (value, NULL);
break;
case PROP_NAMESERVERS:
diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h
index 0440bc52d3..e493f2f99d 100644
--- a/src/nm-ip6-config.h
+++ b/src/nm-ip6-config.h
@@ -108,9 +108,9 @@ struct _NMDedupMultiIndex *nm_ip6_config_get_multi_idx (const NMIP6Config *self)
NMIP6Config *nm_ip6_config_capture (struct _NMDedupMultiIndex *multi_idx, NMPlatform *platform, int ifindex,
gboolean capture_resolv_conf, NMSettingIP6ConfigPrivacy use_temporary);
-void nm_ip6_config_add_device_routes (NMIP6Config *self,
- guint32 route_table,
- guint32 route_metric);
+void nm_ip6_config_add_dependent_routes (NMIP6Config *self,
+ guint32 route_table,
+ guint32 route_metric);
gboolean nm_ip6_config_commit (const NMIP6Config *self,
NMPlatform *platform,
@@ -123,22 +123,24 @@ void nm_ip6_config_merge_setting (NMIP6Config *self,
NMSetting *nm_ip6_config_create_setting (const NMIP6Config *self);
-void nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src, NMIPConfigMergeFlags merge_flags);
-void nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src);
-void nm_ip6_config_intersect (NMIP6Config *dst, const NMIP6Config *src);
+void nm_ip6_config_merge (NMIP6Config *dst,
+ const NMIP6Config *src,
+ NMIPConfigMergeFlags merge_flags,
+ guint32 default_route_metric_penalty);
+void nm_ip6_config_subtract (NMIP6Config *dst,
+ const NMIP6Config *src,
+ guint32 default_route_metric_penalty);
+void nm_ip6_config_intersect (NMIP6Config *dst,
+ const NMIP6Config *src,
+ guint32 default_route_metric_penalty);
gboolean nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relevant_changes);
-int nm_ip6_config_destination_is_direct (const NMIP6Config *self, const struct in6_addr *dest, guint8 plen);
void nm_ip6_config_dump (const NMIP6Config *self, const char *detail);
-
-void nm_ip6_config_set_never_default (NMIP6Config *self, gboolean never_default);
-gboolean nm_ip6_config_get_never_default (const NMIP6Config *self);
-void nm_ip6_config_set_gateway (NMIP6Config *self, const struct in6_addr *);
-const struct in6_addr *nm_ip6_config_get_gateway (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 struct in6_addr *nmtst_ip6_config_get_gateway (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);
@@ -163,7 +165,9 @@ void _nmtst_ip6_config_del_route (NMIP6Config *self, guint i);
guint nm_ip6_config_get_num_routes (const NMIP6Config *self);
const NMPlatformIP6Route *_nmtst_ip6_config_get_route (const NMIP6Config *self, guint i);
-const NMPlatformIP6Route *nm_ip6_config_get_direct_route_for_host (const NMIP6Config *self, const struct in6_addr *host);
+const NMPlatformIP6Route *nm_ip6_config_get_direct_route_for_host (const NMIP6Config *self,
+ const struct in6_addr *host,
+ guint32 route_table);
const NMPlatformIP6Address *nm_ip6_config_get_subnet_for_host (const NMIP6Config *self, const struct in6_addr *host);
void nm_ip6_config_reset_nameservers (NMIP6Config *self);
@@ -210,7 +214,10 @@ void nm_ip6_config_reset_addresses_ndisc (NMIP6Config *self,
guint8 plen,
guint32 ifa_flags);
struct _NMNDiscRoute;
+struct _NMNDiscGateway;
void nm_ip6_config_reset_routes_ndisc (NMIP6Config *self,
+ const struct _NMNDiscGateway *gateways,
+ guint gateways_n,
const struct _NMNDiscRoute *routes,
guint routes_n,
guint32 route_table,
diff --git a/src/nm-types.h b/src/nm-types.h
index af99bdcfad..e01c48b0a5 100644
--- a/src/nm-types.h
+++ b/src/nm-types.h
@@ -194,7 +194,8 @@ typedef enum {
typedef enum {
NM_IP_CONFIG_MERGE_DEFAULT = 0,
NM_IP_CONFIG_MERGE_NO_ROUTES = (1LL << 0),
- NM_IP_CONFIG_MERGE_NO_DNS = (1LL << 1),
+ NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES = (1LL << 1),
+ NM_IP_CONFIG_MERGE_NO_DNS = (1LL << 2),
} NMIPConfigMergeFlags;
diff --git a/src/ppp/nm-ppp-manager-call.c b/src/ppp/nm-ppp-manager-call.c
index d67c0a99ce..ad3307a9d5 100644
--- a/src/ppp/nm-ppp-manager-call.c
+++ b/src/ppp/nm-ppp-manager-call.c
@@ -98,6 +98,22 @@ nm_ppp_manager_create (const char *iface, GError **error)
return ret;
}
+void
+nm_ppp_manager_set_route_parameters (NMPPPManager *self,
+ guint32 ip4_route_table,
+ guint32 ip4_route_metric,
+ guint32 ip6_route_table,
+ guint32 ip6_route_metric)
+{
+ g_return_if_fail (ppp_ops);
+
+ ppp_ops->set_route_parameters (self,
+ ip4_route_table,
+ ip4_route_metric,
+ ip6_route_table,
+ ip6_route_metric);
+}
+
gboolean
nm_ppp_manager_start (NMPPPManager *self,
NMActRequest *req,
diff --git a/src/ppp/nm-ppp-manager-call.h b/src/ppp/nm-ppp-manager-call.h
index f21005f0fd..2258ae08f7 100644
--- a/src/ppp/nm-ppp-manager-call.h
+++ b/src/ppp/nm-ppp-manager-call.h
@@ -25,6 +25,13 @@
NMPPPManager * nm_ppp_manager_create (const char *iface,
GError **error);
+
+void nm_ppp_manager_set_route_parameters (NMPPPManager *ppp_manager,
+ guint32 ip4_route_table,
+ guint32 ip4_route_metric,
+ guint32 ip6_route_table,
+ guint32 ip6_route_metric);
+
gboolean nm_ppp_manager_start (NMPPPManager *self,
NMActRequest *req,
const char *ppp_name,
diff --git a/src/ppp/nm-ppp-manager.c b/src/ppp/nm-ppp-manager.c
index 06703366f3..75299d1a66 100644
--- a/src/ppp/nm-ppp-manager.c
+++ b/src/ppp/nm-ppp-manager.c
@@ -42,6 +42,7 @@
#endif
#include <linux/if.h>
#include <linux/if_ppp.h>
+#include <linux/rtnetlink.h>
#include "NetworkManagerUtils.h"
#include "platform/nm-platform.h"
@@ -105,6 +106,11 @@ typedef struct {
char *ip_iface;
int monitor_fd;
guint monitor_id;
+
+ guint32 ip4_route_table;
+ guint32 ip4_route_metric;
+ guint32 ip6_route_table;
+ guint32 ip6_route_metric;
} NMPPPManagerPrivate;
struct _NMPPPManager {
@@ -132,6 +138,37 @@ static void _ppp_kill (NMPPPManager *manager);
/*****************************************************************************/
+static void
+_ppp_manager_set_route_paramters (NMPPPManager *self,
+ guint32 ip4_route_table,
+ guint32 ip4_route_metric,
+ guint32 ip6_route_table,
+ guint32 ip6_route_metric)
+{
+ NMPPPManagerPrivate *priv;
+
+ g_return_if_fail (NM_IS_PPP_MANAGER (self));
+
+ priv = NM_PPP_MANAGER_GET_PRIVATE (self);
+ if ( priv->ip4_route_table != ip4_route_table
+ || priv->ip4_route_metric != ip4_route_metric
+ || priv->ip6_route_table != ip6_route_table
+ || priv->ip6_route_metric != ip6_route_metric) {
+ priv->ip4_route_table = ip4_route_table;
+ priv->ip4_route_metric = ip4_route_metric;
+ priv->ip6_route_table = ip6_route_table;
+ priv->ip6_route_metric = ip6_route_metric;
+
+ _LOGT ("route-parameters: table-v4: %u, metric-v4: %u, table-v6: %u, metric-v6: %u",
+ priv->ip4_route_table,
+ priv->ip4_route_metric,
+ priv->ip6_route_table,
+ priv->ip6_route_metric);
+ }
+}
+
+/*****************************************************************************/
+
static gboolean
monitor_cb (gpointer user_data)
{
@@ -404,6 +441,7 @@ impl_ppp_manager_set_ip4_config (NMPPPManager *manager,
NMPlatformIP4Address address;
guint32 u32, mtu;
GVariantIter *iter;
+ int ifindex;
_LOGI ("(IPv4 Config Get) reply received.");
@@ -412,8 +450,11 @@ impl_ppp_manager_set_ip4_config (NMPPPManager *manager,
if (!set_ip_config_common (manager, config_dict, NM_PPP_IP4_CONFIG_INTERFACE, &mtu))
goto out;
- config = nm_ip4_config_new (nm_platform_get_multi_idx (NM_PLATFORM_GET),
- nm_platform_link_get_ifindex (NM_PLATFORM_GET, priv->ip_iface));
+ ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, priv->ip_iface);
+ if (ifindex <= 0)
+ goto out;
+
+ config = nm_ip4_config_new (nm_platform_get_multi_idx (NM_PLATFORM_GET), ifindex);
if (mtu)
nm_ip4_config_set_mtu (config, mtu, NM_IP_CONFIG_SOURCE_PPP);
@@ -425,7 +466,15 @@ impl_ppp_manager_set_ip4_config (NMPPPManager *manager,
address.address = u32;
if (g_variant_lookup (config_dict, NM_PPP_IP4_CONFIG_GATEWAY, "u", &u32)) {
- nm_ip4_config_set_gateway (config, u32);
+ const NMPlatformIP4Route r = {
+ .ifindex = ifindex,
+ .rt_source = NM_IP_CONFIG_SOURCE_PPP,
+ .gateway = u32,
+ .table_coerced = nm_platform_route_table_coerce (priv->ip4_route_table),
+ .metric = priv->ip4_route_metric,
+ };
+
+ nm_ip4_config_add_route (config, &r, NULL);
address.peer_address = u32;
} else
address.peer_address = address.address;
@@ -500,6 +549,7 @@ impl_ppp_manager_set_ip6_config (NMPPPManager *manager,
struct in6_addr a;
NMUtilsIPv6IfaceId iid = NM_UTILS_IPV6_IFACE_ID_INIT;
gboolean has_peer = FALSE;
+ int ifindex;
_LOGI ("(IPv6 Config Get) reply received.");
@@ -508,14 +558,25 @@ impl_ppp_manager_set_ip6_config (NMPPPManager *manager,
if (!set_ip_config_common (manager, config_dict, NM_PPP_IP6_CONFIG_INTERFACE, NULL))
goto out;
- config = nm_ip6_config_new (nm_platform_get_multi_idx (NM_PLATFORM_GET),
- nm_platform_link_get_ifindex (NM_PLATFORM_GET, priv->ip_iface));
+ ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, priv->ip_iface);
+ if (ifindex <= 0)
+ goto out;
+
+ config = nm_ip6_config_new (nm_platform_get_multi_idx (NM_PLATFORM_GET), ifindex);
memset (&addr, 0, sizeof (addr));
addr.plen = 64;
if (iid_value_to_ll6_addr (config_dict, NM_PPP_IP6_CONFIG_PEER_IID, &a, NULL)) {
- nm_ip6_config_set_gateway (config, &a);
+ const NMPlatformIP6Route r = {
+ .ifindex = ifindex,
+ .rt_source = NM_IP_CONFIG_SOURCE_PPP,
+ .gateway = a,
+ .table_coerced = nm_platform_route_table_coerce (priv->ip6_route_table),
+ .metric = priv->ip6_route_metric,
+ };
+
+ nm_ip6_config_add_route (config, &r, NULL);
addr.peer_address = a;
has_peer = TRUE;
}
@@ -1167,7 +1228,7 @@ set_property (GObject *object, guint prop_id,
switch (prop_id) {
case PROP_PARENT_IFACE:
- g_free (priv->parent_iface);
+ /* construct-only */
priv->parent_iface = g_value_dup_string (value);
break;
default:
@@ -1181,7 +1242,13 @@ set_property (GObject *object, guint prop_id,
static void
nm_ppp_manager_init (NMPPPManager *manager)
{
- NM_PPP_MANAGER_GET_PRIVATE (manager)->monitor_fd = -1;
+ NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager);
+
+ priv->monitor_fd = -1;
+ priv->ip4_route_table = RT_TABLE_MAIN;
+ priv->ip4_route_metric = 460;
+ priv->ip6_route_table = RT_TABLE_MAIN;
+ priv->ip6_route_metric = 460;
}
static NMPPPManager *
@@ -1291,9 +1358,10 @@ nm_ppp_manager_class_init (NMPPPManagerClass *manager_class)
}
NMPPPOps ppp_ops = {
- .create = _ppp_manager_new,
- .start = _ppp_manager_start,
- .stop_async = _ppp_manager_stop_async,
- .stop_finish = _ppp_manager_stop_finish,
- .stop_sync = _ppp_manager_stop_sync,
+ .create = _ppp_manager_new,
+ .set_route_parameters = _ppp_manager_set_route_paramters,
+ .start = _ppp_manager_start,
+ .stop_async = _ppp_manager_stop_async,
+ .stop_finish = _ppp_manager_stop_finish,
+ .stop_sync = _ppp_manager_stop_sync,
};
diff --git a/src/ppp/nm-ppp-manager.h b/src/ppp/nm-ppp-manager.h
index b1a7bb609a..35fb1b6091 100644
--- a/src/ppp/nm-ppp-manager.h
+++ b/src/ppp/nm-ppp-manager.h
@@ -22,7 +22,7 @@
#ifndef __NM_PPP_MANAGER_H__
#define __NM_PPP_MANAGER_H__
-#define NM_PPP_MANAGER_PARENT_IFACE "parent-iface"
+#define NM_PPP_MANAGER_PARENT_IFACE "parent-iface"
#define NM_PPP_MANAGER_SIGNAL_STATE_CHANGED "state-changed"
#define NM_PPP_MANAGER_SIGNAL_IP4_CONFIG "ip4-config"
diff --git a/src/ppp/nm-ppp-plugin-api.h b/src/ppp/nm-ppp-plugin-api.h
index 0a38fe0551..bb53690c63 100644
--- a/src/ppp/nm-ppp-plugin-api.h
+++ b/src/ppp/nm-ppp-plugin-api.h
@@ -24,6 +24,12 @@
typedef const struct {
NMPPPManager *(*create) (const char *iface);
+ void (*set_route_parameters) (NMPPPManager *manager,
+ guint32 route_table_v4,
+ guint32 route_metric_v4,
+ guint32 route_table_v6,
+ guint32 route_metric_v6);
+
gboolean (*start) (NMPPPManager *manager,
NMActRequest *req,
const char *ppp_name,
diff --git a/src/tests/test-ip4-config.c b/src/tests/test-ip4-config.c
index c2a1c006c5..649b443f2a 100644
--- a/src/tests/test-ip4-config.c
+++ b/src/tests/test-ip4-config.c
@@ -47,7 +47,16 @@ build_test_config (void)
route = *nmtst_platform_ip4_route ("172.16.0.0", 16, "192.168.1.1");
nm_ip4_config_add_route (config, &route, NULL);
- nm_ip4_config_set_gateway (config, nmtst_inet4_from_string ("192.168.1.1"));
+ {
+ const NMPlatformIP4Route r = {
+ .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
+ .gateway = nmtst_inet4_from_string ("192.168.1.1"),
+ .table_coerced = 0,
+ .metric = 100,
+ };
+
+ nm_ip4_config_add_route (config, &r, NULL);
+ }
nm_ip4_config_add_nameserver (config, nmtst_inet4_from_string ("4.2.2.1"));
nm_ip4_config_add_nameserver (config, nmtst_inet4_from_string ("4.2.2.2"));
@@ -106,7 +115,7 @@ test_subtract (void)
nm_ip4_config_set_mtu (dst, expected_mtu, NM_IP_CONFIG_SOURCE_UNKNOWN);
- nm_ip4_config_subtract (dst, src);
+ nm_ip4_config_subtract (dst, src, 0);
/* ensure what's left is what we expect */
g_assert_cmpuint (nm_ip4_config_get_num_addresses (dst), ==, 1);
@@ -116,7 +125,8 @@ test_subtract (void)
g_assert_cmpuint (test_addr->peer_address, ==, test_addr->address);
g_assert_cmpuint (test_addr->plen, ==, expected_addr_plen);
- g_assert_cmpuint (nm_ip4_config_get_gateway (dst), ==, 0);
+ g_assert (!nm_ip4_config_best_default_route_get (dst));
+ g_assert_cmpuint (nmtst_ip4_config_get_gateway (dst), ==, 0);
g_assert_cmpuint (nm_ip4_config_get_num_routes (dst), ==, 1);
test_route = _nmtst_ip4_config_get_route (dst, 0);
@@ -278,15 +288,15 @@ test_merge_subtract_mtu (void)
nm_ip4_config_set_mtu (cfg2, expected_mtu2, NM_IP_CONFIG_SOURCE_UNKNOWN);
nm_ip4_config_set_mtu (cfg3, expected_mtu3, NM_IP_CONFIG_SOURCE_UNKNOWN);
- nm_ip4_config_merge (cfg1, cfg2, NM_IP_CONFIG_MERGE_DEFAULT);
+ nm_ip4_config_merge (cfg1, cfg2, NM_IP_CONFIG_MERGE_DEFAULT, 0);
/* ensure MSS and MTU are in cfg1 */
g_assert_cmpuint (nm_ip4_config_get_mtu (cfg1), ==, expected_mtu2);
- nm_ip4_config_merge (cfg1, cfg3, NM_IP_CONFIG_MERGE_DEFAULT);
+ nm_ip4_config_merge (cfg1, cfg3, NM_IP_CONFIG_MERGE_DEFAULT, 0);
/* ensure again the MSS and MTU in cfg1 got overridden */
g_assert_cmpuint (nm_ip4_config_get_mtu (cfg1), ==, expected_mtu3);
- nm_ip4_config_subtract (cfg1, cfg3);
+ nm_ip4_config_subtract (cfg1, cfg3, 0);
/* ensure MSS and MTU are zero in cfg1 */
g_assert_cmpuint (nm_ip4_config_get_mtu (cfg1), ==, 0);
diff --git a/src/tests/test-ip6-config.c b/src/tests/test-ip6-config.c
index 05d2084ee5..bcbeee3e10 100644
--- a/src/tests/test-ip6-config.c
+++ b/src/tests/test-ip6-config.c
@@ -40,7 +40,7 @@ build_test_config (void)
nm_ip6_config_add_route (config, nmtst_platform_ip6_route ("abcd:1200::", 24, "abcd:1234:4321:cdde::2", NULL), NULL);
nm_ip6_config_add_route (config, nmtst_platform_ip6_route ("2001::", 16, "2001:abba::2234", NULL), NULL);
- nm_ip6_config_set_gateway (config, nmtst_inet6_from_string ("3001:abba::3234"));
+ nm_ip6_config_add_route (config, nmtst_platform_ip6_route ("::", 0, "3001:abba::3234", NULL), NULL);
nm_ip6_config_add_nameserver (config, nmtst_inet6_from_string ("1:2:3:4::1"));
nm_ip6_config_add_nameserver (config, nmtst_inet6_from_string ("1:2:3:4::2"));
@@ -84,7 +84,7 @@ test_subtract (void)
nm_ip6_config_add_domain (dst, expected_domain);
nm_ip6_config_add_search (dst, expected_search);
- nm_ip6_config_subtract (dst, src);
+ nm_ip6_config_subtract (dst, src, 0);
/* ensure what's left is what we expect */
g_assert_cmpuint (nm_ip6_config_get_num_addresses (dst), ==, 1);
@@ -95,7 +95,7 @@ test_subtract (void)
g_assert (memcmp (&test_addr->peer_address, &in6addr_any, sizeof (tmp)) == 0);
g_assert_cmpuint (test_addr->plen, ==, expected_addr_plen);
- g_assert (nm_ip6_config_get_gateway (dst) == NULL);
+ g_assert (nm_ip6_config_best_default_route_get (dst) == NULL);
g_assert_cmpuint (nm_ip6_config_get_num_routes (dst), ==, 1);
test_route = _nmtst_ip6_config_get_route (dst, 0);
diff --git a/src/vpn/nm-vpn-connection.c b/src/vpn/nm-vpn-connection.c
index e9a2bd919f..4b474c50d9 100644
--- a/src/vpn/nm-vpn-connection.c
+++ b/src/vpn/nm-vpn-connection.c
@@ -1018,9 +1018,6 @@ print_vpn_config (NMVpnConnection *self)
nm_utils_inet4_ntop (route->gateway, buf));
}
- _LOGI ("Data: Forbid Default Route: %s",
- nm_ip4_config_get_never_default (priv->ip4_config) ? "yes" : "no");
-
num = nm_ip4_config_get_num_nameservers (priv->ip4_config);
for (i = 0; i < num; i++) {
_LOGI ("Data: Internal DNS: %s",
@@ -1055,9 +1052,6 @@ print_vpn_config (NMVpnConnection *self)
nm_utils_inet6_ntop (&route->gateway, buf));
}
- _LOGI ("Data: Forbid Default Route: %s",
- nm_ip6_config_get_never_default (priv->ip6_config) ? "yes" : "no");
-
num = nm_ip6_config_get_num_nameservers (priv->ip6_config);
for (i = 0; i < num; i++) {
_LOGI ("Data: Internal DNS: %s",
@@ -1098,19 +1092,13 @@ apply_parent_device_config (NMVpnConnection *self)
vpn4_parent_config = nm_ip4_config_new (nm_netns_get_multi_idx (priv->netns),
ifindex);
if (priv->ip_ifindex <= 0)
- nm_ip4_config_merge (vpn4_parent_config, priv->ip4_config, NM_IP_CONFIG_MERGE_NO_DNS);
+ nm_ip4_config_merge (vpn4_parent_config, priv->ip4_config, NM_IP_CONFIG_MERGE_NO_DNS, 0);
}
if (priv->ip6_config) {
vpn6_parent_config = nm_ip6_config_new (nm_netns_get_multi_idx (priv->netns),
ifindex);
- if (priv->ip_ifindex <= 0) {
- nm_ip6_config_merge (vpn6_parent_config, priv->ip6_config, NM_IP_CONFIG_MERGE_NO_DNS);
-
- /* Also clear the gateway. We don't configure the gateway as part of the
- * vpn-config. Instead we tell NMDefaultRouteManager directly about the
- * default route. */
- nm_ip6_config_set_gateway (vpn6_parent_config, NULL);
- }
+ if (priv->ip_ifindex <= 0)
+ nm_ip6_config_merge (vpn6_parent_config, priv->ip6_config, NM_IP_CONFIG_MERGE_NO_DNS, 0);
}
}
@@ -1479,6 +1467,7 @@ nm_vpn_connection_ip4_config_get (NMVpnConnection *self, GVariant *dict)
gboolean b;
int ip_ifindex;
guint32 mss = 0;
+ gboolean never_default = FALSE;
g_return_if_fail (dict && g_variant_is_of_type (dict, G_VARIANT_TYPE_VARDICT));
@@ -1523,10 +1512,8 @@ nm_vpn_connection_ip4_config_get (NMVpnConnection *self, GVariant *dict)
address.plen = 24;
/* Internal address of the VPN subnet's gateway */
- if (g_variant_lookup (dict, NM_VPN_PLUGIN_IP4_CONFIG_INT_GATEWAY, "u", &u32)) {
+ if (g_variant_lookup (dict, NM_VPN_PLUGIN_IP4_CONFIG_INT_GATEWAY, "u", &u32))
priv->ip4_internal_gw = u32;
- nm_ip4_config_set_gateway (config, priv->ip4_internal_gw);
- }
if (g_variant_lookup (dict, NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS, "u", &u32))
address.address = u32;
@@ -1625,7 +1612,7 @@ nm_vpn_connection_ip4_config_get (NMVpnConnection *self, GVariant *dict)
}
if (g_variant_lookup (dict, NM_VPN_PLUGIN_IP4_CONFIG_NEVER_DEFAULT, "b", &b))
- nm_ip4_config_set_never_default (config, b);
+ never_default = b;
/* Merge in user overrides from the NMConnection's IPv4 setting */
nm_ip4_config_merge_setting (config,
@@ -1633,11 +1620,11 @@ nm_vpn_connection_ip4_config_get (NMVpnConnection *self, GVariant *dict)
route_table,
route_metric);
- if (!nm_ip4_config_get_never_default (config)) {
+ if (!never_default) {
const NMPlatformIP4Route r = {
.ifindex = ip_ifindex,
.rt_source = NM_IP_CONFIG_SOURCE_VPN,
- .gateway = nm_ip4_config_get_gateway (config),
+ .gateway = priv->ip4_internal_gw,
.table_coerced = nm_platform_route_table_coerce (route_table),
.metric = route_metric,
.mss = mss,
@@ -1648,10 +1635,10 @@ nm_vpn_connection_ip4_config_get (NMVpnConnection *self, GVariant *dict)
g_clear_pointer (&priv->ip4_dev_route_blacklist, g_ptr_array_unref);
- nm_ip4_config_add_device_routes (config,
- route_table,
- nm_vpn_connection_get_ip4_route_metric (self),
- &priv->ip4_dev_route_blacklist);
+ nm_ip4_config_add_dependent_routes (config,
+ route_table,
+ nm_vpn_connection_get_ip4_route_metric (self),
+ &priv->ip4_dev_route_blacklist);
if (priv->ip4_config) {
nm_ip4_config_replace (priv->ip4_config, config, NULL);
@@ -1679,6 +1666,7 @@ nm_vpn_connection_ip6_config_get (NMVpnConnection *self, GVariant *dict)
gboolean b;
int ip_ifindex;
guint32 mss = 0;
+ gboolean never_default = FALSE;
g_return_if_fail (dict && g_variant_is_of_type (dict, G_VARIANT_TYPE_VARDICT));
@@ -1713,7 +1701,6 @@ nm_vpn_connection_ip6_config_get (NMVpnConnection *self, GVariant *dict)
g_clear_pointer (&priv->ip6_internal_gw, g_free);
if (g_variant_lookup (dict, NM_VPN_PLUGIN_IP6_CONFIG_INT_GATEWAY, "@ay", &v)) {
priv->ip6_internal_gw = ip6_addr_dup_from_variant (v);
- nm_ip6_config_set_gateway (config, priv->ip6_internal_gw);
g_variant_unref (v);
}
@@ -1812,7 +1799,7 @@ next:
}
if (g_variant_lookup (dict, NM_VPN_PLUGIN_IP6_CONFIG_NEVER_DEFAULT, "b", &b))
- nm_ip6_config_set_never_default (config, b);
+ never_default = b;
/* Merge in user overrides from the NMConnection's IPv6 setting */
nm_ip6_config_merge_setting (config,
@@ -1820,11 +1807,11 @@ next:
route_table,
route_metric);
- if (!nm_ip6_config_get_never_default (config)) {
+ if (!never_default) {
const NMPlatformIP6Route r = {
.ifindex = ip_ifindex,
.rt_source = NM_IP_CONFIG_SOURCE_VPN,
- .gateway = *(nm_ip6_config_get_gateway (config) ?: &in6addr_any),
+ .gateway = *(priv->ip6_internal_gw ?: &in6addr_any),
.table_coerced = nm_platform_route_table_coerce (route_table),
.metric = route_metric,
.mss = mss,
@@ -1833,9 +1820,9 @@ next:
nm_ip6_config_add_route (config, &r, NULL);
}
- nm_ip6_config_add_device_routes (config,
- route_table,
- route_metric);
+ nm_ip6_config_add_dependent_routes (config,
+ route_table,
+ route_metric);
if (priv->ip6_config) {
nm_ip6_config_replace (priv->ip6_config, config, NULL);