core: merge branch 'th/ip-config-route-id'

https://github.com/NetworkManager/NetworkManager/pull/27
This commit is contained in:
Thomas Haller 2017-09-13 14:49:36 +02:00
commit b4c249959d
12 changed files with 222 additions and 279 deletions

View file

@ -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);

View file

@ -116,27 +116,35 @@ gboolean nm_ethernet_address_is_valid (gconstpointer addr, gssize len);
gconstpointer nm_utils_ipx_address_clear_host_address (int family, gpointer dst, gconstpointer src, guint8 plen);
in_addr_t nm_utils_ip4_address_clear_host_address (in_addr_t addr, guint8 plen);
const struct in6_addr *nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_addr *src, guint8 plen);
static inline int
nm_utils_ip4_address_same_prefix_cmp (in_addr_t addr_a, in_addr_t addr_b, guint8 plen)
{
NM_CMP_DIRECT (htonl (nm_utils_ip4_address_clear_host_address (addr_a, plen)),
htonl (nm_utils_ip4_address_clear_host_address (addr_b, plen)));
return 0;
}
int nm_utils_ip6_address_same_prefix_cmp (const struct in6_addr *addr_a, const struct in6_addr *addr_b, guint8 plen);
static inline gboolean
nm_utils_ip4_address_same_prefix (in_addr_t addr_a, in_addr_t addr_b, guint8 plen)
{
return nm_utils_ip4_address_same_prefix_cmp (addr_a, addr_b, plen) == 0;
}
static inline gboolean
nm_utils_ip6_address_same_prefix (const struct in6_addr *addr_a, const struct in6_addr *addr_b, guint8 plen)
{
return nm_utils_ip6_address_same_prefix_cmp (addr_a, addr_b, plen) == 0;
}
#define NM_CMP_DIRECT_IN4ADDR_SAME_PREFIX(a, b, plen) \
NM_CMP_RETURN (nm_utils_ip4_address_same_prefix_cmp ((a), (b), (plen)))
#define NM_CMP_DIRECT_IN6ADDR_SAME_PREFIX(a, b, plen) \
NM_CMP_RETURN (nm_utils_ip6_address_same_prefix_cmp ((a), (b), (plen)))
#define NM_CMP_DIRECT_IN4ADDR_SAME_PREFIX(a, b, plen) \
G_STMT_START { \
const guint8 _plen = (plen); \
const in_addr_t _aa = (a); \
const in_addr_t _ab = (b); \
\
NM_CMP_DIRECT (htonl (nm_utils_ip4_address_clear_host_address (_aa, _plen)), \
htonl (nm_utils_ip4_address_clear_host_address (_ab, _plen))); \
} G_STMT_END
static inline guint
NM_HASH_COMBINE_IN6ADDR (guint h, const struct in6_addr *addr)
{

View file

@ -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),

View file

@ -55,67 +55,11 @@ _route_valid (const NMPlatformIP4Route *r)
/*****************************************************************************/
gboolean
nm_ip_config_obj_id_equal_ip4_address (const NMPlatformIP4Address *a,
const NMPlatformIP4Address *b)
{
return a->address == b->address
&& a->plen == b->plen
&& ((a->peer_address ^ b->peer_address) & _nm_utils_ip4_prefix_to_netmask (a->plen)) == 0;
}
gboolean
nm_ip_config_obj_id_equal_ip6_address (const NMPlatformIP6Address *a,
const NMPlatformIP6Address *b)
{
return IN6_ARE_ADDR_EQUAL (&a->address, &b->address);
}
gboolean
nm_ip_config_obj_id_equal_ip4_route (const NMPlatformIP4Route *r_a,
const NMPlatformIP4Route *r_b)
{
return nm_platform_ip4_route_cmp (r_a, r_b, NM_PLATFORM_IP_ROUTE_CMP_TYPE_DST) == 0;
}
gboolean
nm_ip_config_obj_id_equal_ip6_route (const NMPlatformIP6Route *r_a,
const NMPlatformIP6Route *r_b)
{
return nm_platform_ip6_route_cmp (r_a, r_b, NM_PLATFORM_IP_ROUTE_CMP_TYPE_DST) == 0;
}
static guint
_idx_obj_id_hash (const NMDedupMultiIdxType *idx_type,
const NMDedupMultiObj *obj)
{
const NMPObject *o = (NMPObject *) obj;
guint h;
switch (NMP_OBJECT_GET_TYPE (o)) {
case NMP_OBJECT_TYPE_IP4_ADDRESS:
h = 1550630563;
h = NM_HASH_COMBINE (h, o->ip4_address.address);
h = NM_HASH_COMBINE (h, o->ip_address.plen);
h = NM_HASH_COMBINE (h, nm_utils_ip4_address_clear_host_address (o->ip4_address.peer_address, o->ip_address.plen));
break;
case NMP_OBJECT_TYPE_IP6_ADDRESS:
h = 851146661;
h = NM_HASH_COMBINE_IN6ADDR (h, &o->ip6_address.address);
break;
case NMP_OBJECT_TYPE_IP4_ROUTE:
h = 40303327;
h = NM_HASH_COMBINE (h, nm_platform_ip4_route_hash (NMP_OBJECT_CAST_IP4_ROUTE (o), NM_PLATFORM_IP_ROUTE_CMP_TYPE_DST));
break;
case NMP_OBJECT_TYPE_IP6_ROUTE:
h = 577629323;
h = NM_HASH_COMBINE (h, nm_platform_ip6_route_hash (NMP_OBJECT_CAST_IP6_ROUTE (o), NM_PLATFORM_IP_ROUTE_CMP_TYPE_DST));
break;
default:
g_return_val_if_reached (0);
};
return h;
return nmp_object_id_hash ((NMPObject *) obj);
}
static gboolean
@ -123,36 +67,20 @@ _idx_obj_id_equal (const NMDedupMultiIdxType *idx_type,
const NMDedupMultiObj *obj_a,
const NMDedupMultiObj *obj_b)
{
const NMPObject *o_a = (NMPObject *) obj_a;
const NMPObject *o_b = (NMPObject *) obj_b;
nm_assert (NMP_OBJECT_GET_TYPE (o_a) == NMP_OBJECT_GET_TYPE (o_b));
switch (NMP_OBJECT_GET_TYPE (o_a)) {
case NMP_OBJECT_TYPE_IP4_ADDRESS:
return nm_ip_config_obj_id_equal_ip4_address (NMP_OBJECT_CAST_IP4_ADDRESS (o_a), NMP_OBJECT_CAST_IP4_ADDRESS (o_b));
case NMP_OBJECT_TYPE_IP6_ADDRESS:
return nm_ip_config_obj_id_equal_ip6_address (NMP_OBJECT_CAST_IP6_ADDRESS (o_a), NMP_OBJECT_CAST_IP6_ADDRESS (o_b));
case NMP_OBJECT_TYPE_IP4_ROUTE:
return nm_ip_config_obj_id_equal_ip4_route (&o_a->ip4_route, &o_b->ip4_route);
case NMP_OBJECT_TYPE_IP6_ROUTE:
return nm_ip_config_obj_id_equal_ip6_route (&o_a->ip6_route, &o_b->ip6_route);
default:
g_return_val_if_reached (FALSE);
};
return nmp_object_id_equal ((NMPObject *) obj_a, (NMPObject *) obj_b);
}
static const NMDedupMultiIdxTypeClass _dedup_multi_idx_type_class = {
.idx_obj_id_hash = _idx_obj_id_hash,
.idx_obj_id_equal = _idx_obj_id_equal,
};
void
nm_ip_config_dedup_multi_idx_type_init (NMIPConfigDedupMultiIdxType *idx_type,
NMPObjectType obj_type)
{
static const NMDedupMultiIdxTypeClass idx_type_class = {
.idx_obj_id_hash = _idx_obj_id_hash,
.idx_obj_id_equal = _idx_obj_id_equal,
};
nm_dedup_multi_idx_type_init ((NMDedupMultiIdxType *) idx_type,
&_dedup_multi_idx_type_class);
&idx_type_class);
idx_type->obj_type = obj_type;
}
@ -215,17 +143,6 @@ _nm_ip_config_add_obj (NMDedupMultiIndex *multi_idx,
switch (idx_type->obj_type) {
case NMP_OBJECT_TYPE_IP4_ADDRESS:
case NMP_OBJECT_TYPE_IP6_ADDRESS:
/* we want to keep the maximum addr_source. But since we expect
* that usually we already add the maxiumum right away, we first try to
* add the new address (replacing the old one). Only if we later
* find out that addr_source is now lower, we fix it.
*/
if (obj_new->ip_address.addr_source < obj_old->ip_address.addr_source) {
obj_new = nmp_object_stackinit_obj (&obj_new_stackinit, obj_new);
obj_new_stackinit.ip_address.addr_source = obj_old->ip_address.addr_source;
modified = TRUE;
}
/* for addresses that we read from the kernel, we keep the timestamps as defined
* by the previous source (item_old). The reason is, that the other source configured the lifetimes
* with "what should be" and the kernel values are "what turned out after configuring it".
@ -240,14 +157,17 @@ _nm_ip_config_add_obj (NMDedupMultiIndex *multi_idx,
obj_new_stackinit.ip_address.preferred = NMP_OBJECT_CAST_IP_ADDRESS (obj_old)->preferred;
modified = TRUE;
}
/* keep the maximum addr_source. */
if (obj_new->ip_address.addr_source < obj_old->ip_address.addr_source) {
obj_new = nmp_object_stackinit_obj (&obj_new_stackinit, obj_new);
obj_new_stackinit.ip_address.addr_source = obj_old->ip_address.addr_source;
modified = TRUE;
}
break;
case NMP_OBJECT_TYPE_IP4_ROUTE:
case NMP_OBJECT_TYPE_IP6_ROUTE:
/* we want to keep the maximum rt_source. But since we expect
* that usually we already add the maxiumum right away, we first try to
* add the new route (replacing the old one). Only if we later
* find out that rt_source is now lower, we fix it.
*/
/* keep the maximum rt_source. */
if (obj_new->ip_route.rt_source < obj_old->ip_route.rt_source) {
obj_new = nmp_object_stackinit_obj (&obj_new_stackinit, obj_new);
obj_new_stackinit.ip_route.rt_source = obj_old->ip_route.rt_source;
@ -325,7 +245,7 @@ _nm_ip_config_lookup_ip_route (const NMDedupMultiIndex *multi_idx,
if (!entry)
return NULL;
if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_DST)
if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID)
nm_assert (nm_platform_ip4_route_cmp (NMP_OBJECT_CAST_IP4_ROUTE (entry->obj), NMP_OBJECT_CAST_IP4_ROUTE (needle), cmp_type) == 0);
else {
if (nm_platform_ip4_route_cmp (NMP_OBJECT_CAST_IP4_ROUTE (entry->obj),
@ -777,8 +697,6 @@ nm_ip4_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i
if (route->table_coerced)
continue;
if (route->rt_source == NM_IP_CONFIG_SOURCE_RTPROT_KERNEL)
continue;
_add_route (self, plobj, NULL, NULL);
}
@ -804,23 +722,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);
@ -830,96 +830,16 @@ 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,
AF_INET,
ifindex,
routes,
nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel,
nm_platform_lookup_predicate_routes_main,
NULL))
success = FALSE;
nm_platform_ip4_dev_route_blacklist_set (platform,
ifindex,
ip4_dev_route_blacklist);
return success;
}
@ -1679,7 +1599,8 @@ nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relev
if (nm_platform_ip4_address_cmp (r_src, r_dst) != 0) {
are_equal = FALSE;
if ( !nm_ip_config_obj_id_equal_ip4_address (r_src, r_dst)
if ( r_src->address != r_dst->address
|| r_src->plen != r_dst->plen
|| r_src->peer_address != r_dst->peer_address) {
has_relevant_changes = TRUE;
break;
@ -1725,7 +1646,8 @@ nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relev
if (nm_platform_ip4_route_cmp_full (r_src, r_dst) != 0) {
are_equal = FALSE;
if ( !nm_ip_config_obj_id_equal_ip4_route (r_src, r_dst)
if ( r_src->plen != r_dst->plen
|| !nm_utils_ip4_address_same_prefix (r_src->network, r_dst->network, r_src->plen)
|| r_src->gateway != r_dst->gateway
|| r_src->metric != r_dst->metric) {
has_relevant_changes = TRUE;
@ -2310,7 +2232,7 @@ nm_ip4_config_get_num_routes (const NMIP4Config *self)
const NMDedupMultiHeadEntry *head_entry;
head_entry = nm_ip4_config_lookup_routes (self);
nm_assert ((head_entry ? head_entry->len : 0) == c_list_length (&head_entry->lst_entries_head));
nm_assert (!head_entry || head_entry->len == c_list_length (&head_entry->lst_entries_head));
return head_entry ? head_entry->len : 0;
}

View file

@ -94,15 +94,6 @@ gboolean _nm_ip_config_best_default_route_merge (const NMPObject **best_default_
/*****************************************************************************/
gboolean nm_ip_config_obj_id_equal_ip4_address (const NMPlatformIP4Address *a,
const NMPlatformIP4Address *b);
gboolean nm_ip_config_obj_id_equal_ip6_address (const NMPlatformIP6Address *a,
const NMPlatformIP6Address *b);
gboolean nm_ip_config_obj_id_equal_ip4_route (const NMPlatformIP4Route *r_a,
const NMPlatformIP4Route *r_b);
gboolean nm_ip_config_obj_id_equal_ip6_route (const NMPlatformIP6Route *r_a,
const NMPlatformIP6Route *r_b);
gboolean _nm_ip_config_add_obj (NMDedupMultiIndex *multi_idx,
NMIPConfigDedupMultiIdxType *idx_type,
int ifindex,
@ -159,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);

View file

@ -501,8 +501,6 @@ nm_ip6_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i
if (route->table_coerced)
continue;
if (route->rt_source == NM_IP_CONFIG_SOURCE_RTPROT_KERNEL)
continue;
_add_route (self, plobj, NULL, NULL);
}
@ -553,7 +551,7 @@ nm_ip6_config_commit (const NMIP6Config *self,
AF_INET6,
ifindex,
routes,
nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel,
nm_platform_lookup_predicate_routes_main,
NULL))
success = FALSE;
@ -1277,7 +1275,7 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev
if (nm_platform_ip6_address_cmp (r_src, r_dst) != 0) {
are_equal = FALSE;
if ( !nm_ip_config_obj_id_equal_ip6_address (r_src, r_dst)
if ( !IN6_ARE_ADDR_EQUAL (&r_src->address, &r_dst->address)
|| r_src->plen != r_dst->plen
|| !IN6_ARE_ADDR_EQUAL (nm_platform_ip6_address_get_peer (r_src),
nm_platform_ip6_address_get_peer (r_dst))) {
@ -1325,7 +1323,8 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev
if (nm_platform_ip6_route_cmp_full (r_src, r_dst) != 0) {
are_equal = FALSE;
if ( !nm_ip_config_obj_id_equal_ip6_route (r_src, r_dst)
if ( r_src->plen != r_dst->plen
|| !nm_utils_ip6_address_same_prefix (&r_src->network, &r_dst->network, r_src->plen)
|| r_src->metric != r_dst->metric
|| !IN6_ARE_ADDR_EQUAL (&r_src->gateway, &r_dst->gateway)) {
has_relevant_changes = TRUE;
@ -1945,7 +1944,7 @@ nm_ip6_config_get_num_routes (const NMIP6Config *self)
const NMDedupMultiHeadEntry *head_entry;
head_entry = nm_ip6_config_lookup_routes (self);
nm_assert ((head_entry ? head_entry->len : 0) == c_list_length (&head_entry->lst_entries_head));
nm_assert (!head_entry || head_entry->len == c_list_length (&head_entry->lst_entries_head));
return head_entry ? head_entry->len : 0;
}

View file

@ -2898,6 +2898,15 @@ nm_platform_lookup (NMPlatform *self,
lookup);
}
gboolean
nm_platform_lookup_predicate_routes_main (const NMPObject *obj,
gpointer user_data)
{
nm_assert (NM_IN_SET (NMP_OBJECT_GET_TYPE (obj), NMP_OBJECT_TYPE_IP4_ROUTE,
NMP_OBJECT_TYPE_IP6_ROUTE));
return !obj->ip_route.table_coerced;
}
gboolean
nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel (const NMPObject *obj,
gpointer user_data)
@ -2908,15 +2917,6 @@ nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel (const NMPObject *ob
&& obj->ip_route.rt_source != NM_IP_CONFIG_SOURCE_RTPROT_KERNEL;
}
gboolean
nm_platform_lookup_predicate_routes_skip_rtprot_kernel (const NMPObject *obj,
gpointer user_data)
{
nm_assert (NM_IN_SET (NMP_OBJECT_GET_TYPE (obj), NMP_OBJECT_TYPE_IP4_ROUTE,
NMP_OBJECT_TYPE_IP6_ROUTE));
return obj->ip_route.rt_source != NM_IP_CONFIG_SOURCE_RTPROT_KERNEL;
}
/**
* nm_platform_lookup_clone:
* @self:
@ -5402,10 +5402,6 @@ nm_platform_ip4_route_hash (const NMPlatformIP4Route *obj, NMPlatformIPRouteCmpT
if (obj) {
switch (cmp_type) {
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_DST:
h = NM_HASH_COMBINE (h, nm_utils_ip4_address_clear_host_address (obj->network, obj->plen));
h = NM_HASH_COMBINE (h, obj->plen);
break;
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID:
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID:
h = NM_HASH_COMBINE (h, obj->table_coerced);
@ -5475,10 +5471,6 @@ nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route
{
NM_CMP_SELF (a, b);
switch (cmp_type) {
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_DST:
NM_CMP_DIRECT_IN4ADDR_SAME_PREFIX (a->network, b->network, MIN (a->plen, b->plen));
NM_CMP_FIELD (a, b, plen);
break;
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID:
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID:
NM_CMP_FIELD (a, b, table_coerced);
@ -5553,10 +5545,6 @@ nm_platform_ip6_route_hash (const NMPlatformIP6Route *obj, NMPlatformIPRouteCmpT
if (obj) {
switch (cmp_type) {
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_DST:
h = NM_HASH_COMBINE_IN6ADDR_PREFIX (h, &obj->network, obj->plen);
h = NM_HASH_COMBINE (h, obj->plen);
break;
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID:
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID:
h = NM_HASH_COMBINE (h, obj->table_coerced);
@ -5617,10 +5605,6 @@ nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route
{
NM_CMP_SELF (a, b);
switch (cmp_type) {
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_DST:
NM_CMP_DIRECT_IN6ADDR_SAME_PREFIX (&a->network, &b->network, MIN (a->plen, b->plen));
NM_CMP_FIELD (a, b, plen);
break;
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID:
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID:
NM_CMP_FIELD (a, b, table_coerced);

View file

@ -129,11 +129,6 @@ typedef enum {
*/
NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID,
/* NMIP4Config and NMIP6Config also track a list of routes. They have their
* own notion of what equality means. Basically, they consider network/plen
* for IPv4 and IPv6. */
NM_PLATFORM_IP_ROUTE_CMP_TYPE_DST,
/* compare all fields as they make sense for kernel. For example,
* a route destination 192.168.1.5/24 is not accepted by kernel and
* we treat it identical to 192.168.1.0/24. Semantically these
@ -962,10 +957,10 @@ struct _NMPLookup;
const struct _NMDedupMultiHeadEntry *nm_platform_lookup (NMPlatform *platform,
const struct _NMPLookup *lookup);
gboolean nm_platform_lookup_predicate_routes_main (const NMPObject *obj,
gpointer user_data);
gboolean nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel (const NMPObject *obj,
gpointer user_data);
gboolean nm_platform_lookup_predicate_routes_skip_rtprot_kernel (const NMPObject *obj,
gpointer user_data);
GPtrArray *nm_platform_lookup_clone (NMPlatform *platform,
const struct _NMPLookup *lookup,

View file

@ -1111,10 +1111,12 @@ _vt_cmd_plobj_id_hash (ip6_address, NMPlatformIP6Address, {
hash = NM_HASH_COMBINE (hash, nm_utils_in6_addr_hash (&obj->address));
})
_vt_cmd_plobj_id_hash (ip4_route, NMPlatformIP4Route, {
hash = nm_platform_ip4_route_hash (obj, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID);
hash = (guint) 1038302471u;
hash = NM_HASH_COMBINE (hash, nm_platform_ip4_route_hash (obj, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID));
})
_vt_cmd_plobj_id_hash (ip6_route, NMPlatformIP6Route, {
hash = nm_platform_ip6_route_hash (obj, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID);
hash = (guint) 1233384151u;
hash = NM_HASH_COMBINE (hash, nm_platform_ip6_route_hash (obj, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID));
})
gboolean

View file

@ -225,7 +225,7 @@ test_add_address_with_source (void)
static void
test_add_route_with_source (void)
{
NMIP4Config *a;
gs_unref_object NMIP4Config *a = NULL;
NMPlatformIP4Route route;
const NMPlatformIP4Route *test_route;
@ -236,30 +236,34 @@ test_add_route_with_source (void)
route.rt_source = NM_IP_CONFIG_SOURCE_USER;
nm_ip4_config_add_route (a, &route, NULL);
g_assert_cmpint (nm_ip4_config_get_num_routes (a), ==, 1);
test_route = _nmtst_ip4_config_get_route (a, 0);
g_assert_cmpint (test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_USER);
route.rt_source = NM_IP_CONFIG_SOURCE_VPN;
nm_ip4_config_add_route (a, &route, NULL);
g_assert_cmpint (nm_ip4_config_get_num_routes (a), ==, 1);
test_route = _nmtst_ip4_config_get_route (a, 0);
g_assert_cmpint (test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_USER);
/* Test that a lower priority address source is overwritten */
_nmtst_ip4_config_del_route (a, 0);
g_assert_cmpint (nm_ip4_config_get_num_routes (a), ==, 0);
/* Test that a lower priority address source is overwritten */
route.rt_source = NM_IP_CONFIG_SOURCE_RTPROT_KERNEL;
nm_ip4_config_add_route (a, &route, NULL);
g_assert_cmpint (nm_ip4_config_get_num_routes (a), ==, 1);
test_route = _nmtst_ip4_config_get_route (a, 0);
g_assert_cmpint (test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_RTPROT_KERNEL);
route.rt_source = NM_IP_CONFIG_SOURCE_KERNEL;
nm_ip4_config_add_route (a, &route, NULL);
g_assert_cmpint (nm_ip4_config_get_num_routes (a), ==, 1);
test_route = _nmtst_ip4_config_get_route (a, 0);
g_assert_cmpint (test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_KERNEL);
route.rt_source = NM_IP_CONFIG_SOURCE_USER;
nm_ip4_config_add_route (a, &route, NULL);
test_route = _nmtst_ip4_config_get_route (a, 0);
g_assert_cmpint (test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_USER);
g_object_unref (a);
}
static void

View file

@ -196,7 +196,7 @@ test_add_address_with_source (void)
static void
test_add_route_with_source (void)
{
NMIP6Config *a;
gs_unref_object NMIP6Config *a = NULL;
NMPlatformIP6Route route;
const NMPlatformIP6Route *test_route;
@ -207,30 +207,34 @@ test_add_route_with_source (void)
route.rt_source = NM_IP_CONFIG_SOURCE_USER;
nm_ip6_config_add_route (a, &route, NULL);
g_assert_cmpint (nm_ip6_config_get_num_routes (a), ==, 1);
test_route = _nmtst_ip6_config_get_route (a, 0);
g_assert_cmpint (test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_USER);
route.rt_source = NM_IP_CONFIG_SOURCE_VPN;
nm_ip6_config_add_route (a, &route, NULL);
g_assert_cmpint (nm_ip6_config_get_num_routes (a), ==, 1);
test_route = _nmtst_ip6_config_get_route (a, 0);
g_assert_cmpint (test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_USER);
/* Test that a lower priority address source is overwritten */
_nmtst_ip6_config_del_route (a, 0);
g_assert_cmpint (nm_ip6_config_get_num_routes (a), ==, 0);
/* Test that a lower priority address source is overwritten */
route.rt_source = NM_IP_CONFIG_SOURCE_KERNEL;
nm_ip6_config_add_route (a, &route, NULL);
g_assert_cmpint (nm_ip6_config_get_num_routes (a), ==, 1);
test_route = _nmtst_ip6_config_get_route (a, 0);
g_assert_cmpint (test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_KERNEL);
route.rt_source = NM_IP_CONFIG_SOURCE_USER;
nm_ip6_config_add_route (a, &route, NULL);
g_assert_cmpint (nm_ip6_config_get_num_routes (a), ==, 1);
test_route = _nmtst_ip6_config_get_route (a, 0);
g_assert_cmpint (test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_USER);
g_object_unref (a);
}
static void

View file

@ -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);