diff --git a/include/nm-test-utils.h b/include/nm-test-utils.h index 14d4bb4514..3007674e13 100644 --- a/include/nm-test-utils.h +++ b/include/nm-test-utils.h @@ -812,6 +812,38 @@ nmtst_platform_ip6_address_full (const char *address, const char *peer_address, return addr; } +inline static NMPlatformIP4Route * +nmtst_platform_ip4_route (const char *network, guint plen, const char *gateway) +{ + static NMPlatformIP4Route route; + + memset (&route, 0, sizeof (route)); + route.network = nmtst_inet4_from_string (network); + route.plen = plen; + route.gateway = nmtst_inet4_from_string (gateway); + + return &route; +} + +inline static NMPlatformIP4Route * +nmtst_platform_ip4_route_full (const char *network, guint plen, const char *gateway, + int ifindex, NMIPConfigSource source, + guint metric, guint mss, + guint8 scope, + const char *pref_src) +{ + NMPlatformIP4Route *route = nmtst_platform_ip4_route (network, plen, gateway); + + route->ifindex = ifindex; + route->source = source; + route->metric = metric; + route->mss = mss; + route->scope_inv = nm_platform_route_scope_inv (scope); + route->pref_src = nmtst_inet4_from_string (pref_src); + + return route; +} + inline static NMPlatformIP6Route * nmtst_platform_ip6_route (const char *network, guint plen, const char *gateway) { diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 48d2004fe6..415465ada2 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -351,6 +351,7 @@ static gboolean nm_device_set_ip4_config (NMDevice *self, NMIP4Config *config, guint32 default_route_metric, gboolean commit, + gboolean routes_full_sync, NMDeviceStateReason *reason); static gboolean ip4_config_merge_and_apply (NMDevice *self, NMIP4Config *config, @@ -360,6 +361,7 @@ static gboolean ip4_config_merge_and_apply (NMDevice *self, static gboolean nm_device_set_ip6_config (NMDevice *self, NMIP6Config *config, gboolean commit, + gboolean routes_full_sync, NMDeviceStateReason *reason); static gboolean nm_device_master_add_slave (NMDevice *self, NMDevice *slave, gboolean configure); @@ -3248,6 +3250,7 @@ ip4_config_merge_and_apply (NMDevice *self, const guint32 default_route_metric = nm_device_get_ip4_route_metric (self); guint32 gateway; gboolean connection_has_default_route, connection_is_never_default; + gboolean routes_full_sync; /* Merge all the configs into the composite config */ if (config) { @@ -3312,6 +3315,10 @@ ip4_config_merge_and_apply (NMDevice *self, priv->default_route.v4_has = FALSE; priv->default_route.v4_is_assumed = TRUE; + routes_full_sync = commit + && priv->default_route.v4_configure_first_time + && !nm_device_uses_assumed_connection (self); + if (!commit) { /* during a non-commit event, we always pickup whatever is configured. */ goto END_ADD_DEFAULT_ROUTE; @@ -3391,7 +3398,7 @@ END_ADD_DEFAULT_ROUTE: NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit (self, composite); } - success = nm_device_set_ip4_config (self, composite, default_route_metric, commit, out_reason); + success = nm_device_set_ip4_config (self, composite, default_route_metric, commit, routes_full_sync, out_reason); g_object_unref (composite); return success; } @@ -3864,6 +3871,7 @@ ip6_config_merge_and_apply (NMDevice *self, gboolean has_direct_route; const struct in6_addr *gateway; gboolean connection_has_default_route, connection_is_never_default; + gboolean routes_full_sync; /* If no config was passed in, create a new one */ composite = nm_ip6_config_new (nm_device_get_ip_ifindex (self)); @@ -3926,6 +3934,10 @@ ip6_config_merge_and_apply (NMDevice *self, priv->default_route.v6_has = FALSE; priv->default_route.v6_is_assumed = TRUE; + routes_full_sync = commit + && priv->default_route.v6_configure_first_time + && !nm_device_uses_assumed_connection (self); + if (!commit) { /* during a non-commit event, we always pickup whatever is configured. */ goto END_ADD_DEFAULT_ROUTE; @@ -4008,7 +4020,7 @@ END_ADD_DEFAULT_ROUTE: NM_DEVICE_GET_CLASS (self)->ip6_config_pre_commit (self, composite); } - success = nm_device_set_ip6_config (self, composite, commit, out_reason); + success = nm_device_set_ip6_config (self, composite, commit, routes_full_sync, out_reason); g_object_unref (composite); return success; } @@ -6317,6 +6329,7 @@ nm_device_set_ip4_config (NMDevice *self, NMIP4Config *new_config, guint32 default_route_metric, gboolean commit, + gboolean routes_full_sync, NMDeviceStateReason *reason) { NMDevicePrivate *priv; @@ -6351,6 +6364,7 @@ nm_device_set_ip4_config (NMDevice *self, * FIXME: this is wrong in case where "assumed" means "take-over-seamlessly". In this * case, we should manage the device route, for example on new DHCP lease. */ success = nm_ip4_config_commit (new_config, ip_ifindex, + routes_full_sync, assumed ? (gint64) -1 : (gint64) default_route_metric); if (!success) reason_local = NM_DEVICE_STATE_REASON_CONFIG_FAILED; @@ -6456,6 +6470,7 @@ static gboolean nm_device_set_ip6_config (NMDevice *self, NMIP6Config *new_config, gboolean commit, + gboolean routes_full_sync, NMDeviceStateReason *reason) { NMDevicePrivate *priv; @@ -6483,7 +6498,9 @@ nm_device_set_ip6_config (NMDevice *self, /* Always commit to nm-platform to update lifetimes */ if (commit && new_config) { nm_device_ipv6_set_mtu (self, priv->ip6_mtu); - success = nm_ip6_config_commit (new_config, ip_ifindex); + success = nm_ip6_config_commit (new_config, + ip_ifindex, + routes_full_sync); if (!success) reason_local = NM_DEVICE_STATE_REASON_CONFIG_FAILED; } @@ -7937,8 +7954,8 @@ _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, &ignored); - nm_device_set_ip6_config (self, NULL, TRUE, &ignored); + nm_device_set_ip4_config (self, NULL, 0, TRUE, TRUE, &ignored); + nm_device_set_ip6_config (self, NULL, TRUE, TRUE, &ignored); g_clear_object (&priv->con_ip4_config); g_clear_object (&priv->dev_ip4_config); g_clear_object (&priv->ext_ip4_config); diff --git a/src/nm-iface-helper.c b/src/nm-iface-helper.c index 3cdd165965..cbff221a85 100644 --- a/src/nm-iface-helper.c +++ b/src/nm-iface-helper.c @@ -104,7 +104,7 @@ dhcp4_state_changed (NMDhcpClient *client, nm_ip4_config_subtract (existing, last_config); nm_ip4_config_merge (existing, ip4_config); - if (!nm_ip4_config_commit (existing, ifindex, global_opt.priority_v4)) + if (!nm_ip4_config_commit (existing, ifindex, TRUE, global_opt.priority_v4)) nm_log_warn (LOGD_DHCP4, "(%s): failed to apply DHCPv4 config", global_opt.ifname); if (last_config) @@ -241,7 +241,7 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, gpointer user_da nm_ip6_config_subtract (existing, last_config); nm_ip6_config_merge (existing, ip6_config); - if (!nm_ip6_config_commit (existing, ifindex)) + if (!nm_ip6_config_commit (existing, ifindex, TRUE)) nm_log_warn (LOGD_IP6, "(%s): failed to apply IPv6 config", global_opt.ifname); if (last_config) diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index c811e24d34..2b137ff73a 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -290,7 +290,7 @@ nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf) } gboolean -nm_ip4_config_commit (const NMIP4Config *config, int ifindex, gint64 default_route_metric) +nm_ip4_config_commit (const NMIP4Config *config, int ifindex, gboolean routes_full_sync, gint64 default_route_metric) { NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); int i; @@ -359,7 +359,7 @@ nm_ip4_config_commit (const NMIP4Config *config, int ifindex, gint64 default_rou nm_route_manager_ip4_route_register_device_route_purge_list (nm_route_manager_get (), device_route_purge_list); - success = nm_route_manager_ip4_route_sync (nm_route_manager_get (), ifindex, routes, default_route_metric < 0); + success = nm_route_manager_ip4_route_sync (nm_route_manager_get (), ifindex, routes, default_route_metric < 0, routes_full_sync); g_array_unref (routes); if (!success) return FALSE; diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index 0088934a45..0f457217a4 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -71,7 +71,7 @@ const char * nm_ip4_config_get_dbus_path (const NMIP4Config *config); /* Integration with nm-platform and nm-setting */ NMIP4Config *nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf); -gboolean nm_ip4_config_commit (const NMIP4Config *config, int ifindex, gint64 default_route_metric); +gboolean nm_ip4_config_commit (const NMIP4Config *config, int ifindex, gboolean routes_full_sync, gint64 default_route_metric); void nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIPConfig *setting, guint32 default_route_metric); NMSetting *nm_ip4_config_create_setting (const NMIP4Config *config); diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index 082f1d2db7..4794a0ae38 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -406,7 +406,7 @@ nm_ip6_config_capture (int ifindex, gboolean capture_resolv_conf, NMSettingIP6Co } gboolean -nm_ip6_config_commit (const NMIP6Config *config, int ifindex) +nm_ip6_config_commit (const NMIP6Config *config, int ifindex, gboolean routes_full_sync) { NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); int i; @@ -437,7 +437,7 @@ nm_ip6_config_commit (const NMIP6Config *config, int ifindex) g_array_append_vals (routes, route, 1); } - success = nm_route_manager_ip6_route_sync (nm_route_manager_get (), ifindex, routes, TRUE); + success = nm_route_manager_ip6_route_sync (nm_route_manager_get (), ifindex, routes, TRUE, routes_full_sync); g_array_unref (routes); } diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h index 799364e4db..e8cbc0e5f9 100644 --- a/src/nm-ip6-config.h +++ b/src/nm-ip6-config.h @@ -71,7 +71,7 @@ const char * nm_ip6_config_get_dbus_path (const NMIP6Config *config); /* Integration with nm-platform and nm-setting */ NMIP6Config *nm_ip6_config_capture (int ifindex, gboolean capture_resolv_conf, NMSettingIP6ConfigPrivacy use_temporary); -gboolean nm_ip6_config_commit (const NMIP6Config *config, int ifindex); +gboolean nm_ip6_config_commit (const NMIP6Config *config, int ifindex, gboolean routes_full_sync); void nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIPConfig *setting, guint32 default_route_metric); NMSetting *nm_ip6_config_create_setting (const NMIP6Config *config); diff --git a/src/nm-route-manager.c b/src/nm-route-manager.c index 975c95b887..5ee6c8654f 100644 --- a/src/nm-route-manager.c +++ b/src/nm-route-manager.c @@ -445,7 +445,7 @@ _sort_indexes_cmp (guint *a, guint *b) /*********************************************************************************************/ static gboolean -_vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const GArray *known_routes, gboolean ignore_kernel_routes) +_vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const GArray *known_routes, gboolean ignore_kernel_routes, gboolean full_sync) { NMRouteManagerPrivate *priv = NM_ROUTE_MANAGER_GET_PRIVATE (self); GArray *plat_routes; @@ -484,7 +484,7 @@ _vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const ifindex, i, vtable->vt->route_to_string (VTABLE_ROUTE_INDEX (vtable, known_routes, i))); } for (i = 0; i < ipx_routes->index->len; i++) - _LOGT (vtable->vt->addr_family, "%3d: STATE: has #%u - %s (%lld)", + _LOGT (vtable->vt->addr_family, "%3d: STATE: has #%u - %s (%lld)", ifindex, i, vtable->vt->route_to_string (ipx_routes->index->entries[i]), (long long) g_array_index (ipx_routes->effective_metrics, gint64, i)); @@ -526,7 +526,7 @@ _vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const cur_ipx_route->rx.ifindex = ifindex; cur_ipx_route->rx.metric = vtable->vt->metric_normalize (cur_ipx_route->rx.metric); ipx_routes_changed = TRUE; - _LOGT (vtable->vt->addr_family, "%3d: STATE: update #%u - %s", ifindex, i_ipx_routes, vtable->vt->route_to_string (cur_ipx_route)); + _LOGT (vtable->vt->addr_family, "%3d: STATE: update #%u - %s", ifindex, i_ipx_routes, vtable->vt->route_to_string (cur_ipx_route)); } } else if (cur_known_route) { g_assert (!cur_ipx_route || route_id_cmp_result > 0); @@ -543,13 +543,60 @@ _vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const cur_known_route = _get_next_known_route (vtable, known_routes_idx, FALSE, &i_known_routes); } + if (!full_sync && to_delete_indexes) { + /*************************************************************************** + * Delete routes in platform, that we are about to remove from @ipx_routes + * + * When doing a non-full_sync, we delete routes from platform that were previously + * known by route-manager, and are now deleted. + ***************************************************************************/ + + /* iterate over @to_delete_indexes and @plat_routes. + * @to_delete_indexes contains the indexes (relative to ipx_routes->index) of items + * we are about to delete. */ + cur_plat_route = _get_next_plat_route (plat_routes_idx, TRUE, &i_plat_routes); + for (i = 0; i < to_delete_indexes->len; i++) { + int route_dest_cmp_result = 0; + i_ipx_routes = g_array_index (to_delete_indexes, guint, i); + cur_ipx_route = ipx_routes->index->entries[i_ipx_routes]; + p_effective_metric = &effective_metrics[i_ipx_routes]; + + nm_assert (cur_ipx_route->rx.ifindex == ifindex); + + if (*p_effective_metric == -1) + continue; + + /* skip over @plat_routes that are ordered before our @cur_ipx_route. */ + while ( cur_plat_route + && (route_dest_cmp_result = vtable->route_dest_cmp (cur_plat_route, cur_ipx_route)) <= 0) { + if ( route_dest_cmp_result == 0 + && cur_plat_route->rx.metric >= *p_effective_metric) + break; + cur_plat_route = _get_next_plat_route (plat_routes_idx, FALSE, &i_plat_routes); + } + + if (!cur_plat_route) { + /* no more platform routes. Break the loop. */ + break; + } + + if ( route_dest_cmp_result == 0 + && cur_plat_route->rx.metric == *p_effective_metric) { + /* we are about to delete cur_ipx_route and we have a matching route + * in platform. Delete it. */ + _LOGT (vtable->vt->addr_family, "%3d: platform rt-rm #%u - %s", ifindex, i_plat_routes, vtable->vt->route_to_string (cur_plat_route)); + vtable->vt->route_delete (priv->platform, ifindex, cur_plat_route); + } + } + } + /* Update @ipx_routes with the just learned changes. */ if (to_delete_indexes || to_add_routes) { if (to_delete_indexes) { for (i = 0; i < to_delete_indexes->len; i++) { guint idx = g_array_index (to_delete_indexes, guint, i); - _LOGT (vtable->vt->addr_family, "%3d: STATE: delete #%u - %s", ifindex, idx, vtable->vt->route_to_string (ipx_routes->index->entries[idx])); + _LOGT (vtable->vt->addr_family, "%3d: STATE: delete #%u - %s", ifindex, idx, vtable->vt->route_to_string (ipx_routes->index->entries[idx])); g_array_index (to_delete_indexes, guint, i) = _route_index_reverse_idx (vtable, ipx_routes->index, idx, ipx_routes->entries); } g_array_sort (to_delete_indexes, (GCompareFunc) _sort_indexes_cmp); @@ -573,7 +620,7 @@ _vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const g_array_index (ipx_routes->effective_metrics_reverse, gint64, j++) = -1; - _LOGT (vtable->vt->addr_family, "%3d: STATE: added #%u - %s", ifindex, ipx_routes->entries->len - 1, vtable->vt->route_to_string (ipx_route)); + _LOGT (vtable->vt->addr_family, "%3d: STATE: added #%u - %s", ifindex, ipx_routes->entries->len - 1, vtable->vt->route_to_string (ipx_route)); } g_ptr_array_unref (to_add_routes); } @@ -658,49 +705,54 @@ _vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const break; } next: - _LOGT (vtable->vt->addr_family, "%3d: new metric #%u - %s (%lld)", + _LOGT (vtable->vt->addr_family, "%3d: new metric #%u - %s (%lld)", ifindex, i_ipx_routes, vtable->vt->route_to_string (cur_ipx_route), (long long) *p_effective_metric); } } - /*************************************************************************** - * Delete routes in platform, that no longer exist in @ipx_routes - ***************************************************************************/ + if (full_sync) { + /*************************************************************************** + * Delete all routes in platform, that no longer exist in @ipx_routes + * + * Different from the delete action above, we delete every unknown route on + * the interface. + ***************************************************************************/ - /* iterate over @plat_routes and @ipx_routes */ - cur_plat_route = _get_next_plat_route (plat_routes_idx, TRUE, &i_plat_routes); - cur_ipx_route = _get_next_ipx_route (ipx_routes->index, TRUE, &i_ipx_routes, ifindex); - if (cur_ipx_route) - p_effective_metric = &effective_metrics[i_ipx_routes]; - while (cur_plat_route) { - int route_dest_cmp_result = 0; + /* iterate over @plat_routes and @ipx_routes */ + cur_plat_route = _get_next_plat_route (plat_routes_idx, TRUE, &i_plat_routes); + cur_ipx_route = _get_next_ipx_route (ipx_routes->index, TRUE, &i_ipx_routes, ifindex); + if (cur_ipx_route) + p_effective_metric = &effective_metrics[i_ipx_routes]; + while (cur_plat_route) { + int route_dest_cmp_result = 0; - g_assert (cur_plat_route->rx.ifindex == ifindex); + g_assert (cur_plat_route->rx.ifindex == ifindex); - _LOGT (vtable->vt->addr_family, "%3d: platform rt #%u - %s", ifindex, i_plat_routes, vtable->vt->route_to_string (cur_plat_route)); + _LOGT (vtable->vt->addr_family, "%3d: platform rt #%u - %s", ifindex, i_plat_routes, vtable->vt->route_to_string (cur_plat_route)); - /* skip over @cur_ipx_route that are ordered before @cur_plat_route */ - while ( cur_ipx_route - && ((route_dest_cmp_result = vtable->route_dest_cmp (cur_ipx_route, cur_plat_route)) <= 0)) { - if ( route_dest_cmp_result == 0 - && *p_effective_metric != -1 - && *p_effective_metric >= cur_plat_route->rx.metric) { - break; + /* skip over @cur_ipx_route that are ordered before @cur_plat_route */ + while ( cur_ipx_route + && ((route_dest_cmp_result = vtable->route_dest_cmp (cur_ipx_route, cur_plat_route)) <= 0)) { + if ( route_dest_cmp_result == 0 + && *p_effective_metric != -1 + && *p_effective_metric >= cur_plat_route->rx.metric) { + break; + } + cur_ipx_route = _get_next_ipx_route (ipx_routes->index, FALSE, &i_ipx_routes, ifindex); + if (cur_ipx_route) + p_effective_metric = &effective_metrics[i_ipx_routes]; } - cur_ipx_route = _get_next_ipx_route (ipx_routes->index, FALSE, &i_ipx_routes, ifindex); - if (cur_ipx_route) - p_effective_metric = &effective_metrics[i_ipx_routes]; + + /* if @cur_ipx_route is not equal to @plat_route, the route must be deleted. */ + if ( !cur_ipx_route + || route_dest_cmp_result != 0 + || *p_effective_metric != cur_plat_route->rx.metric) + vtable->vt->route_delete (priv->platform, ifindex, cur_plat_route); + + cur_plat_route = _get_next_plat_route (plat_routes_idx, FALSE, &i_plat_routes); } - - /* if @cur_ipx_route is not equal to @plat_route, the route must be deleted. */ - if ( !cur_ipx_route - || route_dest_cmp_result != 0 - || *p_effective_metric != cur_plat_route->rx.metric) - vtable->vt->route_delete (priv->platform, ifindex, cur_plat_route); - - cur_plat_route = _get_next_plat_route (plat_routes_idx, FALSE, &i_plat_routes); } /*************************************************************************** @@ -796,7 +848,7 @@ next: * we need to know whether a route is shadowed by another route, and that * requires to look at @ipx_routes. */ for (; cur_ipx_route; cur_ipx_route = _get_next_ipx_route (ipx_routes->index, FALSE, &i_ipx_routes, ifindex)) { - int route_id_dest_result = -1; + int route_dest_cmp_result = -1; if ( (i_type == 0 && !VTABLE_IS_DEVICE_ROUTE (vtable, cur_ipx_route)) || (i_type == 1 && VTABLE_IS_DEVICE_ROUTE (vtable, cur_ipx_route))) { @@ -814,8 +866,8 @@ next: /* skip over @plat_routes that are ordered before our @cur_ipx_route. */ while ( cur_plat_route - && (route_id_dest_result = vtable->route_dest_cmp (cur_plat_route, cur_ipx_route)) <= 0) { - if ( route_id_dest_result == 0 + && (route_dest_cmp_result = vtable->route_dest_cmp (cur_plat_route, cur_ipx_route)) <= 0) { + if ( route_dest_cmp_result == 0 && cur_plat_route->rx.metric >= *p_effective_metric) break; cur_plat_route = _get_next_plat_route (plat_routes_idx, FALSE, &i_plat_routes); @@ -824,7 +876,7 @@ next: /* only add the route if we don't have an identical route in @plat_routes, * i.e. if @cur_plat_route is different from @cur_ipx_route. */ if ( !cur_plat_route - || route_id_dest_result != 0 + || route_dest_cmp_result != 0 || !_route_equals_ignoring_ifindex (vtable, cur_plat_route, cur_ipx_route, *p_effective_metric)) { if (!vtable->vt->route_add (priv->platform, ifindex, cur_ipx_route, *p_effective_metric)) { @@ -855,6 +907,9 @@ next: * @ifindex: Interface index * @known_routes: List of routes * @ignore_kernel_routes: if %TRUE, ignore kernel routes. + * @full_sync: whether to do a full sync and delete routes + * that are configured on the interface but not currently + * tracked by route-manager. * * A convenience function to synchronize routes for a specific interface * with the least possible disturbance. It simply removes routes that are @@ -865,9 +920,9 @@ next: * Returns: %TRUE on success. */ gboolean -nm_route_manager_ip4_route_sync (NMRouteManager *self, int ifindex, const GArray *known_routes, gboolean ignore_kernel_routes) +nm_route_manager_ip4_route_sync (NMRouteManager *self, int ifindex, const GArray *known_routes, gboolean ignore_kernel_routes, gboolean full_sync) { - return _vx_route_sync (&vtable_v4, self, ifindex, known_routes, ignore_kernel_routes); + return _vx_route_sync (&vtable_v4, self, ifindex, known_routes, ignore_kernel_routes, full_sync); } /** @@ -875,6 +930,9 @@ nm_route_manager_ip4_route_sync (NMRouteManager *self, int ifindex, const GArray * @ifindex: Interface index * @known_routes: List of routes * @ignore_kernel_routes: if %TRUE, ignore kernel routes. + * @full_sync: whether to do a full sync and delete routes + * that are configured on the interface but not currently + * tracked by route-manager. * * A convenience function to synchronize routes for a specific interface * with the least possible disturbance. It simply removes routes that are @@ -885,16 +943,16 @@ nm_route_manager_ip4_route_sync (NMRouteManager *self, int ifindex, const GArray * Returns: %TRUE on success. */ gboolean -nm_route_manager_ip6_route_sync (NMRouteManager *self, int ifindex, const GArray *known_routes, gboolean ignore_kernel_routes) +nm_route_manager_ip6_route_sync (NMRouteManager *self, int ifindex, const GArray *known_routes, gboolean ignore_kernel_routes, gboolean full_sync) { - return _vx_route_sync (&vtable_v6, self, ifindex, known_routes, ignore_kernel_routes); + return _vx_route_sync (&vtable_v6, self, ifindex, known_routes, ignore_kernel_routes, full_sync); } gboolean nm_route_manager_route_flush (NMRouteManager *self, int ifindex) { - return nm_route_manager_ip4_route_sync (self, ifindex, NULL, FALSE) - && nm_route_manager_ip6_route_sync (self, ifindex, NULL, FALSE); + return nm_route_manager_ip4_route_sync (self, ifindex, NULL, FALSE, TRUE) + && nm_route_manager_ip6_route_sync (self, ifindex, NULL, FALSE, TRUE); } /*********************************************************************************************/ diff --git a/src/nm-route-manager.h b/src/nm-route-manager.h index fdd310b73b..1e4ce4840f 100644 --- a/src/nm-route-manager.h +++ b/src/nm-route-manager.h @@ -42,8 +42,8 @@ typedef struct { GType nm_route_manager_get_type (void); -gboolean nm_route_manager_ip4_route_sync (NMRouteManager *self, int ifindex, const GArray *known_routes, gboolean ignore_kernel_routes); -gboolean nm_route_manager_ip6_route_sync (NMRouteManager *self, int ifindex, const GArray *known_routes, gboolean ignore_kernel_routes); +gboolean nm_route_manager_ip4_route_sync (NMRouteManager *self, int ifindex, const GArray *known_routes, gboolean ignore_kernel_routes, gboolean full_sync); +gboolean nm_route_manager_ip6_route_sync (NMRouteManager *self, int ifindex, const GArray *known_routes, gboolean ignore_kernel_routes, gboolean full_sync); gboolean nm_route_manager_route_flush (NMRouteManager *self, int ifindex); void nm_route_manager_ip4_route_register_device_route_purge_list (NMRouteManager *self, GArray *device_route_purge_list); diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c index 147e956167..d5aeb0301f 100644 --- a/src/platform/nm-fake-platform.c +++ b/src/platform/nm-fake-platform.c @@ -992,8 +992,8 @@ ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, int return TRUE; } -static gboolean -ip4_address_exists (NMPlatform *platform, int ifindex, in_addr_t addr, int plen) +static const NMPlatformIP4Address * +ip4_address_get (NMPlatform *platform, int ifindex, in_addr_t addr, int plen) { NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); int i; @@ -1002,14 +1002,14 @@ ip4_address_exists (NMPlatform *platform, int ifindex, in_addr_t addr, int plen) NMPlatformIP4Address *address = &g_array_index (priv->ip4_addresses, NMPlatformIP4Address, i); if (address->ifindex == ifindex && address->plen == plen && address->address == addr) - return TRUE; + return address; } - return FALSE; + return NULL; } -static gboolean -ip6_address_exists (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen) +static const NMPlatformIP6Address * +ip6_address_get (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen) { NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); int i; @@ -1019,10 +1019,10 @@ ip6_address_exists (NMPlatform *platform, int ifindex, struct in6_addr addr, int if (address->ifindex == ifindex && address->plen == plen && IN6_ARE_ADDR_EQUAL (&address->address, &addr)) - return TRUE; + return address; } - return FALSE; + return NULL; } /******************************************************************/ @@ -1271,7 +1271,7 @@ ip6_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source, return TRUE; } -static NMPlatformIP4Route * +static const NMPlatformIP4Route * ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, int plen, guint32 metric) { NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); @@ -1290,7 +1290,7 @@ ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, int plen, g return NULL; } -static NMPlatformIP6Route * +static const NMPlatformIP6Route * ip6_route_get (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, guint32 metric) { NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); @@ -1311,18 +1311,6 @@ ip6_route_get (NMPlatform *platform, int ifindex, struct in6_addr network, int p return NULL; } -static gboolean -ip4_route_exists (NMPlatform *platform, int ifindex, in_addr_t network, int plen, guint32 metric) -{ - return !!ip4_route_get (platform, ifindex, network, plen, metric); -} - -static gboolean -ip6_route_exists (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, guint32 metric) -{ - return !!ip6_route_get (platform, ifindex, network, plen, metric); -} - /******************************************************************/ static void @@ -1453,21 +1441,21 @@ nm_fake_platform_class_init (NMFakePlatformClass *klass) platform_class->mesh_set_channel = mesh_set_channel; platform_class->mesh_set_ssid = mesh_set_ssid; + platform_class->ip4_address_get = ip4_address_get; + platform_class->ip6_address_get = ip6_address_get; platform_class->ip4_address_get_all = ip4_address_get_all; platform_class->ip6_address_get_all = ip6_address_get_all; platform_class->ip4_address_add = ip4_address_add; platform_class->ip6_address_add = ip6_address_add; platform_class->ip4_address_delete = ip4_address_delete; platform_class->ip6_address_delete = ip6_address_delete; - platform_class->ip4_address_exists = ip4_address_exists; - platform_class->ip6_address_exists = ip6_address_exists; + platform_class->ip4_route_get = ip4_route_get; + platform_class->ip6_route_get = ip6_route_get; platform_class->ip4_route_get_all = ip4_route_get_all; platform_class->ip6_route_get_all = ip6_route_get_all; platform_class->ip4_route_add = ip4_route_add; platform_class->ip6_route_add = ip6_route_add; platform_class->ip4_route_delete = ip4_route_delete; platform_class->ip6_route_delete = ip6_route_delete; - platform_class->ip4_route_exists = ip4_route_exists; - platform_class->ip6_route_exists = ip6_route_exists; } diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index efbdbe3351..f3a9254531 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -4163,22 +4163,30 @@ ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, int return do_delete_object (platform, &obj_needle, NULL); } -static gboolean -ip4_address_exists (NMPlatform *platform, int ifindex, in_addr_t addr, int plen) +static const NMPlatformIP4Address * +ip4_address_get (NMPlatform *platform, int ifindex, in_addr_t addr, int plen) { NMPObject obj_needle; + const NMPObject *obj; nmp_object_stackinit_id_ip4_address (&obj_needle, ifindex, addr, plen); - return nmp_object_is_visible (nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, &obj_needle)); + obj = nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, &obj_needle); + if (nmp_object_is_visible (obj)) + return &obj->ip4_address; + return NULL; } -static gboolean -ip6_address_exists (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen) +static const NMPlatformIP6Address * +ip6_address_get (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen) { NMPObject obj_needle; + const NMPObject *obj; nmp_object_stackinit_id_ip6_address (&obj_needle, ifindex, &addr, plen); - return nmp_object_is_visible (nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, &obj_needle)); + obj = nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, &obj_needle); + if (nmp_object_is_visible (obj)) + return &obj->ip6_address; + return NULL; } /******************************************************************/ @@ -4461,24 +4469,32 @@ ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, in return do_delete_object (platform, &obj_needle, nlo); } -static gboolean -ip4_route_exists (NMPlatform *platform, int ifindex, in_addr_t network, int plen, guint32 metric) +static const NMPlatformIP4Route * +ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, int plen, guint32 metric) { NMPObject obj_needle; + const NMPObject *obj; nmp_object_stackinit_id_ip4_route (&obj_needle, ifindex, network, plen, metric); - return nmp_object_is_visible (nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, &obj_needle)); + obj = nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, &obj_needle); + if (nmp_object_is_visible (obj)) + return &obj->ip4_route; + return NULL; } -static gboolean -ip6_route_exists (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, guint32 metric) +static const NMPlatformIP6Route * +ip6_route_get (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, guint32 metric) { NMPObject obj_needle; + const NMPObject *obj; metric = nm_utils_ip6_route_metric_normalize (metric); nmp_object_stackinit_id_ip6_route (&obj_needle, ifindex, &network, plen, metric); - return nmp_object_is_visible (nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, &obj_needle)); + obj = nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, &obj_needle); + if (nmp_object_is_visible (obj)) + return &obj->ip6_route; + return NULL; } /******************************************************************/ @@ -4985,23 +5001,23 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass) platform_class->mesh_set_channel = mesh_set_channel; platform_class->mesh_set_ssid = mesh_set_ssid; + platform_class->ip4_address_get = ip4_address_get; + platform_class->ip6_address_get = ip6_address_get; platform_class->ip4_address_get_all = ip4_address_get_all; platform_class->ip6_address_get_all = ip6_address_get_all; platform_class->ip4_address_add = ip4_address_add; platform_class->ip6_address_add = ip6_address_add; platform_class->ip4_address_delete = ip4_address_delete; platform_class->ip6_address_delete = ip6_address_delete; - platform_class->ip4_address_exists = ip4_address_exists; - platform_class->ip6_address_exists = ip6_address_exists; + platform_class->ip4_route_get = ip4_route_get; + platform_class->ip6_route_get = ip6_route_get; platform_class->ip4_route_get_all = ip4_route_get_all; platform_class->ip6_route_get_all = ip6_route_get_all; platform_class->ip4_route_add = ip4_route_add; platform_class->ip6_route_add = ip6_route_add; platform_class->ip4_route_delete = ip4_route_delete; platform_class->ip6_route_delete = ip6_route_delete; - platform_class->ip4_route_exists = ip4_route_exists; - platform_class->ip6_route_exists = ip6_route_exists; platform_class->check_support_kernel_extended_ifa_flags = check_support_kernel_extended_ifa_flags; platform_class->check_support_user_ipv6ll = check_support_user_ipv6ll; diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 2a7945d11d..8803377a5b 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -1971,26 +1971,24 @@ nm_platform_ip6_address_delete (NMPlatform *self, int ifindex, struct in6_addr a return klass->ip6_address_delete (self, ifindex, address, plen); } -gboolean -nm_platform_ip4_address_exists (NMPlatform *self, int ifindex, in_addr_t address, int plen) +const NMPlatformIP4Address * +nm_platform_ip4_address_get (NMPlatform *self, int ifindex, in_addr_t address, int plen) { _CHECK_SELF (self, klass, FALSE); g_return_val_if_fail (plen > 0, FALSE); - g_return_val_if_fail (klass->ip4_address_exists, FALSE); - return klass->ip4_address_exists (self, ifindex, address, plen); + return klass->ip4_address_get (self, ifindex, address, plen); } -gboolean -nm_platform_ip6_address_exists (NMPlatform *self, int ifindex, struct in6_addr address, int plen) +const NMPlatformIP6Address * +nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr address, int plen) { _CHECK_SELF (self, klass, FALSE); g_return_val_if_fail (plen > 0, FALSE); - g_return_val_if_fail (klass->ip6_address_exists, FALSE); - return klass->ip6_address_exists (self, ifindex, address, plen); + return klass->ip6_address_get (self, ifindex, address, plen); } static gboolean @@ -2272,24 +2270,20 @@ nm_platform_ip6_route_delete (NMPlatform *self, int ifindex, struct in6_addr net return klass->ip6_route_delete (self, ifindex, network, plen, metric); } -gboolean -nm_platform_ip4_route_exists (NMPlatform *self, int ifindex, in_addr_t network, int plen, guint32 metric) +const NMPlatformIP4Route * +nm_platform_ip4_route_get (NMPlatform *self, int ifindex, in_addr_t network, int plen, guint32 metric) { _CHECK_SELF (self, klass, FALSE); - g_return_val_if_fail (klass->ip4_route_exists, FALSE); - - return klass->ip4_route_exists (self ,ifindex, network, plen, metric); + return klass->ip4_route_get (self ,ifindex, network, plen, metric); } -gboolean -nm_platform_ip6_route_exists (NMPlatform *self, int ifindex, struct in6_addr network, int plen, guint32 metric) +const NMPlatformIP6Route * +nm_platform_ip6_route_get (NMPlatform *self, int ifindex, struct in6_addr network, int plen, guint32 metric) { _CHECK_SELF (self, klass, FALSE); - g_return_val_if_fail (klass->ip6_route_exists, FALSE); - - return klass->ip6_route_exists (self, ifindex, network, plen, metric); + return klass->ip6_route_get (self, ifindex, network, plen, metric); } /******************************************************************/ diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 1b5bfb1575..16eb351fa1 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -518,8 +518,8 @@ typedef struct { guint32 lifetime, guint32 preferred_lft, guint flags); gboolean (*ip4_address_delete) (NMPlatform *, int ifindex, in_addr_t address, int plen, in_addr_t peer_address); gboolean (*ip6_address_delete) (NMPlatform *, int ifindex, struct in6_addr address, int plen); - gboolean (*ip4_address_exists) (NMPlatform *, int ifindex, in_addr_t address, int plen); - gboolean (*ip6_address_exists) (NMPlatform *, int ifindex, struct in6_addr address, int plen); + const NMPlatformIP4Address *(*ip4_address_get) (NMPlatform *, int ifindex, in_addr_t address, int plen); + const NMPlatformIP6Address *(*ip6_address_get) (NMPlatform *, int ifindex, struct in6_addr address, int plen); GArray * (*ip4_route_get_all) (NMPlatform *, int ifindex, NMPlatformGetRouteFlags flags); GArray * (*ip6_route_get_all) (NMPlatform *, int ifindex, NMPlatformGetRouteFlags flags); @@ -531,8 +531,8 @@ typedef struct { guint32 metric, guint32 mss); gboolean (*ip4_route_delete) (NMPlatform *, int ifindex, in_addr_t network, int plen, guint32 metric); gboolean (*ip6_route_delete) (NMPlatform *, int ifindex, struct in6_addr network, int plen, guint32 metric); - gboolean (*ip4_route_exists) (NMPlatform *, int ifindex, in_addr_t network, int plen, guint32 metric); - gboolean (*ip6_route_exists) (NMPlatform *, int ifindex, struct in6_addr network, int plen, guint32 metric); + const NMPlatformIP4Route *(*ip4_route_get) (NMPlatform *, int ifindex, in_addr_t network, int plen, guint32 metric); + const NMPlatformIP6Route *(*ip6_route_get) (NMPlatform *, int ifindex, struct in6_addr network, int plen, guint32 metric); gboolean (*check_support_kernel_extended_ifa_flags) (NMPlatform *); gboolean (*check_support_user_ipv6ll) (NMPlatform *); @@ -692,6 +692,8 @@ guint32 nm_platform_mesh_get_channel (NMPlatform *self, int ifindex); gboolean nm_platform_mesh_set_channel (NMPlatform *self, int ifindex, guint32 channel); gboolean nm_platform_mesh_set_ssid (NMPlatform *self, int ifindex, const guint8 *ssid, gsize len); +const NMPlatformIP4Address *nm_platform_ip4_address_get (NMPlatform *self, int ifindex, in_addr_t address, int plen); +const NMPlatformIP6Address *nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr address, int plen); GArray *nm_platform_ip4_address_get_all (NMPlatform *self, int ifindex); GArray *nm_platform_ip6_address_get_all (NMPlatform *self, int ifindex); gboolean nm_platform_ip4_address_add (NMPlatform *self, int ifindex, @@ -703,12 +705,12 @@ gboolean nm_platform_ip6_address_add (NMPlatform *self, int ifindex, guint32 lifetime, guint32 preferred_lft, guint flags); gboolean nm_platform_ip4_address_delete (NMPlatform *self, int ifindex, in_addr_t address, int plen, in_addr_t peer_address); gboolean nm_platform_ip6_address_delete (NMPlatform *self, int ifindex, struct in6_addr address, int plen); -gboolean nm_platform_ip4_address_exists (NMPlatform *self, int ifindex, in_addr_t address, int plen); -gboolean nm_platform_ip6_address_exists (NMPlatform *self, int ifindex, struct in6_addr address, int plen); gboolean nm_platform_ip4_address_sync (NMPlatform *self, int ifindex, const GArray *known_addresses, GPtrArray **out_added_addresses); gboolean nm_platform_ip6_address_sync (NMPlatform *self, int ifindex, const GArray *known_addresses, gboolean keep_link_local); gboolean nm_platform_address_flush (NMPlatform *self, int ifindex); +const NMPlatformIP4Route *nm_platform_ip4_route_get (NMPlatform *self, int ifindex, in_addr_t network, int plen, guint32 metric); +const NMPlatformIP6Route *nm_platform_ip6_route_get (NMPlatform *self, int ifindex, struct in6_addr network, int plen, guint32 metric); GArray *nm_platform_ip4_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRouteFlags flags); GArray *nm_platform_ip6_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRouteFlags flags); gboolean nm_platform_ip4_route_add (NMPlatform *self, int ifindex, NMIPConfigSource source, @@ -719,8 +721,6 @@ gboolean nm_platform_ip6_route_add (NMPlatform *self, int ifindex, NMIPConfigSou guint32 metric, guint32 mss); gboolean nm_platform_ip4_route_delete (NMPlatform *self, int ifindex, in_addr_t network, int plen, guint32 metric); gboolean nm_platform_ip6_route_delete (NMPlatform *self, int ifindex, struct in6_addr network, int plen, guint32 metric); -gboolean nm_platform_ip4_route_exists (NMPlatform *self, int ifindex, in_addr_t network, int plen, guint32 metric); -gboolean nm_platform_ip6_route_exists (NMPlatform *self, int ifindex, struct in6_addr network, int plen, guint32 metric); const char *nm_platform_link_to_string (const NMPlatformLink *link); const char *nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address); diff --git a/src/platform/tests/platform.c b/src/platform/tests/platform.c index 3e43ca57bd..ebf162a98a 100644 --- a/src/platform/tests/platform.c +++ b/src/platform/tests/platform.c @@ -615,7 +615,7 @@ do_ip6_address_add (char **argv) v##_t address; \ int plen; \ if (ifindex && parse_##v##_address (*argv++, &address, &plen)) { \ - gboolean value = nm_platform_##v##_address_##cmdname (NM_PLATFORM_GET, ifindex, address, plen, ##__VA_ARGS__); \ + gboolean value = !!nm_platform_##v##_address_##cmdname (NM_PLATFORM_GET, ifindex, address, plen, ##__VA_ARGS__); \ if (print) { \ print_boolean (value); \ return TRUE; \ @@ -628,7 +628,7 @@ do_ip6_address_add (char **argv) #define ADDR_CMD_PRINT(cmdname) ADDR_CMD_FULL (ip4, cmdname, TRUE) ADDR_CMD_FULL (ip6, cmdname, TRUE) ADDR_CMD (delete) -ADDR_CMD_PRINT (exists) +ADDR_CMD_PRINT (get) static gboolean do_ip4_route_get_all (char **argv) @@ -738,7 +738,7 @@ do_ip6_route_delete (char **argv) } static gboolean -do_ip4_route_exists (char **argv) +do_ip4_route_get (char **argv) { int ifindex = parse_ifindex (*argv++); in_addr_t network; @@ -747,12 +747,12 @@ do_ip4_route_exists (char **argv) parse_ip4_address (*argv++, &network, &plen); metric = strtol (*argv++, NULL, 10); - print_boolean (nm_platform_ip4_route_exists (NM_PLATFORM_GET, ifindex, network, plen, metric)); + print_boolean (!!nm_platform_ip4_route_get (NM_PLATFORM_GET, ifindex, network, plen, metric)); return TRUE; } static gboolean -do_ip6_route_exists (char **argv) +do_ip6_route_get (char **argv) { int ifindex = parse_ifindex (*argv++); struct in6_addr network; @@ -761,7 +761,7 @@ do_ip6_route_exists (char **argv) parse_ip6_address (*argv++, &network, &plen); metric = strtol (*argv++, NULL, 10); - print_boolean (nm_platform_ip6_route_exists (NM_PLATFORM_GET, ifindex, network, plen, metric)); + print_boolean (!!nm_platform_ip6_route_get (NM_PLATFORM_GET, ifindex, network, plen, metric)); return TRUE; } @@ -838,9 +838,9 @@ static const command_t commands[] = { "
/" }, { "ip6-address-delete", "delete IPv6 address", do_ip6_address_delete, 2, "
/" }, - { "ip4-address-exists", "check for existence of IPv4 address", do_ip4_address_exists, 2, + { "ip4-address-exists", "check for existence of IPv4 address", do_ip4_address_get, 2, "
/" }, - { "ip6-address-exists", "check for existence of IPv6 address", do_ip6_address_exists, 2, + { "ip6-address-exists", "check for existence of IPv6 address", do_ip6_address_get, 2, "
/" }, { "ip4-route-get-all", "print all IPv4 routes", do_ip4_route_get_all, 1, "" }, { "ip6-route-get-all", "print all IPv6 routes", do_ip6_route_get_all, 1, "" }, @@ -852,9 +852,9 @@ static const command_t commands[] = { " / " }, { "ip6-route-delete", "delete IPv6 route", do_ip6_route_delete, 3, " / " }, - { "ip4-route-exists", "check for existence of IPv4 route", do_ip4_route_exists, 3, + { "ip4-route-exists", "check for existence of IPv4 route", do_ip4_route_get, 3, " / " }, - { "ip6-route-exists", "check for existence of IPv6 route", do_ip6_route_exists, 3, + { "ip6-route-exists", "check for existence of IPv6 route", do_ip6_route_get, 3, " / " }, { NULL, NULL, NULL, 0, NULL }, }; diff --git a/src/platform/tests/test-address.c b/src/platform/tests/test-address.c index bcc38b399b..d6f346b376 100644 --- a/src/platform/tests/test-address.c +++ b/src/platform/tests/test-address.c @@ -64,9 +64,9 @@ test_ip4_address (void) inet_pton (AF_INET, IP4_ADDRESS, &addr); /* Add address */ - g_assert (!nm_platform_ip4_address_exists (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN)); + g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN)); g_assert (nm_platform_ip4_address_add (NM_PLATFORM_GET, ifindex, addr, 0, IP4_PLEN, lifetime, preferred, NULL)); - g_assert (nm_platform_ip4_address_exists (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN)); + g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN)); accept_signal (address_added); /* Add address again (aka update) */ @@ -85,7 +85,7 @@ test_ip4_address (void) /* Remove address */ g_assert (nm_platform_ip4_address_delete (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, 0)); - g_assert (!nm_platform_ip4_address_exists (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN)); + g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN)); accept_signal (address_removed); /* Remove address again */ @@ -113,9 +113,9 @@ test_ip6_address (void) inet_pton (AF_INET6, IP6_ADDRESS, &addr); /* Add address */ - g_assert (!nm_platform_ip6_address_exists (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); + g_assert (!nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); g_assert (nm_platform_ip6_address_add (NM_PLATFORM_GET, ifindex, addr, in6addr_any, IP6_PLEN, lifetime, preferred, flags)); - g_assert (nm_platform_ip6_address_exists (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); + g_assert (nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); accept_signal (address_added); /* Add address again (aka update) */ @@ -134,7 +134,7 @@ test_ip6_address (void) /* Remove address */ g_assert (nm_platform_ip6_address_delete (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); - g_assert (!nm_platform_ip6_address_exists (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); + g_assert (!nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); accept_signal (address_removed); /* Remove address again */ @@ -167,20 +167,20 @@ test_ip4_address_external (void) run_command ("ip address add %s/%d dev %s valid_lft %d preferred_lft %d", IP4_ADDRESS, IP4_PLEN, DEVICE_NAME, lifetime, preferred); wait_signal (address_added); - g_assert (nm_platform_ip4_address_exists (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN)); + g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN)); run_command ("ip address delete %s/%d dev %s", IP4_ADDRESS, IP4_PLEN, DEVICE_NAME); wait_signal (address_removed); - g_assert (!nm_platform_ip4_address_exists (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN)); + g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN)); /* Add/delete conflict */ run_command ("ip address add %s/%d dev %s valid_lft %d preferred_lft %d", IP4_ADDRESS, IP4_PLEN, DEVICE_NAME, lifetime, preferred); g_assert (nm_platform_ip4_address_add (NM_PLATFORM_GET, ifindex, addr, 0, IP4_PLEN, lifetime, preferred, NULL)); - g_assert (nm_platform_ip4_address_exists (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN)); + g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN)); accept_signal (address_added); /*run_command ("ip address delete %s/%d dev %s", IP4_ADDRESS, IP4_PLEN, DEVICE_NAME); g_assert (nm_platform_ip4_address_delete (ifindex, addr, IP4_PLEN, 0)); - g_assert (!nm_platform_ip4_address_exists (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN)); + g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN)); accept_signal (address_removed);*/ free_signal (address_added); @@ -204,20 +204,20 @@ test_ip6_address_external (void) run_command ("ip address add %s/%d dev %s valid_lft %d preferred_lft %d", IP6_ADDRESS, IP6_PLEN, DEVICE_NAME, lifetime, preferred); wait_signal (address_added); - g_assert (nm_platform_ip6_address_exists (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); + g_assert (nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); run_command ("ip address delete %s/%d dev %s", IP6_ADDRESS, IP6_PLEN, DEVICE_NAME); wait_signal (address_removed); - g_assert (!nm_platform_ip6_address_exists (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); + g_assert (!nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); /* Add/delete conflict */ run_command ("ip address add %s/%d dev %s valid_lft %d preferred_lft %d", IP6_ADDRESS, IP6_PLEN, DEVICE_NAME, lifetime, preferred); g_assert (nm_platform_ip6_address_add (NM_PLATFORM_GET, ifindex, addr, in6addr_any, IP6_PLEN, lifetime, preferred, flags)); - g_assert (nm_platform_ip6_address_exists (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); + g_assert (nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); accept_signal (address_added); /*run_command ("ip address delete %s/%d dev %s", IP6_ADDRESS, IP6_PLEN, DEVICE_NAME); g_assert (nm_platform_ip6_address_delete (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); - g_assert (!nm_platform_ip6_address_exists (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); + g_assert (!nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); wait_signal (address_removed);*/ free_signal (address_added); diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c index 6c754fecec..b0eae63b77 100644 --- a/src/platform/tests/test-common.c +++ b/src/platform/tests/test-common.c @@ -244,7 +244,7 @@ _assert_ip4_route_exists (const char *file, guint line, const char *func, gboole ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, ifname); g_assert (ifindex > 0); - if (!nm_platform_ip4_route_exists (NM_PLATFORM_GET, ifindex, network, plen, metric) != !exists) { + if (!nm_platform_ip4_route_get (NM_PLATFORM_GET, ifindex, network, plen, metric) != !exists) { g_error ("[%s:%u] %s(): The ip4 route %s/%d metric %u %s, but platform thinks %s", file, line, func, nm_utils_inet4_ntop (network, NULL), plen, metric, diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c index 79d6fce75e..cf322dec6e 100644 --- a/src/platform/tests/test-route.c +++ b/src/platform/tests/test-route.c @@ -222,9 +222,9 @@ test_ip6_route (void) accept_signal (route_added); /* Add route */ - g_assert (!nm_platform_ip6_route_exists (NM_PLATFORM_GET, ifindex, network, plen, metric)); + g_assert (!nm_platform_ip6_route_get (NM_PLATFORM_GET, ifindex, network, plen, metric)); g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, metric, mss)); - g_assert (nm_platform_ip6_route_exists (NM_PLATFORM_GET, ifindex, network, plen, metric)); + g_assert (nm_platform_ip6_route_get (NM_PLATFORM_GET, ifindex, network, plen, metric)); accept_signal (route_added); /* Add route again */ @@ -232,9 +232,9 @@ test_ip6_route (void) accept_signals (route_changed, 0, 1); /* Add default route */ - g_assert (!nm_platform_ip6_route_exists (NM_PLATFORM_GET, ifindex, in6addr_any, 0, metric)); + g_assert (!nm_platform_ip6_route_get (NM_PLATFORM_GET, ifindex, in6addr_any, 0, metric)); g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, in6addr_any, 0, gateway, metric, mss)); - g_assert (nm_platform_ip6_route_exists (NM_PLATFORM_GET, ifindex, in6addr_any, 0, metric)); + g_assert (nm_platform_ip6_route_get (NM_PLATFORM_GET, ifindex, in6addr_any, 0, metric)); accept_signal (route_added); /* Add default route again */ @@ -271,7 +271,7 @@ test_ip6_route (void) /* Remove route */ g_assert (nm_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric)); - g_assert (!nm_platform_ip6_route_exists (NM_PLATFORM_GET, ifindex, network, plen, metric)); + g_assert (!nm_platform_ip6_route_get (NM_PLATFORM_GET, ifindex, network, plen, metric)); accept_signal (route_removed); /* Remove route again */ diff --git a/src/tests/test-route-manager.c b/src/tests/test-route-manager.c index 5325b83fae..9b66c2dd38 100644 --- a/src/tests/test-route-manager.c +++ b/src/tests/test-route-manager.c @@ -36,6 +36,8 @@ typedef struct { int ifindex0, ifindex1; } test_fixture; +/*****************************************************************************/ + static void setup_dev0_ip4 (int ifindex, guint mss_of_first_route, guint32 metric_of_second_route) { @@ -61,7 +63,7 @@ setup_dev0_ip4 (int ifindex, guint mss_of_first_route, guint32 metric_of_second_ route.mss = 0; g_array_append_val (routes, route); - nm_route_manager_ip4_route_sync (nm_route_manager_get (), ifindex, routes, TRUE); + nm_route_manager_ip4_route_sync (nm_route_manager_get (), ifindex, routes, TRUE, TRUE); g_array_free (routes, TRUE); } @@ -107,7 +109,7 @@ setup_dev1_ip4 (int ifindex) route.metric = 22; g_array_append_val (routes, route); - nm_route_manager_ip4_route_sync (nm_route_manager_get (), ifindex, routes, TRUE); + nm_route_manager_ip4_route_sync (nm_route_manager_get (), ifindex, routes, TRUE, TRUE); g_array_free (routes, TRUE); } @@ -134,7 +136,7 @@ update_dev0_ip4 (int ifindex) route.metric = 21; g_array_append_val (routes, route); - nm_route_manager_ip4_route_sync (nm_route_manager_get (), ifindex, routes, TRUE); + nm_route_manager_ip4_route_sync (nm_route_manager_get (), ifindex, routes, TRUE, TRUE); g_array_free (routes, TRUE); } @@ -409,7 +411,7 @@ setup_dev0_ip6 (int ifindex) 0); g_array_append_val (routes, *route); - nm_route_manager_ip6_route_sync (nm_route_manager_get (), ifindex, routes, TRUE); + nm_route_manager_ip6_route_sync (nm_route_manager_get (), ifindex, routes, TRUE, TRUE); g_array_free (routes, TRUE); } @@ -466,7 +468,7 @@ setup_dev1_ip6 (int ifindex) 0); g_array_append_val (routes, *route); - nm_route_manager_ip6_route_sync (nm_route_manager_get (), ifindex, routes, TRUE); + nm_route_manager_ip6_route_sync (nm_route_manager_get (), ifindex, routes, TRUE, TRUE); g_array_free (routes, TRUE); } @@ -513,7 +515,7 @@ update_dev0_ip6 (int ifindex) 0); g_array_append_val (routes, *route); - nm_route_manager_ip6_route_sync (nm_route_manager_get (), ifindex, routes, TRUE); + nm_route_manager_ip6_route_sync (nm_route_manager_get (), ifindex, routes, TRUE, TRUE); g_array_free (routes, TRUE); } @@ -779,6 +781,89 @@ test_ip6 (test_fixture *fixture, gconstpointer user_data) g_array_free (routes, TRUE); } +/*****************************************************************************/ + +static void +_assert_route_check (const NMPlatformVTableRoute *vtable, gboolean has, const NMPlatformIPXRoute *route) +{ + const NMPlatformIPXRoute *r; + + g_assert (route); + + if (vtable->is_ip4) + r = (const NMPlatformIPXRoute *) nm_platform_ip4_route_get (NM_PLATFORM_GET, route->rx.ifindex, route->r4.network, route->rx.plen, route->rx.metric); + else + r = (const NMPlatformIPXRoute *) nm_platform_ip6_route_get (NM_PLATFORM_GET, route->rx.ifindex, route->r6.network, route->rx.plen, route->rx.metric); + + if (!has) { + g_assert (!r); + } else { + if (!r || vtable->route_cmp (route, r) != 0) + g_error ("Invalid route. Expect %s, has %s", + nmtst_static_1024_01 (vtable->route_to_string (route)), + nmtst_static_1024_02 (vtable->route_to_string (r))); + g_assert (r); + } +} + +static void +test_ip4_full_sync (test_fixture *fixture, gconstpointer user_data) +{ + const NMPlatformVTableRoute *vtable = &nm_platform_vtable_route_v4; + gs_unref_array GArray *routes = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP4Route)); + NMPlatformIP4Route r01, r02, r03; + + nm_log_dbg (LOGD_CORE, "TEST start test_ip4_full_sync(): start"); + + r01 = *nmtst_platform_ip4_route_full ("12.3.4.0", 24, NULL, + fixture->ifindex0, NM_IP_CONFIG_SOURCE_USER, + 100, 0, RT_SCOPE_LINK, NULL); + r02 = *nmtst_platform_ip4_route_full ("13.4.5.6", 32, "12.3.4.1", + fixture->ifindex0, NM_IP_CONFIG_SOURCE_USER, + 100, 0, RT_SCOPE_UNIVERSE, NULL); + r03 = *nmtst_platform_ip4_route_full ("14.5.6.7", 32, "12.3.4.1", + fixture->ifindex0, NM_IP_CONFIG_SOURCE_USER, + 110, 0, RT_SCOPE_UNIVERSE, NULL); + g_array_set_size (routes, 2); + g_array_index (routes, NMPlatformIP4Route, 0) = r01; + g_array_index (routes, NMPlatformIP4Route, 1) = r02; + nm_route_manager_ip4_route_sync (nm_route_manager_get (), fixture->ifindex0, routes, TRUE, TRUE); + + _assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r01); + _assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r02); + _assert_route_check (vtable, FALSE, (const NMPlatformIPXRoute *) &r03); + + vtable->route_add (NM_PLATFORM_GET, 0, (const NMPlatformIPXRoute *) &r03, -1); + + _assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r01); + _assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r02); + _assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r03); + + nm_route_manager_ip4_route_sync (nm_route_manager_get (), fixture->ifindex0, routes, TRUE, FALSE); + + _assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r01); + _assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r02); + _assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r03); + + g_array_set_size (routes, 1); + + nm_route_manager_ip4_route_sync (nm_route_manager_get (), fixture->ifindex0, routes, TRUE, FALSE); + + _assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r01); + _assert_route_check (vtable, FALSE, (const NMPlatformIPXRoute *) &r02); + _assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r03); + + nm_route_manager_ip4_route_sync (nm_route_manager_get (), fixture->ifindex0, routes, TRUE, TRUE); + + _assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r01); + _assert_route_check (vtable, FALSE, (const NMPlatformIPXRoute *) &r02); + _assert_route_check (vtable, FALSE, (const NMPlatformIPXRoute *) &r03); + + nm_log_dbg (LOGD_CORE, "TEST test_ip4_full_sync(): done"); +} + +/*****************************************************************************/ + static void fixture_setup (test_fixture *fixture, gconstpointer user_data) { @@ -816,6 +901,8 @@ fixture_teardown (test_fixture *fixture, gconstpointer user_data) nm_platform_link_delete (NM_PLATFORM_GET, fixture->ifindex1); } +/*****************************************************************************/ + void init_tests (int *argc, char ***argv) { @@ -827,4 +914,6 @@ setup_tests (void) { g_test_add ("/route-manager/ip4", test_fixture, NULL, fixture_setup, test_ip4, fixture_teardown); g_test_add ("/route-manager/ip6", test_fixture, NULL, fixture_setup, test_ip6, fixture_teardown); + + g_test_add ("/route-manager/ip4-full-sync", test_fixture, NULL, fixture_setup, test_ip4_full_sync, fixture_teardown); } diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c index fffc5cabee..8749e3573b 100644 --- a/src/vpn-manager/nm-vpn-connection.c +++ b/src/vpn-manager/nm-vpn-connection.c @@ -961,12 +961,15 @@ nm_vpn_connection_apply_config (NMVpnConnection *connection) if (priv->ip4_config) { if (!nm_ip4_config_commit (priv->ip4_config, priv->ip_ifindex, + TRUE, nm_vpn_connection_get_ip4_route_metric (connection))) return FALSE; } if (priv->ip6_config) { - if (!nm_ip6_config_commit (priv->ip6_config, priv->ip_ifindex)) + if (!nm_ip6_config_commit (priv->ip6_config, + priv->ip_ifindex, + TRUE)) return FALSE; } }