From 53033aaf5a2620c8adaf6e66ef9afc1d567132c2 Mon Sep 17 00:00:00 2001
From: Vincent Haupert <mail@vincent-haupert.de>
Date: Sat, 30 Jan 2021 11:04:35 +0100
Subject: [PATCH 1/5] nixos/networkd: add missing dhcpV6Config options

---
 nixos/modules/system/boot/networkd.nix | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/nixos/modules/system/boot/networkd.nix b/nixos/modules/system/boot/networkd.nix
index 3b01bc00baf..2a679ffa81a 100644
--- a/nixos/modules/system/boot/networkd.nix
+++ b/nixos/modules/system/boot/networkd.nix
@@ -643,18 +643,29 @@ let
 
       sectionDHCPv6 = checkUnitConfig "DHCPv6" [
         (assertOnlyFields [
+          "UseAddress"
           "UseDNS"
           "UseNTP"
+          "RouteMetric"
           "RapidCommit"
+          "MUDURL"
+          "RequestOptions"
+          "SendVendorOption"
           "ForceDHCPv6PDOtherInformation"
           "PrefixDelegationHint"
-          "RouteMetric"
+          "WithoutRA"
+          "SendOption"
+          "UserClass"
+          "VendorClass"
         ])
+        (assertValueOneOf "UseAddress" boolValues)
         (assertValueOneOf "UseDNS" boolValues)
         (assertValueOneOf "UseNTP" boolValues)
+        (assertInt "RouteMetric")
         (assertValueOneOf "RapidCommit" boolValues)
         (assertValueOneOf "ForceDHCPv6PDOtherInformation" boolValues)
-        (assertInt "RouteMetric")
+        (assertValueOneOf "WithoutRA" ["solicit" "information-request"])
+        (assertRange "SendOption" 1 65536)
       ];
 
       sectionDHCPServer = checkUnitConfig "DHCPServer" [

From 38f19af76935a5c86ee17daa41cc835fe8f10ac9 Mon Sep 17 00:00:00 2001
From: Vincent Haupert <mail@vincent-haupert.de>
Date: Sat, 30 Jan 2021 11:24:13 +0100
Subject: [PATCH 2/5] nixos/networkd: add dhcpV6PrefixDelegationConfig option

networkd gained a new section [DHCPv6PrefixDelegation] which
controls delegated prefixes assigned by DHCPv6 client. Added in systemd
246.
---
 nixos/modules/system/boot/networkd.nix | 29 ++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/nixos/modules/system/boot/networkd.nix b/nixos/modules/system/boot/networkd.nix
index 2a679ffa81a..382e4abe620 100644
--- a/nixos/modules/system/boot/networkd.nix
+++ b/nixos/modules/system/boot/networkd.nix
@@ -437,6 +437,7 @@ let
           "IPv6ProxyNDP"
           "IPv6ProxyNDPAddress"
           "IPv6PrefixDelegation"
+          "DHCPv6PrefixDelegation"
           "IPv6MTUBytes"
           "Bridge"
           "Bond"
@@ -478,6 +479,7 @@ let
         (assertValueOneOf "IPv4ProxyARP" boolValues)
         (assertValueOneOf "IPv6ProxyNDP" boolValues)
         (assertValueOneOf "IPv6PrefixDelegation" ["static" "dhcpv6" "yes" "false"])
+        (assertValueOneOf "DHCPv6PrefixDelegation" boolValues)
         (assertByteFormat "IPv6MTUBytes")
         (assertValueOneOf "ActiveSlave" boolValues)
         (assertValueOneOf "PrimarySlave" boolValues)
@@ -668,6 +670,17 @@ let
         (assertRange "SendOption" 1 65536)
       ];
 
+      sectionDHCPv6PrefixDelegation = checkUnitConfig "DHCPv6PrefixDelegation" [
+        (assertOnlyFields [
+          "SubnetId"
+          "Announce"
+          "Assign"
+          "Token"
+        ])
+        (assertValueOneOf "Announce" boolValues)
+        (assertValueOneOf "Assign" boolValues)
+      ];
+
       sectionDHCPServer = checkUnitConfig "DHCPServer" [
         (assertOnlyFields [
           "PoolOffset"
@@ -1101,6 +1114,18 @@ let
       '';
     };
 
+    dhcpV6PrefixDelegationConfig = mkOption {
+      default = {};
+      example = { SubnetId = "auto"; Announce = true; };
+      type = types.addCheck (types.attrsOf unitOption) check.network.sectionDHCPv6PrefixDelegation;
+      description = ''
+        Each attribute in this set specifies an option in the
+        <literal>[DHCPv6PrefixDelegation]</literal> section of the unit. See
+        <citerefentry><refentrytitle>systemd.network</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
     dhcpServerConfig = mkOption {
       default = {};
       example = { PoolOffset = 50; EmitDNS = false; };
@@ -1468,6 +1493,10 @@ let
           [DHCPv6]
           ${attrsToSection def.dhcpV6Config}
         ''
+        + optionalString (def.dhcpV6PrefixDelegationConfig != { }) ''
+          [DHCPv6PrefixDelegation]
+          ${attrsToSection def.dhcpV6PrefixDelegationConfig}
+        ''
         + optionalString (def.dhcpServerConfig != { }) ''
           [DHCPServer]
           ${attrsToSection def.dhcpServerConfig}

From 735111487b6f5d0e1353e4bac157366ec5036756 Mon Sep 17 00:00:00 2001
From: Vincent Haupert <mail@vincent-haupert.de>
Date: Sat, 30 Jan 2021 11:32:07 +0100
Subject: [PATCH 3/5] nixos/networkd: add ipv6AcceptRAConfig option

Adds `systemd.network.networks.*.ipv6AcceptRAConfig` for networkd's
[IPv6AcceptRA] section.
---
 nixos/modules/system/boot/networkd.nix | 39 ++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/nixos/modules/system/boot/networkd.nix b/nixos/modules/system/boot/networkd.nix
index 382e4abe620..d439c602534 100644
--- a/nixos/modules/system/boot/networkd.nix
+++ b/nixos/modules/system/boot/networkd.nix
@@ -681,6 +681,29 @@ let
         (assertValueOneOf "Assign" boolValues)
       ];
 
+      sectionIPv6AcceptRA = checkUnitConfig "IPv6AcceptRA" [
+        (assertOnlyFields [
+          "UseDNS"
+          "UseDomains"
+          "RouteTable"
+          "UseAutonomousPrefix"
+          "UseOnLinkPrefix"
+          "RouterDenyList"
+          "RouterAllowList"
+          "PrefixDenyList"
+          "PrefixAllowList"
+          "RouteDenyList"
+          "RouteAllowList"
+          "DHCPv6Client"
+        ])
+        (assertValueOneOf "UseDNS" boolValues)
+        (assertValueOneOf "UseDomains" (boolValues ++ ["route"]))
+        (assertRange "RouteTable" 0 4294967295)
+        (assertValueOneOf "UseAutonomousPrefix" boolValues)
+        (assertValueOneOf "UseOnLinkPrefix" boolValues)
+        (assertValueOneOf "DHCPv6Client" (boolValues ++ ["always"]))
+      ];
+
       sectionDHCPServer = checkUnitConfig "DHCPServer" [
         (assertOnlyFields [
           "PoolOffset"
@@ -1126,6 +1149,18 @@ let
       '';
     };
 
+    ipv6AcceptRAConfig = mkOption {
+      default = {};
+      example = { UseDNS = true; DHCPv6Client = "always"; };
+      type = types.addCheck (types.attrsOf unitOption) check.network.sectionIPv6AcceptRA;
+      description = ''
+        Each attribute in this set specifies an option in the
+        <literal>[IPv6AcceptRA]</literal> section of the unit. See
+        <citerefentry><refentrytitle>systemd.network</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
     dhcpServerConfig = mkOption {
       default = {};
       example = { PoolOffset = 50; EmitDNS = false; };
@@ -1497,6 +1532,10 @@ let
           [DHCPv6PrefixDelegation]
           ${attrsToSection def.dhcpV6PrefixDelegationConfig}
         ''
+        + optionalString (def.ipv6AcceptRAConfig != { }) ''
+          [IPv6AcceptRA]
+          ${attrsToSection def.ipv6AcceptRAConfig}
+        ''
         + optionalString (def.dhcpServerConfig != { }) ''
           [DHCPServer]
           ${attrsToSection def.dhcpServerConfig}

From e6660ffe7ff0a516bf6347d01aca7231129c4c03 Mon Sep 17 00:00:00 2001
From: Vincent Haupert <mail@vincent-haupert.de>
Date: Sat, 30 Jan 2021 12:33:14 +0100
Subject: [PATCH 4/5] nixos/networkd: rename ipv6PrefixDelegationConfig option
 to ipv6SendRAConfig

networkd's [IPv6PrefixDelegation] section and IPv6PrefixDelegation=
options have been renamed as [IPv6SendRA] and IPv6SendRA= in systemd
247.

Throws if the deprecated option ipv6PrefixDelegationConfig is used.
---
 nixos/modules/system/boot/networkd.nix | 24 +++++++++++++++---------
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/nixos/modules/system/boot/networkd.nix b/nixos/modules/system/boot/networkd.nix
index d439c602534..d9ae298490c 100644
--- a/nixos/modules/system/boot/networkd.nix
+++ b/nixos/modules/system/boot/networkd.nix
@@ -436,7 +436,7 @@ let
           "IPv4ProxyARP"
           "IPv6ProxyNDP"
           "IPv6ProxyNDPAddress"
-          "IPv6PrefixDelegation"
+          "IPv6SendRA"
           "DHCPv6PrefixDelegation"
           "IPv6MTUBytes"
           "Bridge"
@@ -478,7 +478,7 @@ let
         (assertMinimum "IPv6HopLimit" 0)
         (assertValueOneOf "IPv4ProxyARP" boolValues)
         (assertValueOneOf "IPv6ProxyNDP" boolValues)
-        (assertValueOneOf "IPv6PrefixDelegation" ["static" "dhcpv6" "yes" "false"])
+        (assertValueOneOf "IPv6SendRA" boolValues)
         (assertValueOneOf "DHCPv6PrefixDelegation" boolValues)
         (assertByteFormat "IPv6MTUBytes")
         (assertValueOneOf "ActiveSlave" boolValues)
@@ -732,7 +732,7 @@ let
         (assertValueOneOf "EmitTimezone" boolValues)
       ];
 
-      sectionIPv6PrefixDelegation = checkUnitConfig "IPv6PrefixDelegation" [
+      sectionIPv6SendRA = checkUnitConfig "IPv6SendRA" [
         (assertOnlyFields [
           "Managed"
           "OtherInformation"
@@ -1173,13 +1173,20 @@ let
       '';
     };
 
+    # systemd.network.networks.*.ipv6PrefixDelegationConfig has been deprecated
+    # in 247 in favor of systemd.network.networks.*.ipv6SendRAConfig.
     ipv6PrefixDelegationConfig = mkOption {
+      visible = false;
+      apply = _: throw "The option `systemd.network.networks.*.ipv6PrefixDelegationConfig` has been replaced by `systemd.network.networks.*.ipv6SendRAConfig`.";
+    };
+
+    ipv6SendRAConfig = mkOption {
       default = {};
       example = { EmitDNS = true; Managed = true; OtherInformation = true; };
-      type = types.addCheck (types.attrsOf unitOption) check.network.sectionIPv6PrefixDelegation;
+      type = types.addCheck (types.attrsOf unitOption) check.network.sectionIPv6SendRA;
       description = ''
         Each attribute in this set specifies an option in the
-        <literal>[IPv6PrefixDelegation]</literal> section of the unit.  See
+        <literal>[IPv6SendRA]</literal> section of the unit.  See
         <citerefentry><refentrytitle>systemd.network</refentrytitle>
         <manvolnum>5</manvolnum></citerefentry> for details.
       '';
@@ -1540,9 +1547,9 @@ let
           [DHCPServer]
           ${attrsToSection def.dhcpServerConfig}
         ''
-        + optionalString (def.ipv6PrefixDelegationConfig != { }) ''
-          [IPv6PrefixDelegation]
-          ${attrsToSection def.ipv6PrefixDelegationConfig}
+        + optionalString (def.ipv6SendRAConfig != { }) ''
+          [IPv6SendRA]
+          ${attrsToSection def.ipv6SendRAConfig}
         ''
         + flip concatMapStrings def.ipv6Prefixes (x: ''
           [IPv6Prefix]
@@ -1558,7 +1565,6 @@ let
 in
 
 {
-
   options = {
 
     systemd.network.enable = mkOption {

From 730da50f8512f134d119a2fa4ca12e91bc38a338 Mon Sep 17 00:00:00 2001
From: Vincent Haupert <mail@vincent-haupert.de>
Date: Sat, 30 Jan 2021 13:25:32 +0100
Subject: [PATCH 5/5] nixos/tests: adapt
 systemd-networkd-ipv6-prefix-delegation

---
 ...ystemd-networkd-ipv6-prefix-delegation.nix | 20 ++++++++-----------
 1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/nixos/tests/systemd-networkd-ipv6-prefix-delegation.nix b/nixos/tests/systemd-networkd-ipv6-prefix-delegation.nix
index bce78f09fdc..5831c8692f6 100644
--- a/nixos/tests/systemd-networkd-ipv6-prefix-delegation.nix
+++ b/nixos/tests/systemd-networkd-ipv6-prefix-delegation.nix
@@ -165,7 +165,7 @@ import ./make-test-python.nix ({pkgs, ...}: {
               # accept the delegated prefix.
               PrefixDelegationHint  = "::/48";
             };
-            ipv6PrefixDelegationConfig = {
+            ipv6SendRAConfig = {
               # Let networkd know that we would very much like to use DHCPv6
               # to obtain the "managed" information. Not sure why they can't
               # just take that from the upstream RAs.
@@ -179,24 +179,20 @@ import ./make-test-python.nix ({pkgs, ...}: {
             name = "eth2";
             networkConfig = {
               Description = "Client interface";
-              # the client shouldn't be allowed to send us RAs, that would be weird.
+              # The client shouldn't be allowed to send us RAs, that would be weird.
               IPv6AcceptRA = false;
 
-              # Just delegate prefixes from the DHCPv6 PD pool.
-              # If you also want to distribute a local ULA prefix you want to
-              # set this to `yes` as that includes both static prefixes as well
-              # as PD prefixes.
-              IPv6PrefixDelegation = "dhcpv6";
+              # Delegate prefixes from the DHCPv6 PD pool.
+              DHCPv6PrefixDelegation = true;
+              IPv6SendRA = true;
             };
-            # finally "act as router" (according to systemd.network(5))
-            ipv6PrefixDelegationConfig = {
-              RouterLifetimeSec = 300; # required as otherwise no RA's are being emitted
 
-              # In a production environment you should consider setting these as well:
+            # In a production environment you should consider setting these as well:
+            # ipv6SendRAConfig = {
               #EmitDNS = true;
               #EmitDomains = true;
               #DNS= = "fe80::1"; # or whatever "well known" IP your router will have on the inside.
-            };
+            # };
 
             # This adds a "random" ULA prefix to the interface that is being
             # advertised to the clients.