chiark / gitweb /
networkd: propagate IPFoward= per-interface setting also to /proc/sys/net/ipv4/ip_forward
authorLennart Poettering <lennart@poettering.net>
Tue, 13 Jan 2015 19:50:46 +0000 (20:50 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 13 Jan 2015 19:55:13 +0000 (20:55 +0100)
We need to turn on /proc/sys/net/ipv4/ip_forward before the
per-interface forwarding setting is useful, hence let's propagate the
per-interface setting once to the system-wide setting.

Due to the unclear ownership rules of that flag, and the fact that
turning it on also has effects on other sysctl flags we try to minimize
changes to the flag, and only turn it on once. There's no logic to
turning it off again, but this should be fairly unproblematic as the
per-interface setting defaults to off anyway.

src/network/networkd-link.c

index e4800a1..bc363f9 100644 (file)
@@ -1237,12 +1237,38 @@ static int link_enter_join_netdev(Link *link) {
 
 static int link_set_ipv4_forward(Link *link) {
         const char *p = NULL;
+        bool b;
         int r;
 
+        b = link_ipv4_forward_enabled(link);
+
         p = strappenda("/proc/sys/net/ipv4/conf/", link->ifname, "/forwarding");
-        r = write_string_file_no_create(p, one_zero(link_ipv4_forward_enabled(link)));
+        r = write_string_file_no_create(p, one_zero(b));
         if (r < 0)
-                log_link_warning_errno(link, r, "Cannot configure IPv4 forwarding for interface: %m");
+                log_link_warning_errno(link, r, "Cannot configure IPv4 forwarding for interface %s: %m", link->ifname);
+
+        if (b) {
+                _cleanup_free_ char *buf = NULL;
+
+                /* If IP forwarding is turned on for this interface,
+                 * then propagate this to the global setting. Given
+                 * that turning this on has side-effects on other
+                 * fields, we'll try to avoid doing this unless
+                 * necessary, hence check the previous value
+                 * first. Note that we never turn this option off
+                 * again, since all interfaces we manage do not do
+                 * forwarding anyway by default, and ownership rules
+                 * of this control are so unclear. */
+
+                r = read_one_line_file("/proc/sys/net/ipv4/ip_forward", &buf);
+                if (r < 0)
+                        log_link_warning_errno(link, r, "Cannot read /proc/sys/net/ipv4/ip_forward: %m");
+                else if (!streq(buf, "1")) {
+                        r = write_string_file_no_create("/proc/sys/net/ipv4/ip_forward", "1");
+                        if (r < 0)
+                                log_link_warning_errno(link, r, "Cannot write /proc/sys/net/ipv4/ip_forward: %m");
+                }
+        }
 
         return 0;
 }