summary refs log tree commit diff
path: root/nixos/modules/services/networking/dhcpd.nix
diff options
context:
space:
mode:
authorNikolay Amiantov <ab@fmap.me>2017-01-14 14:36:33 +0300
committerNikolay Amiantov <ab@fmap.me>2017-01-15 19:38:53 +0300
commit1158eda66a7646ca8b8204ffbb3d1c55a73d0374 (patch)
tree640cc2a9b8983213d343ce954a8334d0a71c89b7 /nixos/modules/services/networking/dhcpd.nix
parentf673243aff0bc9ae4d2e96ccd60124ff9fe5b103 (diff)
downloadnixlib-1158eda66a7646ca8b8204ffbb3d1c55a73d0374.tar
nixlib-1158eda66a7646ca8b8204ffbb3d1c55a73d0374.tar.gz
nixlib-1158eda66a7646ca8b8204ffbb3d1c55a73d0374.tar.bz2
nixlib-1158eda66a7646ca8b8204ffbb3d1c55a73d0374.tar.lz
nixlib-1158eda66a7646ca8b8204ffbb3d1c55a73d0374.tar.xz
nixlib-1158eda66a7646ca8b8204ffbb3d1c55a73d0374.tar.zst
nixlib-1158eda66a7646ca8b8204ffbb3d1c55a73d0374.zip
dhcpd service: add DHCPv6 support
Diffstat (limited to 'nixos/modules/services/networking/dhcpd.nix')
-rw-r--r--nixos/modules/services/networking/dhcpd.nix250
1 files changed, 149 insertions, 101 deletions
diff --git a/nixos/modules/services/networking/dhcpd.nix b/nixos/modules/services/networking/dhcpd.nix
index d2cd00e74a1f..86bcaa96f345 100644
--- a/nixos/modules/services/networking/dhcpd.nix
+++ b/nixos/modules/services/networking/dhcpd.nix
@@ -4,11 +4,10 @@ with lib;
 
 let
 
-  cfg = config.services.dhcpd;
+  cfg4 = config.services.dhcpd4;
+  cfg6 = config.services.dhcpd6;
 
-  stateDir = "/var/lib/dhcp"; # Don't use /var/state/dhcp; not FHS-compliant.
-
-  configFile = if cfg.configFile != null then cfg.configFile else pkgs.writeText "dhcpd.conf"
+  writeConfig = cfg: pkgs.writeText "dhcpd.conf"
     ''
       default-lease-time 600;
       max-lease-time 7200;
@@ -29,131 +28,180 @@ let
       }
     '';
 
-in
-
-{
-
-  ###### interface
-
-  options = {
+  dhcpdService = postfix: cfg: optionalAttrs cfg.enable {
+    "dhcpd${postfix}" = {
+      description = "DHCPv${postfix} server";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+
+      preStart = ''
+        mkdir -m 755 -p ${cfg.stateDir}
+        touch ${cfg.stateDir}/dhcpd.leases
+      '';
+
+      serviceConfig =
+        let
+          configFile = if cfg.configFile != null then cfg.configFile else writeConfig cfg;
+          args = [ "@${pkgs.dhcp}/sbin/dhcpd" "dhcpd${postfix}" "-${postfix}"
+                   "-pf" "/run/dhcpd${postfix}/dhcpd.pid"
+                   "-cf" "${configFile}"
+                   "-lf" "${cfg.stateDir}/dhcpd.leases"
+                   "-user" "dhcpd" "-group" "nogroup"
+                 ] ++ cfg.extraFlags
+                   ++ cfg.interfaces;
+
+        in {
+          ExecStart = concatMapStringsSep " " escapeShellArg args;
+          Type = "forking";
+          Restart = "always";
+          RuntimeDirectory = [ "dhcpd${postfix}" ];
+          PIDFile = "/run/dhcpd${postfix}/dhcpd.pid";
+        };
+    };
+  };
 
-    services.dhcpd = {
+  machineOpts = {...}: {
+    config = {
 
-      enable = mkOption {
-        default = false;
-        description = "
-          Whether to enable the DHCP server.
-        ";
+      hostName = mkOption {
+        type = types.str;
+        example = "foo";
+        description = ''
+          Hostname which is assigned statically to the machine.
+        '';
       };
 
-      extraConfig = mkOption {
-        type = types.lines;
-        default = "";
-        example = ''
-          option subnet-mask 255.255.255.0;
-          option broadcast-address 192.168.1.255;
-          option routers 192.168.1.5;
-          option domain-name-servers 130.161.158.4, 130.161.33.17, 130.161.180.1;
-          option domain-name "example.org";
-          subnet 192.168.1.0 netmask 255.255.255.0 {
-            range 192.168.1.100 192.168.1.200;
-          }
+      ethernetAddress = mkOption {
+        type = types.str;
+        example = "00:16:76:9a:32:1d";
+        description = ''
+          MAC address of the machine.
         '';
-        description = "
-          Extra text to be appended to the DHCP server configuration
-          file.  Currently, you almost certainly need to specify
-          something here, such as the options specifying the subnet
-          mask, DNS servers, etc.
-        ";
       };
 
-      extraFlags = mkOption {
-        default = "";
-        example = "-6";
-        description = "
-          Additional command line flags to be passed to the dhcpd daemon.
-        ";
+      ipAddress = mkOption {
+        type = types.str;
+        example = "192.168.1.10";
+        description = ''
+          IP address of the machine.
+        '';
       };
 
-      configFile = mkOption {
-        default = null;
-        description = "
-          The path of the DHCP server configuration file.  If no file
-          is specified, a file is generated using the other options.
-        ";
-      };
+    };
+  };
 
-      interfaces = mkOption {
-        default = ["eth0"];
-        description = "
-          The interfaces on which the DHCP server should listen.
-        ";
-      };
+  dhcpConfig = postfix: {
 
-      machines = mkOption {
-        default = [];
-        example = [
-          { hostName = "foo";
-            ethernetAddress = "00:16:76:9a:32:1d";
-            ipAddress = "192.168.1.10";
-          }
-          { hostName = "bar";
-            ethernetAddress = "00:19:d1:1d:c4:9a";
-            ipAddress = "192.168.1.11";
-          }
-        ];
-        description = "
-          A list mapping ethernet addresses to IP addresses for the
-          DHCP server.
-        ";
-      };
+    enable = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Whether to enable the DHCPv${postfix} server.
+      '';
+    };
 
+    stateDir = mkOption {
+      type = types.path;
+      # We use /var/lib/dhcp for DHCPv4 to save backwards compatibility.
+      default = "/var/lib/dhcp${if postfix == "4" then "" else postfix}";
+      description = ''
+        State directory for the DHCP server.
+      '';
     };
 
-  };
+    extraConfig = mkOption {
+      type = types.lines;
+      default = "";
+      example = ''
+        option subnet-mask 255.255.255.0;
+        option broadcast-address 192.168.1.255;
+        option routers 192.168.1.5;
+        option domain-name-servers 130.161.158.4, 130.161.33.17, 130.161.180.1;
+        option domain-name "example.org";
+        subnet 192.168.1.0 netmask 255.255.255.0 {
+          range 192.168.1.100 192.168.1.200;
+        }
+      '';
+      description = ''
+        Extra text to be appended to the DHCP server configuration
+        file. Currently, you almost certainly need to specify something
+        there, such as the options specifying the subnet mask, DNS servers,
+        etc.
+      '';
+    };
 
+    extraFlags = mkOption {
+      type = types.listOf types.str;
+      default = [];
+      description = ''
+        Additional command line flags to be passed to the dhcpd daemon.
+      '';
+    };
 
-  ###### implementation
+    configFile = mkOption {
+      type = types.nullOr types.path;
+      default = null;
+      description = ''
+        The path of the DHCP server configuration file.  If no file
+        is specified, a file is generated using the other options.
+      '';
+    };
 
-  config = mkIf config.services.dhcpd.enable {
+    interfaces = mkOption {
+      type = types.listOf types.str;
+      default = ["eth0"];
+      description = ''
+        The interfaces on which the DHCP server should listen.
+      '';
+    };
 
-    users = {
-      extraUsers.dhcpd = {
-        uid = config.ids.uids.dhcpd;
-        description = "DHCP daemon user";
-      };
+    machines = mkOption {
+      type = types.listOf (types.submodule machineOpts);
+      default = [];
+      example = [
+        { hostName = "foo";
+          ethernetAddress = "00:16:76:9a:32:1d";
+          ipAddress = "192.168.1.10";
+        }
+        { hostName = "bar";
+          ethernetAddress = "00:19:d1:1d:c4:9a";
+          ipAddress = "192.168.1.11";
+        }
+      ];
+      description = ''
+        A list mapping Ethernet addresses to IPv${postfix} addresses for the
+        DHCP server.
+      '';
     };
 
-    systemd.services.dhcpd =
-      { description = "DHCP server";
+  };
+
+in
+
+{
+
+  ###### interface
 
-        wantedBy = [ "multi-user.target" ];
+  options = {
 
-        after = [ "network.target" ];
+    services.dhcpd4 = dhcpConfig "4";
+    services.dhcpd6 = dhcpConfig "6";
 
-        path = [ pkgs.dhcp ];
+  };
 
-        preStart =
-          ''
-            mkdir -m 755 -p ${stateDir}
 
-            touch ${stateDir}/dhcpd.leases
+  ###### implementation
 
-            mkdir -m 755 -p /run/dhcpd
-            chown dhcpd /run/dhcpd
-          '';
+  config = mkIf (cfg4.enable || cfg6.enable) {
 
-        serviceConfig =
-          { ExecStart = "@${pkgs.dhcp}/sbin/dhcpd dhcpd"
-              + " -pf /run/dhcpd/dhcpd.pid -cf ${configFile}"
-              + " -lf ${stateDir}/dhcpd.leases -user dhcpd -group nogroup"
-              + " ${cfg.extraFlags}"
-              + " ${toString cfg.interfaces}";
-            Restart = "always";
-            Type = "forking";
-            PIDFile = "/run/dhcpd/dhcpd.pid";
-          };
+    users = {
+      extraUsers.dhcpd = {
+        uid = config.ids.uids.dhcpd;
+        description = "DHCP daemon user";
       };
+    };
+
+    systemd.services = dhcpdService "4" cfg4 // dhcpdService "6" cfg6;
 
   };