summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/network/networkd-link.c52
-rw-r--r--src/network/networkd-util.c10
2 files changed, 39 insertions, 23 deletions
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 4a84e49699..c37532bb73 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -111,16 +111,26 @@ static bool link_ipv4_forward_enabled(Link *link) {
if (!link->network)
return false;
+ if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID)
+ return false;
+
return link->network->ip_forward & ADDRESS_FAMILY_IPV4;
}
static bool link_ipv6_forward_enabled(Link *link) {
+
+ if (!socket_ipv6_is_supported())
+ return false;
+
if (link->flags & IFF_LOOPBACK)
return false;
if (!link->network)
return false;
+ if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID)
+ return false;
+
return link->network->ip_forward & ADDRESS_FAMILY_IPV6;
}
@@ -1851,45 +1861,43 @@ static int link_enter_join_netdev(Link *link) {
}
static int link_set_ipv4_forward(Link *link) {
- const char *p = NULL, *v;
int r;
- if (link->flags & IFF_LOOPBACK)
- return 0;
-
- if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID)
+ if (!link_ipv4_forward_enabled(link))
return 0;
- p = strjoina("/proc/sys/net/ipv4/conf/", link->ifname, "/forwarding");
- v = one_zero(link_ipv4_forward_enabled(link));
+ /* We propagate the forwarding flag from one interface to the
+ * global setting one way. This means: as long as at least one
+ * interface was configured at any time that had IP forwarding
+ * enabled the setting will stay on for good. We do this
+ * primarily to keep IPv4 and IPv6 packet forwarding behaviour
+ * somewhat in sync (see below). */
- r = write_string_file(p, v, WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+ r = write_string_file("/proc/sys/net/ipv4/ip_forward", "1", WRITE_STRING_FILE_VERIFY_ON_FAILURE);
if (r < 0)
- log_link_warning_errno(link, r, "Cannot configure IPv4 forwarding for interface %s: %m", link->ifname);
+ log_link_warning_errno(link, r, "Cannot turn on IPv4 packet forwarding, ignoring: %m");
return 0;
}
static int link_set_ipv6_forward(Link *link) {
- const char *p = NULL, *v = NULL;
int r;
- /* Make this a NOP if IPv6 is not available */
- if (!socket_ipv6_is_supported())
- return 0;
-
- if (link->flags & IFF_LOOPBACK)
- return 0;
-
- if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID)
+ if (!link_ipv6_forward_enabled(link))
return 0;
- p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/forwarding");
- v = one_zero(link_ipv6_forward_enabled(link));
+ /* On Linux, the IPv6 stack does not not know a per-interface
+ * packet forwarding setting: either packet forwarding is on
+ * for all, or off for all. We hence don't bother with a
+ * per-interface setting, but simply propagate the interface
+ * flag, if it is set, to the global flag, one-way. Note that
+ * while IPv4 would allow a per-interface flag, we expose the
+ * same behaviour there and also propagate the setting from
+ * one to all, to keep things simple (see above). */
- r = write_string_file(p, v, WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+ r = write_string_file("/proc/sys/net/ipv6/conf/all/forwarding", "1", WRITE_STRING_FILE_VERIFY_ON_FAILURE);
if (r < 0)
- log_link_warning_errno(link, r, "Cannot configure IPv6 forwarding for interface: %m");
+ log_link_warning_errno(link, r, "Cannot configure IPv6 packet forwarding, ignoring: %m");
return 0;
}
diff --git a/src/network/networkd-util.c b/src/network/networkd-util.c
index df091393f6..2545621a93 100644
--- a/src/network/networkd-util.c
+++ b/src/network/networkd-util.c
@@ -79,10 +79,18 @@ int config_parse_address_family_boolean_with_kernel(
assert(rvalue);
assert(data);
+ /* This function is mostly obsolete now. It simply redirects
+ * "kernel" to "no". In older networkd versions we used to
+ * distuingish IPForward=off from IPForward=kernel, where the
+ * former would explicitly turn off forwarding while the
+ * latter would simply not touch the setting. But that logic
+ * is gone, hence silently accept the old setting, but turn it
+ * to "no". */
+
s = address_family_boolean_from_string(rvalue);
if (s < 0) {
if (streq(rvalue, "kernel"))
- s = _ADDRESS_FAMILY_BOOLEAN_INVALID;
+ s = ADDRESS_FAMILY_NO;
else {
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IPForward= option, ignoring: %s", rvalue);
return 0;