summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2019-02-08 17:28:58 +0100
committerThomas Haller <thaller@redhat.com>2019-02-08 17:28:58 +0100
commitaacb3c4f5b59e1728f01ede6cddc0d9267611e86 (patch)
tree2f64cca015bf679214683182d89238e916d51939
parentbba33ba20c6d3bdbbafe6184903e0437f11c9c28 (diff)
parent983b430075f1da5ca47ee7bdc5863eb0218a9bd1 (diff)
downloadNetworkManager-aacb3c4f5b59e1728f01ede6cddc0d9267611e86.tar.gz
connectivity: merge branch 'th/connectivity-rp-filter'
-rw-r--r--contrib/fedora/rpm/20-connectivity-fedora.conf5
-rw-r--r--contrib/fedora/rpm/20-connectivity-redhat.conf5
-rw-r--r--man/NetworkManager.conf.xml8
-rw-r--r--src/devices/nm-device.c36
4 files changed, 54 insertions, 0 deletions
diff --git a/contrib/fedora/rpm/20-connectivity-fedora.conf b/contrib/fedora/rpm/20-connectivity-fedora.conf
index 945bea6f29..4c398c3ec9 100644
--- a/contrib/fedora/rpm/20-connectivity-fedora.conf
+++ b/contrib/fedora/rpm/20-connectivity-fedora.conf
@@ -1,3 +1,8 @@
+# Enable connectivity checking for NetworkManager.
+# See `man NetworkManager.conf`.
+#
+# Note that connectivity checking works badly with rp_filter set to
+# strict. Check "/proc/sys/net/ipv4/conf/*/rp_filter".
[connectivity]
uri=http://fedoraproject.org/static/hotspot.txt
response=OK
diff --git a/contrib/fedora/rpm/20-connectivity-redhat.conf b/contrib/fedora/rpm/20-connectivity-redhat.conf
index e556fd6235..94783b3557 100644
--- a/contrib/fedora/rpm/20-connectivity-redhat.conf
+++ b/contrib/fedora/rpm/20-connectivity-redhat.conf
@@ -1,3 +1,8 @@
+# Enable connectivity checking for NetworkManager.
+# See `man NetworkManager.conf`.
+#
+# Note that connectivity checking works badly with rp_filter set to
+# strict. Check "/proc/sys/net/ipv4/conf/*/rp_filter".
[connectivity]
uri=http://static.redhat.com/test/rhel-networkmanager.txt
response=OK
diff --git a/man/NetworkManager.conf.xml b/man/NetworkManager.conf.xml
index 4d6fe12df7..b6577aed50 100644
--- a/man/NetworkManager.conf.xml
+++ b/man/NetworkManager.conf.xml
@@ -1056,10 +1056,12 @@ managed=1
<refsect1>
<title><literal>connectivity</literal> section</title>
+
<para>This section controls NetworkManager's optional connectivity
checking functionality. This allows NetworkManager to detect
whether or not the system can actually access the internet or
whether it is behind a captive portal.</para>
+
<para>Connectivity checking serves two purposes. For one, it exposes
a connectivity state on D-Bus, which other applications may use. For example,
Gnome's portal helper uses this as signal to show a captive portal login
@@ -1070,6 +1072,12 @@ managed=1
when being connected to WWAN and to a Wi-Fi network which is behind a captive
portal, WWAN still gets preferred until login.</para>
+ <para>Note that your distribution might set <literal>/proc/sys/net/ipv4/conf/*/rp_filter</literal> to
+ strict filtering. That works badly with per-device connectivity checking,
+ which uses SO_BINDDEVICE to send requests on all devices. A strict rp_filter
+ setting will reject any response and the connectivity check on all but the
+ best route will fail.</para>
+
<para>
<variablelist>
<varlistentry>
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index fcdc75d754..bff35ddd43 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -397,6 +397,8 @@ typedef struct _NMDevicePrivate {
bool ndisc_started:1;
bool device_link_changed_down:1;
+ bool concheck_rp_filter_checked:1;
+
/* Generic DHCP stuff */
char * dhcp_anycast_address;
@@ -3042,6 +3044,7 @@ concheck_start (NMDevice *self,
static guint64 seq_counter = 0;
NMDevicePrivate *priv;
NMDeviceConnectivityHandle *handle;
+ const char *ifname;
g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
@@ -3064,6 +3067,39 @@ concheck_start (NMDevice *self,
(long long unsigned) handle->seq,
is_periodic ? ", periodic-check" : "");
+ if ( addr_family == AF_INET
+ && !priv->concheck_rp_filter_checked) {
+
+ if ((ifname = nm_device_get_ip_iface_from_platform (self))) {
+ int val, val_all;
+
+ val = nm_platform_sysctl_ip_conf_get_int_checked (nm_device_get_platform (self),
+ AF_INET,
+ ifname,
+ "rp_filter",
+ 10, 0, 2, 3);
+ if (val < 2) {
+ val_all = nm_platform_sysctl_ip_conf_get_int_checked (nm_device_get_platform (self),
+ AF_INET,
+ "all",
+ "rp_filter",
+ 10, 0, 2, val);
+ if (val_all > val) {
+ val = val_all;
+ ifname = "all";
+ }
+ }
+
+ if (val == 1) {
+ _LOGW (LOGD_CONCHECK, "connectivity: \"/proc/sys/net/ipv4/conf/%s/rp_filter\" is set to \"1\". "
+ "This might break connectivity checking for IPv4 on this device", ifname);
+ }
+ }
+
+ /* we only check once per device. It's a warning after all. */
+ priv->concheck_rp_filter_checked = TRUE;
+ }
+
handle->c_handle = nm_connectivity_check_start (concheck_get_mgr (self),
handle->addr_family,
nm_device_get_ip_ifindex (self),