mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-08 10:20:30 +01:00
core: track IPv4 device routes in NMIP4Config
For IPv6, we create device routes when processing the RA and add it to NMIP6Config like any other route. For IPv4 we didn't do that. Instead we created the list of device routes during nm_ip4_config_commit() and passed it to nm_platform_ip_route_sync().
This commit is contained in:
parent
4b4efac3ab
commit
9a3117f1d3
5 changed files with 139 additions and 103 deletions
|
|
@ -496,8 +496,8 @@ static void nm_device_set_proxy_config (NMDevice *self, const char *pac_url);
|
|||
|
||||
static gboolean nm_device_set_ip4_config (NMDevice *self,
|
||||
NMIP4Config *config,
|
||||
guint32 default_route_metric,
|
||||
gboolean commit);
|
||||
gboolean commit,
|
||||
GPtrArray *ip4_dev_route_blacklist);
|
||||
static gboolean ip4_config_merge_and_apply (NMDevice *self,
|
||||
NMIP4Config *config,
|
||||
gboolean commit);
|
||||
|
|
@ -3885,7 +3885,7 @@ nm_device_removed (NMDevice *self, gboolean unconfigure_ip_config)
|
|||
if (!unconfigure_ip_config)
|
||||
return;
|
||||
|
||||
nm_device_set_ip4_config (self, NULL, 0, FALSE);
|
||||
nm_device_set_ip4_config (self, NULL, FALSE, NULL);
|
||||
nm_device_set_ip6_config (self, NULL, FALSE);
|
||||
}
|
||||
|
||||
|
|
@ -5578,6 +5578,7 @@ ip4_config_merge_and_apply (NMDevice *self,
|
|||
gboolean ignore_auto_dns = FALSE;
|
||||
GSList *iter;
|
||||
NMPlatformIP4Route default_route;
|
||||
gs_unref_ptrarray GPtrArray *ip4_dev_route_blacklist = NULL;
|
||||
|
||||
/* Merge all the configs into the composite config */
|
||||
if (config) {
|
||||
|
|
@ -5694,12 +5695,19 @@ ip4_config_merge_and_apply (NMDevice *self,
|
|||
}
|
||||
|
||||
END_ADD_DEFAULT_ROUTE:
|
||||
|
||||
if (commit) {
|
||||
nm_ip4_config_add_device_routes (composite,
|
||||
default_route_metric,
|
||||
&ip4_dev_route_blacklist);
|
||||
}
|
||||
|
||||
if (commit) {
|
||||
if (NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit)
|
||||
NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit (self, composite);
|
||||
}
|
||||
|
||||
success = nm_device_set_ip4_config (self, composite, default_route_metric, commit);
|
||||
success = nm_device_set_ip4_config (self, composite, commit, ip4_dev_route_blacklist);
|
||||
g_object_unref (composite);
|
||||
|
||||
if (commit)
|
||||
|
|
@ -9739,8 +9747,8 @@ nm_device_get_ip4_config (NMDevice *self)
|
|||
static gboolean
|
||||
nm_device_set_ip4_config (NMDevice *self,
|
||||
NMIP4Config *new_config,
|
||||
guint32 default_route_metric,
|
||||
gboolean commit)
|
||||
gboolean commit,
|
||||
GPtrArray *ip4_dev_route_blacklist)
|
||||
{
|
||||
NMDevicePrivate *priv;
|
||||
NMIP4Config *old_config = NULL;
|
||||
|
|
@ -9766,8 +9774,10 @@ nm_device_set_ip4_config (NMDevice *self,
|
|||
if (commit && new_config) {
|
||||
_commit_mtu (self, new_config);
|
||||
success = nm_ip4_config_commit (new_config,
|
||||
nm_device_get_platform (self),
|
||||
default_route_metric);
|
||||
nm_device_get_platform (self));
|
||||
nm_platform_ip4_dev_route_blacklist_set (nm_device_get_platform (self),
|
||||
nm_ip4_config_get_ifindex (new_config),
|
||||
ip4_dev_route_blacklist);
|
||||
}
|
||||
|
||||
if (new_config) {
|
||||
|
|
@ -11986,7 +11996,7 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type)
|
|||
/* Clean up IP configs; this does not actually deconfigure the
|
||||
* interface; the caller must flush routes and addresses explicitly.
|
||||
*/
|
||||
nm_device_set_ip4_config (self, NULL, 0, TRUE);
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ dhcp4_state_changed (NMDhcpClient *client,
|
|||
{
|
||||
static NMIP4Config *last_config = NULL;
|
||||
NMIP4Config *existing;
|
||||
gs_unref_ptrarray GPtrArray *ip4_dev_route_blacklist = NULL;
|
||||
|
||||
g_return_if_fail (!ip4_config || NM_IS_IP4_CONFIG (ip4_config));
|
||||
|
||||
|
|
@ -123,11 +124,17 @@ dhcp4_state_changed (NMDhcpClient *client,
|
|||
nm_ip4_config_subtract (existing, last_config);
|
||||
|
||||
nm_ip4_config_merge (existing, ip4_config, NM_IP_CONFIG_MERGE_DEFAULT);
|
||||
nm_ip4_config_add_device_routes (existing,
|
||||
global_opt.priority_v4,
|
||||
&ip4_dev_route_blacklist);
|
||||
if (!nm_ip4_config_commit (existing,
|
||||
NM_PLATFORM_GET,
|
||||
global_opt.priority_v4))
|
||||
NM_PLATFORM_GET))
|
||||
_LOGW (LOGD_DHCP4, "failed to apply DHCPv4 config");
|
||||
|
||||
nm_platform_ip4_dev_route_blacklist_set (NM_PLATFORM_GET,
|
||||
gl.ifindex,
|
||||
ip4_dev_route_blacklist);
|
||||
|
||||
if (last_config)
|
||||
g_object_unref (last_config);
|
||||
last_config = nm_ip4_config_new (nm_platform_get_multi_idx (NM_PLATFORM_GET),
|
||||
|
|
|
|||
|
|
@ -724,23 +724,105 @@ nm_ip4_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i
|
|||
return self;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_ip4_config_commit (const NMIP4Config *self,
|
||||
NMPlatform *platform,
|
||||
guint32 default_route_metric)
|
||||
void
|
||||
nm_ip4_config_add_device_routes (NMIP4Config *self,
|
||||
guint32 default_route_metric,
|
||||
GPtrArray **out_ip4_dev_route_blacklist)
|
||||
{
|
||||
const NMIP4ConfigPrivate *priv;
|
||||
GPtrArray *ip4_dev_route_blacklist = NULL;
|
||||
const NMPlatformIP4Address *addr;
|
||||
int ifindex;
|
||||
NMDedupMultiIter iter;
|
||||
|
||||
g_return_if_fail (NM_IS_IP4_CONFIG (self));
|
||||
|
||||
priv = NM_IP4_CONFIG_GET_PRIVATE (self);
|
||||
|
||||
ifindex = nm_ip4_config_get_ifindex (self);
|
||||
g_return_if_fail (ifindex > 0);
|
||||
|
||||
/* For IPv6, we explicitly add the device-routes (onlink) to NMIP6Config.
|
||||
* As we don't do that for IPv4, add it here shortly before syncing
|
||||
* the routes. */
|
||||
|
||||
nm_ip_config_iter_ip4_address_for_each (&iter, self, &addr) {
|
||||
nm_auto_nmpobj NMPObject *r = NULL;
|
||||
NMPlatformIP4Route *route;
|
||||
in_addr_t network;
|
||||
|
||||
if (addr->plen == 0)
|
||||
continue;
|
||||
|
||||
nm_assert (addr->plen <= 32);
|
||||
|
||||
/* The destination network depends on the peer-address. */
|
||||
network = nm_utils_ip4_address_clear_host_address (addr->peer_address, addr->plen);
|
||||
|
||||
if (_ipv4_is_zeronet (network)) {
|
||||
/* Kernel doesn't add device-routes for destinations that
|
||||
* start with 0.x.y.z. Skip them. */
|
||||
continue;
|
||||
}
|
||||
|
||||
r = nmp_object_new (NMP_OBJECT_TYPE_IP4_ROUTE, NULL);
|
||||
route = NMP_OBJECT_CAST_IP4_ROUTE (r);
|
||||
|
||||
route->ifindex = ifindex;
|
||||
route->rt_source = NM_IP_CONFIG_SOURCE_KERNEL;
|
||||
route->network = network;
|
||||
route->plen = addr->plen;
|
||||
route->pref_src = addr->address;
|
||||
route->metric = default_route_metric;
|
||||
route->scope_inv = nm_platform_route_scope_inv (NM_RT_SCOPE_LINK);
|
||||
|
||||
nm_platform_ip_route_normalize (AF_INET, (NMPlatformIPRoute *) route);
|
||||
|
||||
if (_lookup_route (self,
|
||||
r,
|
||||
NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID)) {
|
||||
/* we already track this route. Don't add it again. */
|
||||
} else
|
||||
_add_route (self, nmp_object_ref (r), NULL, NULL);
|
||||
|
||||
if ( out_ip4_dev_route_blacklist
|
||||
&& default_route_metric != NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE) {
|
||||
nm_auto_nmpobj NMPObject *r_dev = NULL;
|
||||
|
||||
r_dev = nmp_object_clone (r, FALSE);
|
||||
route = NMP_OBJECT_CAST_IP4_ROUTE (r_dev);
|
||||
route->metric = NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE;
|
||||
|
||||
nm_platform_ip_route_normalize (AF_INET, (NMPlatformIPRoute *) route);
|
||||
|
||||
if (_lookup_route (self,
|
||||
r_dev,
|
||||
NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID)) {
|
||||
/* we track such a route explicitly. Don't blacklist it. */
|
||||
} else {
|
||||
if (!ip4_dev_route_blacklist)
|
||||
ip4_dev_route_blacklist = g_ptr_array_new_with_free_func ((GDestroyNotify) nmp_object_unref);
|
||||
|
||||
g_ptr_array_add (ip4_dev_route_blacklist,
|
||||
g_steal_pointer (&r_dev));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NM_SET_OUT (out_ip4_dev_route_blacklist, ip4_dev_route_blacklist);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_ip4_config_commit (const NMIP4Config *self,
|
||||
NMPlatform *platform)
|
||||
{
|
||||
gs_unref_ptrarray GPtrArray *addresses = NULL;
|
||||
gs_unref_ptrarray GPtrArray *routes = NULL;
|
||||
gs_unref_ptrarray GPtrArray *ip4_dev_route_blacklist = NULL;
|
||||
int ifindex;
|
||||
guint i;
|
||||
gboolean success = TRUE;
|
||||
|
||||
g_return_val_if_fail (NM_IS_IP4_CONFIG (self), FALSE);
|
||||
|
||||
priv = NM_IP4_CONFIG_GET_PRIVATE (self);
|
||||
|
||||
ifindex = nm_ip4_config_get_ifindex (self);
|
||||
g_return_val_if_fail (ifindex > 0, FALSE);
|
||||
|
||||
|
|
@ -750,82 +832,6 @@ nm_ip4_config_commit (const NMIP4Config *self,
|
|||
routes = nm_dedup_multi_objs_to_ptr_array_head (nm_ip4_config_lookup_routes (self),
|
||||
NULL, NULL);
|
||||
|
||||
if (addresses) {
|
||||
/* For IPv6, we explicitly add the device-routes (onlink) to NMIP6Config.
|
||||
* As we don't do that for IPv4, add it here shortly before syncing
|
||||
* the routes. */
|
||||
for (i = 0; i < addresses->len; i++) {
|
||||
const NMPObject *o = addresses->pdata[i];
|
||||
const NMPlatformIP4Address *addr;
|
||||
nm_auto_nmpobj NMPObject *r = NULL;
|
||||
NMPlatformIP4Route *route;
|
||||
in_addr_t network;
|
||||
|
||||
if (!o)
|
||||
continue;
|
||||
|
||||
addr = NMP_OBJECT_CAST_IP4_ADDRESS (o);
|
||||
if (addr->plen == 0)
|
||||
continue;
|
||||
|
||||
nm_assert (addr->plen <= 32);
|
||||
|
||||
/* The destination network depends on the peer-address. */
|
||||
network = nm_utils_ip4_address_clear_host_address (addr->peer_address, addr->plen);
|
||||
|
||||
if (_ipv4_is_zeronet (network)) {
|
||||
/* Kernel doesn't add device-routes for destinations that
|
||||
* start with 0.x.y.z. Skip them. */
|
||||
continue;
|
||||
}
|
||||
|
||||
r = nmp_object_new (NMP_OBJECT_TYPE_IP4_ROUTE, NULL);
|
||||
route = NMP_OBJECT_CAST_IP4_ROUTE (r);
|
||||
|
||||
route->ifindex = ifindex;
|
||||
route->rt_source = NM_IP_CONFIG_SOURCE_KERNEL;
|
||||
route->network = network;
|
||||
route->plen = addr->plen;
|
||||
route->pref_src = addr->address;
|
||||
route->metric = default_route_metric;
|
||||
route->scope_inv = nm_platform_route_scope_inv (NM_RT_SCOPE_LINK);
|
||||
|
||||
nm_platform_ip_route_normalize (AF_INET, (NMPlatformIPRoute *) route);
|
||||
|
||||
if (_lookup_route (self,
|
||||
r,
|
||||
NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID)) {
|
||||
/* we already track this route. Don't add it again. */
|
||||
} else {
|
||||
if (!routes)
|
||||
routes = g_ptr_array_new_with_free_func ((GDestroyNotify) nmp_object_unref);
|
||||
g_ptr_array_add (routes, (gpointer) nmp_object_ref (r));
|
||||
}
|
||||
|
||||
if (default_route_metric != NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE) {
|
||||
nm_auto_nmpobj NMPObject *r_dev = NULL;
|
||||
|
||||
r_dev = nmp_object_clone (r, FALSE);
|
||||
route = NMP_OBJECT_CAST_IP4_ROUTE (r_dev);
|
||||
route->metric = NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE;
|
||||
|
||||
nm_platform_ip_route_normalize (AF_INET, (NMPlatformIPRoute *) route);
|
||||
|
||||
if (_lookup_route (self,
|
||||
r_dev,
|
||||
NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID)) {
|
||||
/* we track such a route explicitly. Don't blacklist it. */
|
||||
} else {
|
||||
if (!ip4_dev_route_blacklist)
|
||||
ip4_dev_route_blacklist = g_ptr_array_new_with_free_func ((GDestroyNotify) nmp_object_unref);
|
||||
|
||||
g_ptr_array_add (ip4_dev_route_blacklist,
|
||||
g_steal_pointer (&r_dev));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nm_platform_ip4_address_sync (platform, ifindex, addresses);
|
||||
|
||||
if (!nm_platform_ip_route_sync (platform,
|
||||
|
|
@ -836,10 +842,6 @@ nm_ip4_config_commit (const NMIP4Config *self,
|
|||
NULL))
|
||||
success = FALSE;
|
||||
|
||||
nm_platform_ip4_dev_route_blacklist_set (platform,
|
||||
ifindex,
|
||||
ip4_dev_route_blacklist);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -150,9 +150,14 @@ int nm_ip4_config_get_ifindex (const NMIP4Config *self);
|
|||
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 default_route_metric,
|
||||
GPtrArray **out_ip4_dev_route_blacklist);
|
||||
|
||||
gboolean nm_ip4_config_commit (const NMIP4Config *self,
|
||||
NMPlatform *platform,
|
||||
guint32 default_route_metric);
|
||||
NMPlatform *platform);
|
||||
|
||||
void nm_ip4_config_merge_setting (NMIP4Config *self, NMSettingIPConfig *setting, guint32 default_route_metric);
|
||||
NMSetting *nm_ip4_config_create_setting (const NMIP4Config *self);
|
||||
|
||||
|
|
|
|||
|
|
@ -121,6 +121,8 @@ typedef struct {
|
|||
|
||||
NMNetns *netns;
|
||||
|
||||
GPtrArray *ip4_dev_route_blacklist;
|
||||
|
||||
GDBusProxy *proxy;
|
||||
GCancellable *cancellable;
|
||||
GVariant *connect_hash;
|
||||
|
|
@ -1147,9 +1149,11 @@ nm_vpn_connection_apply_config (NMVpnConnection *self)
|
|||
if (priv->ip4_config) {
|
||||
nm_assert (priv->ip_ifindex == nm_ip4_config_get_ifindex (priv->ip4_config));
|
||||
if (!nm_ip4_config_commit (priv->ip4_config,
|
||||
nm_netns_get_platform (priv->netns),
|
||||
nm_vpn_connection_get_ip4_route_metric (self)))
|
||||
nm_netns_get_platform (priv->netns)))
|
||||
return FALSE;
|
||||
nm_platform_ip4_dev_route_blacklist_set (nm_netns_get_platform (priv->netns),
|
||||
priv->ip_ifindex,
|
||||
priv->ip4_dev_route_blacklist);
|
||||
}
|
||||
|
||||
if (priv->ip6_config) {
|
||||
|
|
@ -1601,6 +1605,12 @@ nm_vpn_connection_ip4_config_get (NMVpnConnection *self, GVariant *dict)
|
|||
nm_ip4_config_add_route (config, &r, NULL);
|
||||
}
|
||||
|
||||
g_clear_pointer (&priv->ip4_dev_route_blacklist, g_ptr_array_unref);
|
||||
|
||||
nm_ip4_config_add_device_routes (config,
|
||||
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);
|
||||
g_object_unref (config);
|
||||
|
|
@ -2704,6 +2714,8 @@ dispose (GObject *object)
|
|||
|
||||
g_clear_pointer (&priv->connect_hash, g_variant_unref);
|
||||
|
||||
g_clear_pointer (&priv->ip4_dev_route_blacklist, g_ptr_array_unref);
|
||||
|
||||
nm_clear_g_source (&priv->connect_timeout);
|
||||
|
||||
dispatcher_cleanup (self);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue