commit c59a2289552fe1a748b2c65657b3ea75e9bd3d87
parent 1673a71831e8187588c9b418a09a262a962d02f8
Author: Daniel Barlow <dan@telent.net>
Date: Sun, 24 Sep 2023 23:29:30 +0100
this is the dhcp6c service we want
Diffstat:
11 files changed, 164 insertions(+), 61 deletions(-)
diff --git a/examples/demo.nix b/examples/demo.nix
@@ -7,7 +7,7 @@
{ config, pkgs, lib, ... } :
let
- inherit (pkgs.liminix.services) oneshot longrun;
+ inherit (pkgs.liminix.services) bundle oneshot longrun;
inherit (pkgs) serviceFns;
# EDIT: you can pick your preferred RFC1918 address space
# for NATted connections, if you don't like this one.
@@ -25,6 +25,7 @@ in rec {
imports = [
../modules/bridge
+ ../modules/dhcp6c
../modules/dnsmasq
../modules/firewall
../modules/hostapd
@@ -95,11 +96,16 @@ in rec {
resolvconf = services.resolvconf;
inherit interface;
ranges = [
- "${ipv4LocalNet}.10,${ipv4LocalNet}.240"
- # ra-stateless: sends router advertisements with the O and A
+ "${ipv4LocalNet}.10,${ipv4LocalNet}.249"
+ # EDIT: ... maybe. In this example we use "ra-stateless",
+ # meaning dnsmasq sends router advertisements with the O and A
# bits set, and provides a stateless DHCP service. The client
# will use a SLAAC address, and use DHCP for other
# configuration information.
+ # If you didn't understand the preceding sentence then
+ # the default is _probably_ fine, but if you need
+ # a DHCP-only IPv6 network or some other different
+ # configuration, this is the place to change it.
"::,constructor:$(output ${interface} ifname),ra-stateless"
];
# EDIT: choose a domain name for the DNS names issued for your
@@ -158,34 +164,37 @@ in rec {
services.packet_forwarding = svc.network.forward.build { };
- services.dhcp6 =
- let
- name = "dhcp6c.wan";
- in longrun {
- inherit name;
- notification-fd = 10;
- run = ''
- export SERVICE_STATE=/run/service-state/${name}
- ${pkgs.odhcp6c}/bin/odhcp6c -s ${pkgs.odhcp-script} -e -v -p /run/${name}.pid -P 48 $(output ${services.wan} ifname)
- )
- '';
- dependencies = [ services.wan ];
- };
-
- services.acquire-lan-prefix =
- let script = pkgs.callPackage ./acquire-delegated-prefix.nix { };
- in longrun {
- name = "acquire-lan-prefix";
- run = "${script} /run/service-state/dhcp6c.wan $(output ${services.int} ifname)";
- dependencies = [ services.dhcp6 ];
- };
-
- services.acquire-wan-address =
- let script = pkgs.callPackage ./acquire-wan-address.nix { };
- in longrun {
- name = "acquire-wan-address";
- run = "${script} /run/service-state/dhcp6c.wan $(output ${services.wan} ifname)";
- dependencies = [ services.dhcp6 ];
+ # We expect the ISP uses DHCP6 to issue IPv6 addresses. There is a
+ # service to request address information in the form of a DHCP
+ # lease, and two dependent services that listen for updates to the
+ # DHCP address information and update the addresses of the WAN and
+ # LAN interfaces respectively.
+
+ services.dhcp6c =
+ let client = svc.dhcp6c.client.build {
+ interface = services.wan;
+ };
+ in bundle {
+ name = "dhcp6c";
+ contents = [
+ (svc.dhcp6c.prefix.build {
+ # if your ISP provides you a real IPv6 prefix for your local
+ # network (usually a /64 or /48 or something in between the
+ # two), this service subscribes to that "prefix delegation"
+ # information, and uses it to assign an address to the LAN
+ # device. dnsmasq will notice this address and use it to
+ # form the addresses it hands out to devices on the lan
+ inherit client;
+ interface = services.int;
+ })
+ (svc.dhcp6c.address.build {
+ # if your ISP provides you a regular global IPv6 address,
+ # this service subscribes to that information and assigns
+ # the address to the WAN device.
+ inherit client;
+ interface = services.wan;
+ })
+ ];
};
defaultProfile.packages = with pkgs; [
diff --git a/examples/rotuer.nix b/examples/rotuer.nix
@@ -9,7 +9,7 @@
{ config, pkgs, lib, ... } :
let
secrets = import ./rotuer-secrets.nix;
- inherit (pkgs.liminix.services) oneshot longrun;
+ inherit (pkgs.liminix.services) oneshot longrun bundle;
inherit (pkgs) serviceFns;
svc = config.system.service;
wirelessConfig = {
@@ -38,6 +38,7 @@ in rec {
../modules/network
../modules/ppp
../modules/dnsmasq
+ ../modules/dhcp6c
../modules/firewall
../modules/hostapd
../modules/bridge
@@ -154,39 +155,27 @@ in rec {
};
services.firewall = svc.firewall.build {
- ruleset = import ./rotuer-firewall.nix;
+ ruleset = import ./demo-firewall.nix;
};
services.packet_forwarding = svc.network.forward.build { };
- services.dhcp6 =
- let
- name = "dhcp6c.wan";
- in longrun {
- inherit name;
- notification-fd = 10;
- run = ''
- export SERVICE_STATE=/run/service-state/${name}
- ${pkgs.odhcp6c}/bin/odhcp6c -s ${pkgs.odhcp-script} -e -v -p /run/${name}.pid -P 48 $(output ${services.wan} ifname)
- )
- '';
- dependencies = [ services.wan ];
- };
-
- services.acquire-lan-prefix =
- let script = pkgs.callPackage ./acquire-delegated-prefix.nix { };
- in longrun {
- name = "acquire-lan-prefix";
- run = "${script} /run/service-state/dhcp6c.wan $(output ${services.int} ifname)";
- dependencies = [ services.dhcp6 ];
- };
-
- services.acquire-wan-address =
- let script = pkgs.callPackage ./acquire-wan-address.nix { };
- in longrun {
- name = "acquire-wan-address";
- run = "${script} /run/service-state/dhcp6c.wan $(output ${services.wan} ifname)";
- dependencies = [ services.dhcp6 ];
+ services.dhcp6c =
+ let client = svc.dhcp6c.client.build {
+ interface = services.wan;
+ };
+ in bundle {
+ name = "dhcp6c";
+ contents = [
+ (svc.dhcp6c.prefix.build {
+ inherit client;
+ interface = services.int;
+ })
+ (svc.dhcp6c.address.build {
+ inherit client;
+ interface = services.wan;
+ })
+ ];
};
defaultProfile.packages = with pkgs; [
diff --git a/examples/acquire-delegated-prefix.fnl b/modules/dhcp6c/acquire-delegated-prefix.fnl
diff --git a/examples/acquire-delegated-prefix.nix b/modules/dhcp6c/acquire-delegated-prefix.nix
diff --git a/examples/acquire-wan-address-test.fnl b/modules/dhcp6c/acquire-wan-address-test.fnl
diff --git a/examples/acquire-wan-address.fnl b/modules/dhcp6c/acquire-wan-address.fnl
diff --git a/examples/acquire-wan-address.nix b/modules/dhcp6c/acquire-wan-address.nix
diff --git a/modules/dhcp6c/address.nix b/modules/dhcp6c/address.nix
@@ -0,0 +1,16 @@
+{
+ liminix
+, lib
+, callPackage
+}:
+{ client, interface } :
+let
+ inherit (liminix.services) longrun;
+ inherit (lib) mkOption types;
+ name = "dhcp6c.addr.${client.name}.${interface.name}";
+ script = callPackage ./acquire-wan-address.nix { };
+in longrun {
+ inherit name;
+ run = "${script} /run/service-state/${client.name} $(output ${interface} ifname)";
+ dependencies = [ client interface ];
+}
diff --git a/modules/dhcp6c/client.nix b/modules/dhcp6c/client.nix
@@ -0,0 +1,21 @@
+{
+ liminix
+, lib
+, odhcp6c
+, odhcp-script
+}:
+{ interface } :
+let
+ inherit (liminix.services) longrun;
+ inherit (lib) mkOption types;
+ name = "dhcp6c.${interface.name}";
+in longrun {
+ inherit name;
+ notification-fd = 10;
+ run = ''
+ export SERVICE_STATE=/run/service-state/${name}
+ ${odhcp6c}/bin/odhcp6c -s ${odhcp-script} -e -v -p /run/${name}.pid -P0 $(output ${interface} ifname)
+ )
+ '';
+ dependencies = [ interface ];
+}
diff --git a/modules/dhcp6c/default.nix b/modules/dhcp6c/default.nix
@@ -0,0 +1,52 @@
+## DHCP6 client module
+## ===================
+##
+## This is for use if you have an IPv6-capable upstream that provides
+## address information and/or prefix delegation using DHCP6. It
+## provides a service to request address information in the form of a
+## DHCP lease, and two dependent services that listen for updates
+## to the DHCP address information and can be used to update
+## addresses of network interfaces that you want to assign those
+## prefixes to
+
+{ lib, pkgs, config, ...}:
+let
+ inherit (lib) mkOption types;
+ inherit (pkgs.liminix.services) oneshot;
+ inherit (pkgs) liminix;
+in
+{
+ options = {
+ system.service.dhcp6c = {
+ client = mkOption { type = liminix.lib.types.serviceDefn; };
+ prefix = mkOption { type = liminix.lib.types.serviceDefn; };
+ address = mkOption { type = liminix.lib.types.serviceDefn; };
+ };
+ };
+ config.system.service.dhcp6c = {
+ client = liminix.callService ./client.nix {
+ interface = mkOption {
+ type = liminix.lib.types.interface;
+ description = "interface (usually WAN) to query for DHCP6";
+ };
+ };
+ address = liminix.callService ./address.nix {
+ client = mkOption {
+ type = types.anything; # liminix.lib.types.service;
+ };
+ interface = mkOption {
+ type = liminix.lib.types.interface;
+ description = "interface to assign the address to";
+ };
+ };
+ prefix = liminix.callService ./prefix.nix {
+ client = mkOption {
+ type = types.anything; # liminix.lib.types.service;
+ };
+ interface = mkOption {
+ type = liminix.lib.types.interface;
+ description = "interface to assign <prefix>::1 to";
+ };
+ };
+ };
+}
diff --git a/modules/dhcp6c/prefix.nix b/modules/dhcp6c/prefix.nix
@@ -0,0 +1,16 @@
+{
+ liminix
+, lib
+, callPackage
+}:
+{ client, interface } :
+let
+ inherit (liminix.services) longrun;
+ inherit (lib) mkOption types;
+ name = "dhcp6c.prefix.${client.name}.${interface.name}";
+ script = callPackage ./acquire-delegated-prefix.nix { };
+in longrun {
+ inherit name;
+ run = "${script} /run/service-state/${client.name} $(output ${interface} ifname)";
+ dependencies = [ client interface ];
+}