diff options
author | Lubomir Rintel <lkundrak@v3.sk> | 2017-03-22 12:21:56 +0100 |
---|---|---|
committer | Lubomir Rintel <lkundrak@v3.sk> | 2017-03-22 12:21:56 +0100 |
commit | edaa7d064e5efef2abcb08d44355a2a8f5a09e87 (patch) | |
tree | 0355e419953688659c2a5fe6d352e2a856f5f49b | |
parent | 8d4570d28d1825d52de936b21d785c75b602394a (diff) | |
parent | cae3cef60fe6b37929e69d103663882274ad46bc (diff) | |
download | NetworkManager-edaa7d064e5efef2abcb08d44355a2a8f5a09e87.tar.gz |
merge: branch 'lr/rp-filter'
https://bugzilla.gnome.org/show_bug.cgi?id=780155
-rw-r--r-- | src/devices/nm-device.c | 81 | ||||
-rw-r--r-- | src/nm-route-manager.c | 43 | ||||
-rw-r--r-- | src/nm-route-manager.h | 3 |
3 files changed, 127 insertions, 0 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index de9bf78bc7..017d55a3a5 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -339,6 +339,8 @@ typedef struct _NMDevicePrivate { NMPlatformIP4Route v4; NMPlatformIP6Route v6; } default_route; + bool v4_has_shadowed_routes; + const char *ip4_rp_filter; /* DHCPv4 tracking */ struct { @@ -704,6 +706,38 @@ init_ip6_config_dns_priority (NMDevice *self, NMIP6Config *config) /*****************************************************************************/ +static gboolean +nm_device_ipv4_sysctl_set (NMDevice *self, const char *property, const char *value) +{ + NMPlatform *platform = NM_PLATFORM_GET; + gs_free char *value_to_free = NULL; + const char *value_to_set; + + if (value) { + value_to_set = value; + } else { + /* Set to a default value when we've got a NULL @value. */ + value_to_free = nm_platform_sysctl_get (platform, + NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_ip4_property_path ("default", property))); + value_to_set = value_to_free; + } + + return nm_platform_sysctl_set (platform, + NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_ip4_property_path (nm_device_get_ip_iface (self), property)), + value_to_set); +} + +static guint32 +nm_device_ipv4_sysctl_get_uint32 (NMDevice *self, const char *property, guint32 fallback) +{ + return nm_platform_sysctl_get_int_checked (NM_PLATFORM_GET, + NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_ip4_property_path (nm_device_get_ip_iface (self), property)), + 10, + 0, + G_MAXUINT32, + fallback); +} + gboolean nm_device_ipv6_sysctl_set (NMDevice *self, const char *property, const char *value) { @@ -2362,6 +2396,45 @@ link_changed_cb (NMPlatform *platform, } static void +ip4_rp_filter_update (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + const char *ip4_rp_filter; + + if ( priv->v4_has_shadowed_routes + || priv->default_route.v4_has) { + if (nm_device_ipv4_sysctl_get_uint32 (self, "rp_filter", 0) != 1) { + /* Don't touch the rp_filter if it's not strict. */ + return; + } + /* Loose rp_filter */ + ip4_rp_filter = "2"; + } else { + /* Default rp_filter */ + ip4_rp_filter = NULL; + } + + if (ip4_rp_filter != priv->ip4_rp_filter) { + nm_device_ipv4_sysctl_set (self, "rp_filter", ip4_rp_filter); + priv->ip4_rp_filter = ip4_rp_filter; + } +} + +static void +ip4_routes_changed_changed_cb (NMRouteManager *route_manager, NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + int ifindex = nm_device_get_ip_ifindex (self); + + if (nm_device_sys_iface_state_is_external_or_assume (self)) + return; + + priv->v4_has_shadowed_routes = nm_route_manager_ip4_routes_shadowed (route_manager, + ifindex); + ip4_rp_filter_update (self); +} + +static void link_changed (NMDevice *self, const NMPlatformLink *pllink) { /* stub implementation of virtual function to allow subclasses to chain up. */ @@ -9410,6 +9483,8 @@ nm_device_set_ip4_config (NMDevice *self, } nm_default_route_manager_ip4_update_default_route (nm_default_route_manager_get (), self); + if (!nm_device_sys_iface_state_is_external_or_assume (self)) + ip4_rp_filter_update (self); if (has_changes) { NMSettingsConnection *settings_connection; @@ -13343,6 +13418,9 @@ constructed (GObject *object) g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, G_CALLBACK (device_ipx_changed), self); g_signal_connect (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, G_CALLBACK (link_changed_cb), self); + g_signal_connect (nm_route_manager_get (), NM_ROUTE_MANAGER_IP4_ROUTES_CHANGED, + G_CALLBACK (ip4_routes_changed_changed_cb), self); + priv->settings = g_object_ref (NM_SETTINGS_GET); g_assert (priv->settings); @@ -13381,6 +13459,9 @@ dispose (GObject *object) g_signal_handlers_disconnect_by_func (platform, G_CALLBACK (device_ipx_changed), self); g_signal_handlers_disconnect_by_func (platform, G_CALLBACK (link_changed_cb), self); + g_signal_handlers_disconnect_by_func (nm_route_manager_get (), + G_CALLBACK (ip4_routes_changed_changed_cb), self); + g_slist_free_full (priv->arping.dad_list, (GDestroyNotify) nm_arping_manager_destroy); priv->arping.dad_list = NULL; diff --git a/src/nm-route-manager.c b/src/nm-route-manager.c index a8778e2a7d..0a8f1f635e 100644 --- a/src/nm-route-manager.c +++ b/src/nm-route-manager.c @@ -63,6 +63,12 @@ typedef struct { /*****************************************************************************/ +enum { + IP4_ROUTES_CHANGED, + LAST_SIGNAL, +}; +static guint signals[LAST_SIGNAL] = { 0 }; + NM_GOBJECT_PROPERTIES_DEFINE_BASE ( PROP_PLATFORM, ); @@ -904,6 +910,9 @@ next: } } + if (vtable->vt->is_ip4 && ipx_routes_changed) + g_signal_emit (self, signals[IP4_ROUTES_CHANGED], 0); + g_free (known_routes_idx); g_free (plat_routes_idx); g_array_unref (plat_routes); @@ -967,6 +976,33 @@ nm_route_manager_route_flush (NMRouteManager *self, int ifindex) return success; } +/** + * nm_route_manager_ip4_routes_shadowed: + * @ifindex: Interface index + * + * Returns: %TRUE if some other link has a route to the same destination + * with a lower metric. + */ +gboolean +nm_route_manager_ip4_routes_shadowed (NMRouteManager *self, int ifindex) +{ + NMRouteManagerPrivate *priv = NM_ROUTE_MANAGER_GET_PRIVATE (self); + RouteIndex *index = priv->ip4_routes.index; + const NMPlatformIP4Route *route; + guint i; + + for (i = 1; i < index->len; i++) { + route = (const NMPlatformIP4Route *) index->entries[i]; + + if (route->ifindex != ifindex) + continue; + if (_v4_route_dest_cmp (route, (const NMPlatformIP4Route *) index->entries[i - 1]) == 0) + return TRUE; + } + + return FALSE; +} + /*****************************************************************************/ static gboolean @@ -1258,4 +1294,11 @@ nm_route_manager_class_init (NMRouteManagerClass *klass) G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + signals[IP4_ROUTES_CHANGED] = + g_signal_new (NM_ROUTE_MANAGER_IP4_ROUTES_CHANGED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 0); } diff --git a/src/nm-route-manager.h b/src/nm-route-manager.h index d12f025603..328fa8cba6 100644 --- a/src/nm-route-manager.h +++ b/src/nm-route-manager.h @@ -30,6 +30,8 @@ #define NM_ROUTE_MANAGER_PLATFORM "platform" +#define NM_ROUTE_MANAGER_IP4_ROUTES_CHANGED "ip4-routes-changed" + typedef struct _NMRouteManagerClass NMRouteManagerClass; GType nm_route_manager_get_type (void); @@ -38,6 +40,7 @@ gboolean nm_route_manager_ip4_route_sync (NMRouteManager *self, int ifindex, con 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); +gboolean nm_route_manager_ip4_routes_shadowed (NMRouteManager *self, int ifindex); void nm_route_manager_ip4_route_register_device_route_purge_list (NMRouteManager *self, GArray *device_route_purge_list); NMRouteManager *nm_route_manager_get (void); |