]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
networkd-network: Introduce DHCPv6 PD knob for RFC 7084 WPD-4
authorPatrik Flykt <patrik.flykt@linux.intel.com>
Fri, 7 Sep 2018 20:15:55 +0000 (14:15 -0600)
committerPatrik Flykt <patrik.flykt@linux.intel.com>
Wed, 19 Sep 2018 19:45:17 +0000 (13:45 -0600)
RFC 7084, WPD-4, requires Customer Edge end routers to behave
according to the following:

"WPD-4:  By default, the IPv6 CE router MUST initiate DHCPv6 prefix
           delegation when either the M or O flags are set to 1 in a
           received Router Advertisement (RA) message.  Behavior of the
           CE router to use DHCPv6 prefix delegation when the CE router
           has not received any RA or received an RA with the M and the
           O bits set to zero is out of scope for this document."

Since it cannot be automatically detected whether DHCPv6 is to be
operated as an CE end router or whether to initiate an Informational
exchange to obtain other useful network information via DHCPv6 when the
Router Advertisement 'O' bit is set, a 'ForceDHCPv6PDOtherInformation'
boolean network configuration option in the '[DHCP]' section of a is
introduced. Setting this option causes DHCPv6 to be started in stateful
mode, although only the 'O' bit is seen in the Router Advertisement.

When 'ForceDHCPv6PDOtherInformation' is set and the Router Advertisement
has only the Other information 'O' bit set, disable requests for IA_NA
addresses.

Fixes #9745.

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

index 31af7cfa9835fdc25525e400d857d9f60bf29566..2c564d26b47858786b628dc478df828ef24562f6 100644 (file)
           </listitem>
         </varlistentry>
 
+        <varlistentry>
+          <term><varname>ForceDHCPv6PDOtherInformation=</varname></term>
+          <listitem>
+            <para>A boolean that enforces DHCPv6 stateful mode when the 'Other information' bit is set in
+            Router Advertisement messages. By default setting only the 'O' bit in Router Advertisements
+            makes DHCPv6 request network information in a stateless manner using a two-message Information
+            Request and Information Reply message exchange.
+            <ulink url="https://tools.ietf.org/html/rfc7084">RFC 7084</ulink>, requirement WPD-4, updates
+            this behavior for a Customer Edge router so that stateful DHCPv6 Prefix Delegation is also
+            requested when only the 'O' bit is set in Router Advertisements. This option enables such a CE
+            behavior as it is impossible to automatically distinguish the intention of the 'O' bit otherwise.
+            By default this option is set to 'false', enable it if no prefixes are delegated when the device
+            should be acting as a CE router.</para>
+          </listitem>
+        </varlistentry>
+
       </variablelist>
     </refsect1>
 
index 0aa7a190c46a3aa12c888438879e7487afd2caaa..f9b97d17ddc43e514633b51b606d78ec1458e96d 100644 (file)
@@ -403,11 +403,12 @@ static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) {
 }
 
 int dhcp6_request_address(Link *link, int ir) {
-        int r, inf_req;
+        int r, inf_req, pd;
         bool running;
 
         assert(link);
         assert(link->dhcp6_client);
+        assert(link->network);
         assert(in_addr_is_link_local(AF_INET6, (const union in_addr_union*)&link->ipv6ll_address) > 0);
 
         r = sd_dhcp6_client_is_running(link->dhcp6_client);
@@ -416,6 +417,21 @@ int dhcp6_request_address(Link *link, int ir) {
         else
                 running = r;
 
+        r = sd_dhcp6_client_get_prefix_delegation(link->dhcp6_client, &pd);
+        if (r < 0)
+                return r;
+
+        if (pd && ir && link->network->dhcp6_force_pd_other_information) {
+                log_link_debug(link, "Enabling managed mode to request DHCPv6 PD with 'Other Information' set");
+
+                r = sd_dhcp6_client_set_address_request(link->dhcp6_client,
+                                                        false);
+                if (r < 0 )
+                        return r;
+
+                ir = false;
+        }
+
         if (running) {
                 r = sd_dhcp6_client_get_information_request(link->dhcp6_client, &inf_req);
                 if (r < 0)
index 357231152e0649c4f02fa4fc3144921a781d0fab..a7c94d1dc49143812adbe65f5b6a59c9a875f84f 100644 (file)
@@ -138,6 +138,7 @@ DHCP.UseTimezone,                       config_parse_bool,
 DHCP.IAID,                              config_parse_iaid,                              0,                             offsetof(Network, iaid)
 DHCP.ListenPort,                        config_parse_uint16,                            0,                             offsetof(Network, dhcp_client_port)
 DHCP.RapidCommit,                       config_parse_bool,                              0,                             offsetof(Network, rapid_commit)
+DHCP.ForceDHCPv6PDOtherInformation,    config_parse_bool,                              0,                             offsetof(Network, dhcp6_force_pd_other_information)
 IPv6AcceptRA.UseDNS,                    config_parse_bool,                              0,                             offsetof(Network, ipv6_accept_ra_use_dns)
 IPv6AcceptRA.UseDomains,                config_parse_dhcp_use_domains,                  0,                             offsetof(Network, ipv6_accept_ra_use_domains)
 IPv6AcceptRA.RouteTable,                config_parse_uint32,                            0,                             offsetof(Network, ipv6_accept_ra_route_table)
index 6bfd8d5dd5fd3f4045b3aa592744141138c337a7..1be7d467353b92e6a6d9d1b1b36b840b749b6dbe 100644 (file)
@@ -171,6 +171,9 @@ struct Network {
         struct in6_addr *router_dns;
         unsigned n_router_dns;
         char **router_search_domains;
+        bool dhcp6_force_pd_other_information; /* Start DHCPv6 PD also when 'O'
+                                                  RA flag is set, see RFC 7084,
+                                                  WPD-4 */
 
         /* Bridge Support */
         int use_bpdu;