]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
networkd: extend IPMasquerade to cover ipv6
authorFlorian Westphal <fw@strlen.de>
Thu, 17 Dec 2020 04:32:42 +0000 (05:32 +0100)
committerFlorian Westphal <fw@strlen.de>
Tue, 19 Jan 2021 15:38:53 +0000 (16:38 +0100)
Extend IPMasquerade to also cover ipv6.
For compatibility reasons with earlier releases IPMasquerade=yes
is identical to IPMasquerade=ipv4.

Use IPMasquerade=both to cover ipv6 as well as ipv4.

IPForward will now also enable ipv6 forwarding if IPMasquerade for ipv6 is enabled.

man/systemd.network.xml
src/network/networkd-address.c
src/network/networkd-address.h
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/networkd-network.h
src/network/networkd-util.c
src/network/networkd-util.h

index 8b7c9ff32a7c617bc3f0632b640abc195f8d457a..5b622877e19c785eb36a88298d2499229dd30a84 100644 (file)
@@ -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>
index 549f5f1f82ee0a31b07169c06fee3ea5013adb02..9c0e0220bbb13bff8725b987460c7ad1cba1a2cc 100644 (file)
@@ -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;
 }
index 4764766996f735b613a2dcf700b84c8bdd918929..1a7f6c8ed265068f5d83eb5312e07f744c377b78 100644 (file)
@@ -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 */
index 896a884063781a60ddeef4c8d1d5b62c3200ace5..516df618742ac4e81043f5e912bb0be188a0db5e 100644 (file)
@@ -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)
index 97a5f1b0d1b84643596bb9a00d46a20fb9347f70..5d7f3b9b0561c3ef33a5865ce2c6baab4e592f69 100644 (file)
@@ -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);
index bd419f6ef41ebafcf26f21102c789df62a1a5996..e6353c6dc72085b683985460627f3699df148d21 100644 (file)
@@ -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;
index 83b38b2b0538d75fd9c1e92f2b2a03473d4d07d3..02a6800a414d0fb2087321032b576f77f2433d90 100644 (file)
@@ -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,
index 7b48046c351ec0c546967ae816a2f2a788a4a7c1..76b4d0cfba44c6609c3a9851c8b97232ee1241c6 100644 (file)
@@ -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_;