summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--man/systemd.network.xml11
-rw-r--r--src/network/networkd-address.c20
-rw-r--r--src/network/networkd-address.h1
-rw-r--r--src/network/networkd-network-gperf.gperf2
-rw-r--r--src/network/networkd-network.c5
-rw-r--r--src/network/networkd-network.h2
-rw-r--r--src/network/networkd-util.c10
-rw-r--r--src/network/networkd-util.h1
8 files changed, 39 insertions, 13 deletions
diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index 8b7c9ff32a..5b622877e1 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -729,9 +729,14 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
<listitem><para>Configures IP masquerading for the network
interface. If enabled, packets forwarded from the network
interface will be appear as coming from the local host.
- Takes a boolean argument. Implies
- <varname>IPForward=ipv4</varname>. Defaults to
- <literal>no</literal>.</para></listitem>
+ Takes one of <literal>ipv4</literal>, <literal>ipv6</literal>,
+ <literal>both</literal>, <literal>no</literal>.
+ The setting <literal>yes</literal> is the same as <literal>ipv4</literal> and not as
+ <literal>both</literal>!
+ Defaults to <literal>no</literal>.
+ If enabled, this automatically sets <varname>IPForward</varname> to one of
+ <literal>ipv4</literal>, <literal>ipv6</literal> or <literal>both</literal>.
+ </para></listitem>
</varlistentry>
<varlistentry>
<term><varname>IPv6PrivacyExtensions=</varname></term>
diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c
index 549f5f1f82..9c0e0220bb 100644
--- a/src/network/networkd-address.c
+++ b/src/network/networkd-address.c
@@ -261,16 +261,23 @@ static int address_set_masquerade(Address *address, bool add) {
if (!address->link->network)
return 0;
- if (!address->link->network->ip_masquerade)
+ if (address->family == AF_INET &&
+ !FLAGS_SET(address->link->network->ip_masquerade, ADDRESS_FAMILY_IPV4))
return 0;
- if (address->family != AF_INET)
+ if (address->family == AF_INET6 &&
+ !FLAGS_SET(address->link->network->ip_masquerade, ADDRESS_FAMILY_IPV6))
return 0;
if (address->scope >= RT_SCOPE_LINK)
return 0;
- if (address->ip_masquerade_done == add)
+ if (address->family == AF_INET &&
+ address->ip_masquerade_done == add)
+ return 0;
+
+ if (address->family == AF_INET6 &&
+ address->ipv6_masquerade_done == add)
return 0;
masked = address->in_addr;
@@ -278,11 +285,14 @@ static int address_set_masquerade(Address *address, bool add) {
if (r < 0)
return r;
- r = fw_add_masquerade(&address->link->manager->fw_ctx, add, AF_INET, &masked, address->prefixlen);
+ r = fw_add_masquerade(&address->link->manager->fw_ctx, add, address->family, &masked, address->prefixlen);
if (r < 0)
return r;
- address->ip_masquerade_done = add;
+ if (address->family == AF_INET)
+ address->ip_masquerade_done = add;
+ else if (address->family == AF_INET6)
+ address->ipv6_masquerade_done = add;
return 0;
}
diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h
index 4764766996..1a7f6c8ed2 100644
--- a/src/network/networkd-address.h
+++ b/src/network/networkd-address.h
@@ -38,6 +38,7 @@ typedef struct Address {
bool scope_set:1;
bool ip_masquerade_done:1;
+ bool ipv6_masquerade_done:1;
AddressFamily duplicate_address_detection;
/* Called when address become ready */
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 896a884063..516df61874 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -111,7 +111,7 @@ Network.DNSSEC, config_parse_dnssec_mode,
Network.DNSSECNegativeTrustAnchors, config_parse_dnssec_negative_trust_anchors, 0, 0
Network.NTP, config_parse_ntp, 0, offsetof(Network, ntp)
Network.IPForward, config_parse_address_family_with_kernel, 0, offsetof(Network, ip_forward)
-Network.IPMasquerade, config_parse_bool, 0, offsetof(Network, ip_masquerade)
+Network.IPMasquerade, config_parse_address_family_compat, 0, offsetof(Network, ip_masquerade)
Network.IPv6PrivacyExtensions, config_parse_ipv6_privacy_extensions, 0, offsetof(Network, ipv6_privacy_extensions)
Network.IPv6AcceptRA, config_parse_tristate, 0, offsetof(Network, ipv6_accept_ra)
Network.IPv6AcceptRouterAdvertisements, config_parse_tristate, 0, offsetof(Network, ipv6_accept_ra)
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 97a5f1b0d1..5d7f3b9b05 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -208,9 +208,8 @@ int network_verify(Network *network) {
if (network->link_local < 0)
network->link_local = network->bridge ? ADDRESS_FAMILY_NO : ADDRESS_FAMILY_IPV6;
- /* IPMasquerade=yes implies IPForward=yes */
- if (network->ip_masquerade)
- network->ip_forward |= ADDRESS_FAMILY_IPV4;
+ /* IPMasquerade implies IPForward */
+ network->ip_forward |= network->ip_masquerade;
network_adjust_ipv6_accept_ra(network);
network_adjust_dhcp(network);
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index bd419f6ef4..e6353c6dc7 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -100,7 +100,7 @@ struct Network {
KeepConfiguration keep_configuration;
char **bind_carrier;
bool default_route_on_device;
- bool ip_masquerade;
+ AddressFamily ip_masquerade;
/* DHCP Client Support */
AddressFamily dhcp;
diff --git a/src/network/networkd-util.c b/src/network/networkd-util.c
index 83b38b2b05..02a6800a41 100644
--- a/src/network/networkd-util.c
+++ b/src/network/networkd-util.c
@@ -53,6 +53,16 @@ DEFINE_CONFIG_PARSE_ENUM(config_parse_link_local_address_family, link_local_addr
AddressFamily, "Failed to parse option");
DEFINE_STRING_TABLE_LOOKUP(dhcp_lease_server_type, sd_dhcp_lease_server_type);
+static AddressFamily address_family_compat_from_string(const char *s) {
+ if (streq_ptr(s, "yes")) /* compat name */
+ return ADDRESS_FAMILY_IPV4;
+ if (streq_ptr(s, "both"))
+ return ADDRESS_FAMILY_YES;
+ return address_family_from_string(s);
+}
+DEFINE_CONFIG_PARSE_ENUM(config_parse_address_family_compat, address_family_compat,
+ AddressFamily, "Failed to parse option");
+
int config_parse_address_family_with_kernel(
const char* unit,
const char *filename,
diff --git a/src/network/networkd-util.h b/src/network/networkd-util.h
index 7b48046c35..76b4d0cfba 100644
--- a/src/network/networkd-util.h
+++ b/src/network/networkd-util.h
@@ -28,6 +28,7 @@ typedef struct NetworkConfigSection {
CONFIG_PARSER_PROTOTYPE(config_parse_link_local_address_family);
CONFIG_PARSER_PROTOTYPE(config_parse_address_family_with_kernel);
+CONFIG_PARSER_PROTOTYPE(config_parse_address_family_compat);
const char *address_family_to_string(AddressFamily b) _const_;
AddressFamily address_family_from_string(const char *s) _pure_;