diff --git a/hosts/carbon/ppp.nix b/hosts/carbon/ppp.nix index 1de2f19..77e6270 100644 --- a/hosts/carbon/ppp.nix +++ b/hosts/carbon/ppp.nix @@ -57,22 +57,19 @@ ip46tables -t mangle -A forward-mangle -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1416 ''; - networking.interfaces.net-heimnetz.useDHCP = true; - - networking.dhcpcd = { - enable = false; - allowInterfaces = [ - "net-heimnetz" - "ppp-dtagdsl" - ]; - wait = "ipv6"; - extraConfig = '' - ipv6only - noipv6rs - interface ppp-dtagdsl - ipv6rs - ia_pd 1/::/56 net-heimnetz/201/64 - ''; + networking.dhcpcd-prefixdelegation = { + enable = true; + interfaces = { + "ppp-dtagdsl" = { + iaid = 1; + interfaces = { + "net-heimnetz" = { + sla_id = 201; + prefix_len = 64; + }; + }; + }; + }; }; environment.etc."ppp/ipv6-up" = { diff --git a/modules/default.nix b/modules/default.nix index 09a16f8..41ba192 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -8,6 +8,7 @@ ./clerie-firewall ./clerie-gc-dir ./clerie-system-upgrade + ./dhcpcd-prefixdelegation ./minecraft-server ./monitoring ./nginx-port-forward diff --git a/modules/dhcpcd-prefixdelegation/default.nix b/modules/dhcpcd-prefixdelegation/default.nix new file mode 100644 index 0000000..a681efd --- /dev/null +++ b/modules/dhcpcd-prefixdelegation/default.nix @@ -0,0 +1,144 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.networking.dhcpcd-prefixdelegation; + + downstreamInterfaceConfig = name: opts: "${name}${ + optionalString (opts.sla_id != null) "/${builtins.toString opts.sla_id}${ + optionalString (opts.prefix_len != null) "/${builtins.toString opts.prefix_len}${ + optionalString (opts.suffix != null) "/${opts.suffix}" + }" + }" + }"; + + interfaceConfig = name: opts: '' + interface ${name} + ipv6rs + ia_pd ${builtins.toString opts.iaid}${ + optionalString (opts.prefix != null) "/${opts.prefix}${ + optionalString (opts.prefix_len != null) "/${builtins.toString opts.prefix_len}" + }" + } ${concatMapStringsSep " " ({name, value}: downstreamInterfaceConfig name value) (attrsToList opts.interfaces)} + ''; + + + dhcpcdConf = pkgs.writeText "dhcpcd.conf" '' + duid + noipv6rs + waitip 6 + ipv6only + + allowinterfaces ${concatStringsSep " " (builtins.attrNames cfg.interfaces)} ${concatMapStringsSep " " ({name, value}: concatStringsSep "" (builtins.attrNames value.interfaces)) (attrsToList cfg.interfaces)} + + ${concatMapStringsSep "\n" ({name, value}: interfaceConfig name value) (attrsToList cfg.interfaces)} + ''; + + downstreamInterfaceOpts = { ... }: { + options = { + sla_id = mkOption { + type = with types; nullOr ints.unsigned; + default = null; + }; + + prefix_len = mkOption { + type = with types; nullOr ints.unsigned; + default = null; + }; + + suffix = mkOption { + type = with types; nullOr str; + default = null; + }; + }; + }; + + interfaceOpts = { ... }: { + options = { + iaid = mkOption { + type = with types; ints.unsigned; + description = '' + Request a delegated prefix with this IAID on this interface + ''; + }; + + prefix = mkOption { + type = with types; nullOr str; + default = null; + }; + + prefix_len = mkOption { + type = with types; nullOr ints.unsigned; + default = null; + }; + + interfaces = mkOption { + type = with types; attrsOf (submodule downstreamInterfaceOpts); + default = {}; + description ='' + Interfaces to assign IPv6 prefixes to + ''; + }; + }; + }; + +in + +{ + + options = { + + networking.dhcpcd-prefixdelegation = { + enable = mkEnableOption "dhcpcd for prefixdelegation"; + + interfaces = mkOption { + type = with types; attrsOf (submodule interfaceOpts); + default = {}; + description = '' + Interfaces to request IPv6 prefixes from + ''; + }; + }; + }; + + config = mkIf cfg.enable { + + environment.etc."dhcpcd.conf".source = dhcpcdConf; + + systemd.services.dhcpcd-prefixdelegation = { + description = "DHCP Client for IPv6 Prefix Delegation"; + + wantedBy = [ "multi-user.target" ]; + wants = [ "network.target" ]; + before = [ "network-online.target" ]; + + # Stopping dhcpcd during a reconfiguration is undesirable + # because it brings down the network interfaces configured by + # dhcpcd. So do a "systemctl restart" instead. + stopIfChanged = false; + + path = [ pkgs.dhcpcd ]; + + unitConfig.ConditionCapability = "CAP_NET_ADMIN"; + + serviceConfig = + { Type = "forking"; + PIDFile = "/run/dhcpcd/pid"; + RuntimeDirectory = "dhcpcd"; + ExecStart = "@${pkgs.dhcpcd}/sbin/dhcpcd dhcpcd --quiet --config ${dhcpcdConf}"; + ExecReload = "${pkgs.dhcpcd}/sbin/dhcpcd --rebind"; + Restart = "always"; + }; + }; + + users.users.dhcpcd = { + isSystemUser = true; + group = "dhcpcd"; + }; + users.groups.dhcpcd = {}; + + }; + +}