From 0a6af46364d8991bbeda2e2c5c5bdcaaea028895 Mon Sep 17 00:00:00 2001 From: Daniel Barlow Date: Mon, 4 Sep 2023 22:06:53 +0100 Subject: [PATCH] support dhcp static leases --- THOUGHTS.txt | 96 +++++++++++++++++++++++++++++++++++++ modules/dnsmasq/default.nix | 31 ++++++++++++ modules/dnsmasq/service.nix | 7 ++- 3 files changed, 133 insertions(+), 1 deletion(-) diff --git a/THOUGHTS.txt b/THOUGHTS.txt index c6c9f8cb..0f11f6b3 100644 --- a/THOUGHTS.txt +++ b/THOUGHTS.txt @@ -2151,3 +2151,99 @@ Thu Aug 31 23:53:54 BST 2023 - [done] ntp is not setting the time - static dhcp(6) lease support reqd for dogfooding +Sat Sep 2 21:35:41 BST 2023 + +Considerations for "mount" service: each filesystem needs to depend on +any mount points for its parent directories, and maybe also on other +services (e.g. filesystem modules, network devices, routes) + +mountpoints = { + mnt = { + media = svc.mountpoint.build { + fstype = "msdos"; + device = "/dev/sda1"; + options = [ ...]; + }; + archive = svc.mountpoint.build { + fstype = "ext4"; + device = "/dev/sda2"; + options = [ ...]; + mountpoints = { + remote = svc.mountpoint.build { + fstype = "nfs"; + device = "doc.ic.ac.uk:/public"; + }; + }; + }; + }; +} + +services.somethingelse = svc.ftpd.build { + # ... + dependencies = [ mountpoints.mnt.archive ]; +} + +what don't we like about this? we have to walk the nested attrset in a +weird way, because the services may contain other mountpoints. Maybe +just keep it simple and do + + +services.mountpoints = bundle { + name = "mountpoints"; + contents = [ + svc.mountpoint.build { + device = "/dev/sda2"; fstype = "ext4"; directory = "/mnt/isos"; + }; + svc.mountpoint.build { + device = "/dev/sdb1"; fstype = "msdos"; directory = "/mnt/backup"; + dependencies = [ load-vfat-module ]; + }; + ]; +} + +Sun Sep 3 17:34:36 BST 2023 + +how to dogfood + +DHCP6 server: static lease support +DHCP client and acquire-{lan-prefix,wan-address} + +The emergency boot thingy in glinet u-boot won't help because it +expects to flash from its tftp request instead of booting it. So we +could use kexec instead except that the openwrt install doesn't have +it. So we could swap the hardware devices, the only downside of that +being that then I don't have a test system any more. Or we could YOLO it. + +Sun Sep 3 22:11:02 BST 2023 + +I think we should rejigger the documentation ... + +- "getting started": worked example, building and installing Liminix +with a very simple config (wifi AP with ssh daemon) + +- using modules + - link to module reference + +- creating custom services + - longrun or oneshot + - dependencies + - outputs + +- creating your own modules + +- hacking on Liminix itself + +- contributing + +- external links and resources + +- module reference + +- hardware device reference + +--- + +I think we might rename wlan_24 to wlan and wlan_5 to wlan1. +This is on the assumption that almost no device is 5GHz only, so +would make it easier to write a basic wlan example that works +both on 2.4GHz boards and dual radio boards diff --git a/modules/dnsmasq/default.nix b/modules/dnsmasq/default.nix index 59c39b7c..b8ad7535 100644 --- a/modules/dnsmasq/default.nix +++ b/modules/dnsmasq/default.nix @@ -42,6 +42,37 @@ in { ranges = mkOption { type = types.listOf types.str; }; + hosts = mkOption { + type = types.attrsOf (types.submodule { + options = { + mac = mkOption { + description = '' + MAC or other hardware address to match on. For Ethernet + this is a 48 bit address represented as colon-separated + hex bytes, or "id:clientid" to match a presented + client id (IPv6 DUID) + ''; + type = types.str; + example = "01:20:31:4a:50"; + }; + v4 = mkOption { + description = "IPv4 address to assign to this client"; + example = "192.0.2.1"; + type = types.str; + }; + v6 = mkOption { + type = types.listOf types.str; + description = "IPv6 addresses or interface-ids to assign to this client"; + default = []; + example = [ "fe80::42:1eff:fefd:b341" "::1234"]; + }; + leasetime = mkOption { + type = types.int; + default = 86400; + }; + }; + }); + }; domain = mkOption { # this can be given multiple times so probably should be # domains plural and list of string diff --git a/modules/dnsmasq/service.nix b/modules/dnsmasq/service.nix index 02cf4764..aa1a2608 100644 --- a/modules/dnsmasq/service.nix +++ b/modules/dnsmasq/service.nix @@ -10,13 +10,17 @@ , domain , group , ranges +, hosts , upstreams , resolvconf }: let name = "${interface.name}.dnsmasq"; inherit (liminix.services) longrun; - inherit (lib) concatStringsSep; + inherit (lib) concatStrings concatStringsSep mapAttrsToList; + hostOpt = name : { mac, v4, v6, leasetime } @ attrs: + let v6s = concatStrings (map (a : ",[${a}]") v6); + in "--dhcp-host=${mac},${v4}${v6s},${name},${builtins.toString leasetime}"; in longrun { inherit name; @@ -33,6 +37,7 @@ longrun { --keep-in-foreground \ --dhcp-authoritative \ ${if resolvconf != null then "--resolv-file=$(output_path ${resolvconf} resolv.conf)" else "--no-resolv"} \ + ${lib.concatStringsSep " " (mapAttrsToList hostOpt hosts)} \ --no-hosts \ --log-dhcp \ --enable-ra \