1
0
Fork 0

Compare commits

...

192 Commits

Author SHA1 Message Date
Daniel Barlow 2663f58807 disable security for bordervm "liminix" share
tftp needs to be able to follow symlinks into the store
2024-07-01 20:53:03 +01:00
Daniel Barlow 9dbc285605 build libusb1 without libatomic 2024-06-30 17:52:17 +01:00
Daniel Barlow 8b6aa2134e zyxel dual image; restore deleted params 2024-06-30 17:50:45 +01:00
Daniel Barlow 3df1ec76ff cleanup whitespace and commas
* [] is now [ ]
* {} is now { }
* commas in arglists go at end of line not beginning

In short, I ran the whole thing through nixfmt-rfc-style but only
accepted about 30% of its changes. I might grow accustomed to more
of it over time
2024-06-30 17:16:28 +01:00
Daniel Barlow 0d3218127f remove unused makeWrapper input 2024-06-30 10:46:37 +01:00
Daniel Barlow e94bf62ec1 remove dead code (run deadnix) 2024-06-29 22:59:27 +01:00
Daniel Barlow 16a2499d74 avoid makeWrapper on host, it requires bash 2024-06-29 22:36:05 +01:00
Daniel Barlow d4d8093f97 working l2tp-over-wwan stick example 2024-06-20 10:15:54 +01:00
Daniel Barlow 7c9c801afc rename isTrigger to restart-on-upgrade
we're moving away from "trigger" services to "controller" services,
and "restart-on-upgrade" is the name used by s6-rc
2024-06-16 12:58:06 +01:00
Daniel Barlow c4185617c0 a6-rc-up-tree wait for lock if needed 2024-06-15 15:36:07 +01:00
Daniel Barlow 06d28e9b08 dhcpc handle case when env vars are missing
the notify-script should continue and signal readiness even if one or
more of the outputs it writes are mssing in the environment
2024-06-15 15:34:49 +01:00
Daniel Barlow 9540fc2641 add writeAshScriptBin (forgot to add file) 2024-06-15 15:04:56 +01:00
Daniel Barlow adc84108ad Revert "wwan gets address from ppp ipcp not dhcp"
This reverts commit be13ab23ca.
2024-06-15 15:04:33 +01:00
Daniel Barlow eae99051fa exec devout in service definition
makes little practical difference but saves a process slot
2024-06-15 15:01:57 +01:00
Daniel Barlow 49d1703428 add s6-rc-up-tree: start reverse deps of controlled service
When s6-rc stops a service, it also stops everything that
depends on it. but when it starts a service it starts only
that service, so we have to go through the other services
depending on it and figure out if they should be started too.
2024-06-15 14:59:34 +01:00
Daniel Barlow 1d337588f9 think 2024-06-15 09:04:19 +01:00
Daniel Barlow 29a869b4fa qemu: use kmodloader for wifi 2024-06-13 10:12:17 +01:00
Daniel Barlow 5ae1b0a193 Revert "bodervm: remove usbutils until we can fix the udev dep"
This reverts commit c22e3fb2ef.
2024-06-12 20:58:13 +01:00
Daniel Barlow 473a4947a5 inout test: wait longer for disk to appear 2024-06-12 20:44:03 +01:00
Daniel Barlow 50bad5c604 libusb needs udev on build
this is a workaround to make CI work again, but what we really need to
do is completely separate the nixpkgs used for nixos build-system
tools from the nixpkgs we use for liminix host binaries
2024-06-12 18:55:30 +01:00
Daniel Barlow c22e3fb2ef bodervm: remove usbutils until we can fix the udev dep 2024-06-12 13:07:29 +01:00
Daniel Barlow f898e4dca2 remove debug 2024-06-12 13:03:26 +01:00
Daniel Barlow 5121a8563d callService: dependencies are services not names 2024-06-12 12:58:57 +01:00
Daniel Barlow 78be354b6e think 2024-06-12 12:52:52 +01:00
Daniel Barlow be13ab23ca wwan gets address from ppp ipcp not dhcp 2024-06-12 12:51:07 +01:00
Daniel Barlow 4b30cd7a75 think 2024-06-11 14:05:32 +01:00
Daniel Barlow b15542b668 start correct services at boot
- uncontrolled services that are not dependent on a controlled service
- controllers
- _not_ controlled services or any other service that depends on one
2024-06-11 14:04:14 +01:00
Daniel Barlow 6daeaf29a0 flip controller/controlled relationship for wwan services 2024-06-11 14:02:48 +01:00
Daniel Barlow e6ca5ea064 store derivations not just names for service deps
.. also controllers, contents. This is to make it possible (easier)
to work out transitive dependencies at build time
2024-06-11 14:01:06 +01:00
Daniel Barlow e6e4665a18 flip dependencies for triggered/controlled services
Instead of treating the trigger as the "main" service and the
triggered service as subsidary, now we treat the triggered
service as the service and the trigger as "subsidary". This
needs some special handling when we work out which services
go in the default bundle, but it works better for declaring
dependencies on triggered services because it means the
dependency runs after the triggered service comes up, not
just when the watcher-for-events starts
2024-06-09 22:37:45 +01:00
Daniel Barlow 2c10790a6d think 2024-06-09 11:19:38 +01:00
Daniel Barlow 571adf84c0 inherit builtins.map 2024-06-07 16:55:45 +01:00
Daniel Barlow c8c79fd75a update all calls to uevent-watch 2024-06-02 20:42:09 +01:00
Daniel Barlow 884d8d194e wrap uevent-watch in a service 2024-06-02 20:42:09 +01:00
Daniel Barlow f091bbd706 devout: recognise attr,attrs when parsing search term string 2024-06-01 23:48:05 +01:00
Daniel Barlow 37d7e20582 wwan use uevent-watch to find tty for AT commands 2024-06-01 23:47:20 +01:00
Daniel Barlow 04b068f7a3 delete unused code 2024-06-01 22:43:48 +01:00
Daniel Barlow 53f57c1a8c devout: support sysfs attributes for (grand*)parent device 2024-06-01 22:43:27 +01:00
Daniel Barlow 19aba0d873 devout: support search for sysfs attributes 2024-06-01 21:20:41 +01:00
Daniel Barlow 7d00b39249 rename attributes->properties when referring to uevent fields
properties: key-value pairs in the uevent message
attributes: file contents in sysfs
2024-06-01 12:17:49 +01:00
Daniel Barlow 7aa8633cde think 2024-06-01 12:16:21 +01:00
Daniel Barlow 58bec8a40f semi-automate tftpbooting with minicom 2024-05-26 18:03:32 +01:00
Daniel Barlow a3fca5bf05 devout: add functions to read sysfs attributes 2024-05-26 18:03:32 +01:00
Daniel Barlow e0bd7aec1e wwan: hook usb-modeswitch to uevent 2024-05-26 18:03:32 +01:00
Daniel Barlow e815f61bb5 think 2024-05-26 18:00:31 +01:00
Daniel Barlow af9200a136 skip symlink handing unless linkname was provided 2024-05-26 18:00:31 +01:00
Daniel Barlow 898958fa10 make a serviceDefn for wwan 2024-05-22 18:54:49 +01:00
Daniel Barlow fa0f262706 commentary 2024-05-22 18:54:49 +01:00
Daniel Barlow 71aeb27b2f add hacky wwan service with hardcoding all over 2024-05-22 18:54:49 +01:00
Daniel Barlow 530b4080c9 create cdc-ncm module 2024-05-22 18:54:49 +01:00
Daniel Barlow 58cd007ccc barebones usb_modeswitch package 2024-05-22 18:54:49 +01:00
Daniel Barlow 3a56798eb5 l2tp set default route via tunnel 2024-05-22 18:54:49 +01:00
Daniel Barlow 758c7ef657 exec xl2tpd
haven't fully worked out why, but without this s6 is unable to stop it.
2024-05-22 18:54:49 +01:00
Daniel Barlow 73225a70b2 add rudimentary l2tp service module 2024-05-22 18:54:49 +01:00
Daniel Barlow ab304dd3f1 bordervm enable nat 2024-05-22 18:47:37 +01:00
Daniel Barlow 0d49f0f7a7 gl-ar750 appendDTB 2024-05-22 18:47:16 +01:00
Daniel Barlow e64390460a memorable net device names for gl-ar750
linux's view of eth1 and eth0 are opposite to that of u-boot
2024-05-22 18:47:08 +01:00
Daniel Barlow c0ef6ce282 list pkgs we need in bordervm build
it's a bit silly trying to build it with the whole liminix overlay
when it's a nixos system not a liminix system
2024-05-22 18:45:35 +01:00
Daniel Barlow bd6ec5201f run dhcp server on bordervm
this is for testing clients that have dhcp upstream
2024-05-22 18:45:35 +01:00
Daniel Barlow b4068da9fe tftp addresses 2024-05-22 18:45:35 +01:00
Daniel Barlow aa4b09da85 think (foreshadowing) 2024-05-22 18:45:23 +01:00
Daniel Barlow 471c63b399 s6-rc do cleanup in "finish", don't append to "run" script
s6-supervise sends signals (e.g. SIGTERM) to the pid of the process
running "run", so how do we know if the ceanup commands are even
getting executed if the shell interpreter that is supposed to do that
got killed already?
2024-05-13 17:53:02 +01:00
Daniel Barlow 782feaeafa set default for firewall extraRules 2024-05-03 16:28:53 +01:00
Daniel Barlow ac54c89427 add busybox to bordervm for udhcpd 2024-05-01 23:09:23 +01:00
Daniel Barlow 5a3646cb29 add authorized keys to bordervm
You don't often need this because it has autologin, but sometimes
you want to do antics involving sshing through it to the wan port
of a test device.

Note that you probably wanted to start bordervm with funny qemu
options to even make that possible

 nix-shell --run "QEMU_NET_OPTS=hostfwd=tcp::10022-:22 run-border-vm"
2024-05-01 23:07:11 +01:00
Daniel Barlow e249f48cff add deps on {ins,rm}mod and kconfig for firewall module 2024-05-01 23:06:12 +01:00
Daniel Barlow 6661e42684 mt300a tftpboot needs appendDTB 2024-05-01 23:04:25 +01:00
Daniel Barlow b9ba9ef835 mt300a remove unneeded service dependencies 2024-05-01 23:03:55 +01:00
Daniel Barlow 8b69dcc209 pass entire config fragment to levitate, not just services
to make it useful we need to be able to set packages, passwords, ssh
keys etc
2024-04-29 20:07:01 +01:00
Daniel Barlow 9b3a3b9ff7 add levitate to arhcive
this is largely untested
2024-04-28 21:38:13 +01:00
Daniel Barlow 7d08497bcb arhcive remove coldplug fudge 2024-04-28 21:37:30 +01:00
Daniel Barlow 0e84adaa0e maybe don't need deps for gl-mt300a vlan devices?
will delete them next time I have that device open to test
2024-04-28 21:35:09 +01:00
Daniel Barlow 660ed5df8f vlan interface services depend on primary 2024-04-28 21:33:36 +01:00
Daniel Barlow 792a11c8c0 gl-mt300n-v2 use full path to swconfig in service stop 2024-04-28 21:32:42 +01:00
Daniel Barlow 7e4a05bbf8 separate kernel and base modules
this is needed for levitate
2024-04-28 12:44:27 +01:00
Daniel Barlow a4ba5c85e1 alphabetize list in all-modules 2024-04-28 12:42:47 +01:00
Daniel Barlow 723ef73d5a inout: test hotplug and coldplug 2024-04-27 22:41:30 +01:00
Daniel Barlow 3d4e782929 devout: run tests in postBuild
because checkPhase is not executed when cross-compiling, and this
package is always only cross-compiled
2024-04-27 21:07:25 +01:00
Daniel Barlow 1b6a05aec5 make uevent-watch use devout instead of direct netlink 2024-04-27 21:07:25 +01:00
Daniel Barlow 80628a3d90 move event matching tests to devout
in preparation for future uevent-watch not needing to do
event matching
2024-04-27 21:07:25 +01:00
Daniel Barlow bf0cafffed start devout alongside mdevd
ensure it starts before mdevd-coldplug so it can populate
its database
2024-04-26 20:52:12 +01:00
Daniel Barlow e49aba127c devout: improve socket error handling 2024-04-26 20:49:23 +01:00
Daniel Barlow 324465bc18 devout: write uevent KEY=value format to clients 2024-04-26 17:37:28 +01:00
Daniel Barlow b33249a050 devout: add readiness notification 2024-04-26 17:23:29 +01:00
Daniel Barlow b9c084415e devout: handle readiness on netlink socket but no event 2024-04-26 17:20:33 +01:00
Daniel Barlow cf9cadd212 devout: replay relevant events to new subscriber 2024-04-26 17:20:33 +01:00
Daniel Barlow a116fe084a devout: use socket constants from anoia.net.constants 2024-04-26 16:48:51 +01:00
Daniel Barlow 74cf3e0711 add anoia.net.constants for SOCK_{STREAM,DGRAM} etc
we use an ugly bit of C preprocessor to get the values from
header files, because certain constants are different on MIPS
than on other architectures
2024-04-26 16:43:09 +01:00
Daniel Barlow 9795f03da4 think 2024-04-26 16:41:31 +01:00
Daniel Barlow cdb23b147c convert anoia.fs to use lualinux 2024-04-25 21:14:37 +01:00
Daniel Barlow dbd1264352 convert anoia.fs to use lualinux instead of lfs 2024-04-24 20:44:32 +01:00
Daniel Barlow 834858d5bc think 2024-04-24 18:33:57 +01:00
Daniel Barlow 18335b95e3 devout: strip newlines from client terms
this is just to make testing with socat easier
2024-04-24 18:33:02 +01:00
Daniel Barlow 6bee2f67ac devout: add incoming netlink messages to database 2024-04-24 18:32:27 +01:00
Daniel Barlow b4ba3eea21 fix revents in unpack-pollfds 2024-04-24 18:31:26 +01:00
Daniel Barlow 16af3984c9 add lualinux to fennelrepl 2024-04-24 18:30:34 +01:00
Daniel Barlow ce7e395295 devout test: replace minisock with lualinux 2024-04-24 18:29:24 +01:00
Daniel Barlow 7e13e017eb add readline suport to fennelrepl 2024-04-24 18:28:39 +01:00
Daniel Barlow bbf2f53c0e cross-compile lualinux 2024-04-24 18:28:14 +01:00
Daniel Barlow 032d0f8aca add netlink socket
it's not hooked up to anything yet, but it proves we can
do this with lualinux
2024-04-23 23:34:25 +01:00
Daniel Barlow b8ac9e5279 convert devout from minisock to lualinux 2024-04-23 23:33:11 +01:00
Daniel Barlow ff2604ca5d think 2024-04-23 23:30:50 +01:00
Daniel Barlow 72789984ce add lualinux package 2024-04-23 22:41:38 +01:00
Daniel Barlow 90d9d0e811 update minisock to not scribble on lua strings 2024-04-23 20:19:33 +01:00
Daniel Barlow 97a8ae1c84 devout: add event loop and main `run` function 2024-04-23 20:15:02 +01:00
Daniel Barlow 52eb283a26 implement unsubscribe
and add ids to subscribe so that there's a unique identifier
to pass to unsubscribe
2024-04-23 20:12:46 +01:00
Daniel Barlow cbb1de804e switch to minisock fork witj poll() call
this is likely to be temporary as minisock is getting
replaced with lualinux
2024-04-23 20:09:41 +01:00
Daniel Barlow f9c03998b8 implement subscriptions with callback 2024-04-21 13:19:17 +01:00
Daniel Barlow 50de1b090f add the rest of the test list (all we've thought of) 2024-04-21 11:22:26 +01:00
Daniel Barlow 648382f64a report bodyless tests as PENDING 2024-04-21 11:19:42 +01:00
Daniel Barlow e9370358ae implement "remove" events 2024-04-21 11:19:06 +01:00
Daniel Barlow 762ce7b6b8 cut/paste devout implementation into a real module 2024-04-20 22:48:00 +01:00
Daniel Barlow b1c0560f4f implement fetch by path 2024-04-20 22:20:43 +01:00
Daniel Barlow e34135c41a improve failed test reporting 2024-04-20 21:46:37 +01:00
Daniel Barlow 712c9b266f implement find 2024-04-20 18:42:42 +01:00
Daniel Barlow 4df963996c devout: add device 2024-04-20 18:24:10 +01:00
Daniel Barlow 349bfecbb8 new package "devout", does nothing yet 2024-04-20 17:45:40 +01:00
Daniel Barlow 450d3820b2 clean up uevent-watch test using writeFennel and mainFunction
requires less cavorting with globals and stuff
2024-04-20 16:53:43 +01:00
Daniel Barlow 771585546d import expect= where previously it was copy-pasted 2024-04-20 15:09:50 +01:00
Daniel Barlow 73abf952d5 package minisock, a minimal Lua socket library 2024-04-20 15:09:17 +01:00
Daniel Barlow 8af4e9fd5b package anoia assert macros and point fennelrepl at them 2024-04-20 14:59:14 +01:00
Daniel Barlow 7e19d80130 anoia: add assert macro module
contains expect and expect=
2024-04-20 14:04:32 +01:00
Daniel Barlow 0f0688c802 think 2024-04-20 14:03:48 +01:00
Daniel Barlow b43f17f655 think 2024-04-20 12:23:04 +01:00
Daniel Barlow adf62d4483 arhcive: make it work when disk is attached before boot
This is a bit of a kludge (a lot of a kludge) but it will
get it running whilt I work on something better
2024-04-17 18:49:30 +01:00
Daniel Barlow 68eb1360f6 use appended dtb in gl-mt300n-v2 tftpboot
probably the A variant needs this as well
2024-04-17 18:48:19 +01:00
Daniel Barlow 19ad6cd278 watchdog: put s6 pkg on $PATH for s6-svstat 2024-04-17 13:01:10 +01:00
Daniel Barlow 00076c7b81 mount service: use uevent-watch 2024-04-17 12:59:13 +01:00
Daniel Barlow 721e7499f3 arhcive: use usb module instead of harcoded kconfig 2024-04-17 12:53:43 +01:00
Daniel Barlow fc723b9a35 think 2024-04-16 18:59:01 +01:00
Daniel Barlow a5f16dfa81 convert inout test to use uevent-watch 2024-04-15 22:15:27 +01:00
Daniel Barlow 41a4b1f7ef clean cruft from inout test script 2024-04-15 22:00:44 +01:00
Daniel Barlow 42a5699326 remove unneeded config from inout test 2024-04-15 21:19:18 +01:00
Daniel Barlow ea2b25168e add uevent-watch, which toggles services based on uevent msgs 2024-04-15 21:15:07 +01:00
Daniel Barlow 5564cf0554 add nellie.close 2024-04-14 22:45:29 +01:00
Daniel Barlow f3a13630d3 add multicast groups param to nellie.open 2024-04-14 22:45:29 +01:00
Daniel Barlow f233acf9ff netlink uevent hello world 2024-04-14 22:45:29 +01:00
Daniel Barlow b6a054c588 add mdevd as module
following the upstream example, it republishes uevent messages
using multicast group 4 instead of group 2 as used by udev.
2024-04-14 21:59:23 +01:00
Daniel Barlow b231664a06 anoia: add basename, dirname 2024-04-11 23:11:20 +01:00
Daniel Barlow f4bf3029fa anoia: alphabetize exports 2024-04-11 23:11:13 +01:00
Daniel Barlow 05f2c9a2f7 add lua in nix-shell environment 2024-04-11 23:11:06 +01:00
Daniel Barlow 5df5c822ea convert mount service to trigger
Good: this means it's not hanging holding the s6 dataase lock.

Bad: it's the ugliest implementation and doesn't deserve to be preserved

(tbf the ugliness is not new)
2024-04-03 23:17:36 +01:00
Daniel Barlow 4795dd05b7 unconditionally restart trigger services on liminix-rebuild
We call s6-rc -u -p default to restart/start the base services
on a rebuild, otherwise services that are only in the new
configuration won't come up. However, this stops any service
started by a trigger. So, workaround is to restart the trigger
service and expect it to restart the services it manages if they're
needed
2024-04-03 23:07:56 +01:00
Daniel Barlow a192f08881 remove missing module 2024-03-29 17:34:10 +00:00
Daniel Barlow a873dc6608 Merge commit 'efcfdcc' 2024-03-28 23:47:04 +00:00
Daniel Barlow 2fb4756a7f add soft restart option to liminix-rebuild
instead of doing a full reboot, it runs activate / and uses
s6-rc-update to install the new service database
2024-03-28 23:45:10 +00:00
Daniel Barlow 04f5174425 fix vanilla-configuration defaultroute 2024-03-28 22:13:21 +00:00
Daniel Barlow dca2e4def1 fix params to s6-rc-init
flags must precede scandir otherwise they're ignored
2024-03-28 21:56:28 +00:00
Daniel Barlow b60126775a improve liminix-rebuild test
* make it executable
* improve robustness
* do't hardcode services.default (why did it do this?)
2024-03-28 21:37:47 +00:00
Daniel Barlow 76f11bcc93 liminix-rebuild: remove -f flag from reboot call
now we have timeouts in service definitions, shouldn't need this
any more
2024-03-28 21:37:47 +00:00
Daniel Barlow efcfdcc21d think 2024-03-28 20:59:39 +00:00
Daniel Barlow 77f1a78331 ifwait block if s6-rc lock is held
otherwise it doesn't trigger the service if something else is
slow to start
2024-03-28 20:59:39 +00:00
Daniel Barlow 28a5dec7dd implement ifwait trigger service and use in bridge
should we convert all ifwait uses to this trigger too? seems
reasonable
2024-03-28 20:59:39 +00:00
Daniel Barlow fad0a47b75 add config.system.callService
this is like pkgs.callService except that it passes
config.system.service as a param so that the service
being defined can invoke other services

if this proves to be a good idea, all uses of
pkgs.callService should be changed to use it instead
2024-03-28 20:59:39 +00:00
Daniel Barlow af52aafc84 deep thoughts 2024-03-28 20:59:39 +00:00
Daniel Barlow 34442b6069 failing test for ifwait 2024-03-28 20:59:39 +00:00
Daniel Barlow b8a46fc05e allow buildInputs param to s6 service
this is in preparation for trigger services that need to
close over the triggered service without adding it to
s6-rc dependencies
2024-03-28 20:58:53 +00:00
Daniel Barlow 8ac2c6cec1 support timeouts (default 30s) for starting s6-rc services 2024-03-28 20:58:47 +00:00
Daniel Barlow 8879b2d1ba fix rt2x00 wifi 2024-03-28 20:58:39 +00:00
Daniel Barlow 83e346d5a0 add deviceName param 2024-03-22 21:55:44 +00:00
Daniel Barlow 156b1fe64a deep thoughts 2024-03-22 21:54:38 +00:00
Daniel Barlow 1a314e55b7 firewall module: provide default rules and merge extraRules
a firewall with no configuration will get a relatively sane ruleset. a
firewall with `extraRules` will get them deep merged into the default
rules.  Specifying `rules` will override the defaults
2024-03-21 12:00:34 +00:00
Daniel Barlow 9263b21faa create gateway profile by extracting from rotuer example 2024-03-21 10:04:42 +00:00
Daniel Barlow 0a820a702a extneder: delete nftables kernel config
don't need nftables on a bridge. (do we? hope not)
2024-03-20 19:05:31 +00:00
Daniel Barlow 4ea518e296 expose modulesPath to ease out-of-tree configuration.nix 2024-03-20 18:58:44 +00:00
Daniel Barlow 98318b450d deep thoughts 2024-03-16 20:16:49 +00:00
Daniel Barlow e4ac7f19dc fix ifwait deps 2024-03-16 20:16:49 +00:00
Daniel Barlow 9c22744850 deep thoughts 2024-03-16 20:16:49 +00:00
Daniel Barlow c697be8c28 temporary fix for cmake cross-compilation 2024-03-16 20:16:49 +00:00
dan 202a37221a Merge pull request 'tftpboot: use commandLineDtbNode' (#11) from flokli/liminix:tftpboot-honor-commandLineDtbNode into main
Reviewed-on: dan/liminix#11
2024-03-16 18:18:18 +00:00
Florian Klink 436eb03a7b tftpboot: use commandLineDtbNode
config.boot.commandLineDtbNode can be set from `bootargs` to
`bootargs-override` (used for boards where the u-boot on the board does
set `bootargs` on its own).

In that case, the code updating the cmdline for tftpboot purposes also
needs to update this node, not the `bootargs` node.

Otherwise the kernel won't find the phram device, as it never heard
about it, as it didn't get the necessary cmdline options.
2024-03-16 20:06:38 +02:00
Daniel Barlow e5963ae3f7 deep thoughts 2024-03-06 23:19:47 +00:00
Daniel Barlow f164f19d95 service starts and stops 2024-03-06 23:19:47 +00:00
Daniel Barlow dd4ab41f6a rename run-event 2024-03-06 23:19:47 +00:00
Daniel Barlow 5d5dff6729 WIP add failing test that service starts 2024-03-06 23:19:47 +00:00
Daniel Barlow 570d29c368 pass command line params to run instead of reffing global 2024-03-06 23:19:47 +00:00
Daniel Barlow 725af00dc9 improve test for dummy0 up
if we run off the end of the events fixture, it didn't work
2024-03-06 23:19:47 +00:00
Daniel Barlow e1b932ec27 remove hardcoded filename in test event generator 2024-03-06 23:19:47 +00:00
Daniel Barlow 7173b6fb1c don't call os.exit 2024-03-06 23:19:47 +00:00
Daniel Barlow ed9548f21d pass event producer fn as param 2024-03-06 23:19:47 +00:00
Daniel Barlow 0787807a7f ifwait: don't run on load if in test harness 2024-03-06 23:19:47 +00:00
Daniel Barlow 38ed91f641 simplify assertion 2024-03-06 23:19:47 +00:00
Daniel Barlow ffe9603c39 remove file-scoped parameters var 2024-03-06 23:19:47 +00:00
Daniel Barlow cbd3dfefc5 ifwait fixture/test harness 2024-03-06 23:19:47 +00:00
Daniel Barlow 018c1868b5 ifwait: use anoia.assoc 2024-03-06 23:19:47 +00:00
Daniel Barlow 5184ff63f7 add anoia.nl, a convenience wrapper on netlink 2024-03-06 23:19:47 +00:00
Daniel Barlow 35909c9a23 add netlink to fennelrepl 2024-03-06 23:19:47 +00:00
Daniel Barlow 4383462199 deep thoughts 2024-03-06 23:19:47 +00:00
Daniel Barlow 9730cdd63b add assoc to anoia 2024-03-06 23:19:47 +00:00
dan 095853214b Merge pull request 'Fix kernel build on belkin' (#10) from sinavir/liminix:fix_kernel_build_on_belkin into main
Reviewed-on: dan/liminix#10
2024-03-06 18:21:13 +00:00
sinavir 27c7735f02 belkin-RT3200: fix kernel options 2024-02-22 21:57:40 +01:00
sinavir 29c9de248d fix import of openwrt sources 2024-02-22 21:57:33 +01:00
1616 changed files with 5965 additions and 1065 deletions

21
NEWS
View File

@ -83,4 +83,23 @@ sponsoring this development (and funding the hardware)
2024-02-21
New port! Thanks to Raito Bezarius, Liminix now runs on the Zyxel NWA50AX,
an MT7621 (MIPS EL) dual radio WiFi AP.
an MT7621 (MIPS EL) dual radio WiFi AP.
2024-04-29
The setup for using `levitate` has changed: now it accepts an entire
config fragment, not just a list of services. Hopefully this makes it
a bit more useful :-)
defaultProfile.packages = with pkgs; [
...
(levitate.override {
config = {
services = {
inherit (config.services) dhcpc sshd watchdog;
};
defaultProfile.packages = [ mtdutils ];
users.root.openssh.authorizedKeys.keys = secrets.root.keys;
};
})
];

File diff suppressed because it is too large Load Diff

20
boot.expect Normal file
View File

@ -0,0 +1,20 @@
# This is for use with minicom, but needs you to configure it to
# use expect as its "Script program" instead of runscript. Try
# Ctrl+A O -> Filenames and paths -> D
log_user 0
log_file -a -open stderr
set f [open "result/boot.scr"]
send "version\r"
set timeout 60
while {[gets $f line] >= 0} {
puts stderr "next line $line\r"
puts stderr "waiting for prompt\r"
expect {
"ath>" {}
"BusyBox" { puts stderr "DONE"; exit 0 }
}
send "$line\r\n"
}
puts stderr "done\r\n"
close $f

View File

@ -4,6 +4,10 @@ let
inherit (lib) mkOption mkEnableOption mdDoc types optional optionals;
in {
options.bordervm = {
keys = mkOption {
type = types.listOf types.str;
default = [ ];
};
l2tp = {
host = mkOption {
description = mdDoc ''
@ -51,18 +55,17 @@ in {
<nixpkgs/nixos/modules/virtualisation/qemu-vm.nix>
];
config = {
boot.kernelParams = [
"loglevel=9"
];
boot.kernelParams = [ "loglevel=9" ];
systemd.services.pppoe =
let conf = pkgs.writeText "kpppoed.toml"
''
interface_name = "eth1"
services = [ "myservice" ]
lns_ipaddr = "${cfg.l2tp.host}:${builtins.toString cfg.l2tp.port}"
ac_name = "kpppoed-1.0"
'';
in {
let
conf = pkgs.writeText "kpppoed.toml" ''
interface_name = "eth1"
services = [ "myservice" ]
lns_ipaddr = "${cfg.l2tp.host}:${builtins.toString cfg.l2tp.port}"
ac_name = "kpppoed-1.0"
'';
in
{
wantedBy = [ "multi-user.target" ];
after = [ "network-online.target" ];
serviceConfig = {
@ -76,24 +79,36 @@ in {
};
};
services.openssh.enable = true;
services.dnsmasq = {
enable = true;
resolveLocalQueries = false;
settings = {
# domain-needed = true;
dhcp-range = [ "10.0.0.10,10.0.0.240" ];
interface = "eth1";
};
};
systemd.services.sshd.wantedBy = pkgs.lib.mkForce [ "multi-user.target" ];
virtualisation = {
qemu = {
networkingOptions = [];
options = [] ++
optional cfg.ethernet.pci.enable
"-device vfio-pci,host=${cfg.ethernet.pci.id}" ++
optionals cfg.ethernet.usb.enable [
networkingOptions = [ ];
options =
[ ]
++ optional cfg.ethernet.pci.enable "-device vfio-pci,host=${cfg.ethernet.pci.id}"
++ optionals cfg.ethernet.usb.enable [
"-device usb-ehci,id=ehci"
"-device usb-host,bus=ehci.0,vendorid=${cfg.ethernet.usb.vendor},productid=${cfg.ethernet.usb.product}"
] ++ [
]
++ [
"-nographic"
"-serial mon:stdio"
];
};
sharedDirectories = {
liminix = {
securityModel = "none";
source = builtins.toString ./.;
target = "/home/liminix/liminix";
};
@ -108,6 +123,7 @@ in {
tufted
iptables
usbutils
busybox
];
security.sudo.wheelNeedsPassword = false;
networking = {
@ -117,11 +133,17 @@ in {
useDHCP = false;
ipv4.addresses = [ { address = "10.0.0.1"; prefixLength = 24;}];
};
nat = {
enable = true;
internalInterfaces = [ "eth1" ];
externalInterface = "eth0";
};
};
users.users.liminix = {
isNormalUser = true;
uid = 1000;
extraGroups = [ "wheel"];
extraGroups = [ "wheel" ];
openssh.authorizedKeys.keys = cfg.keys;
};
services.getty.autologinUser = "liminix";
};

View File

@ -1,8 +1,12 @@
{...}:
{ ... }:
{
bordervm = {
# ethernet.pci = { id = "01:00.0"; enable = true; };
ethernet.usb = { vendor = "0x0bda"; product = "0x8153"; enable = true; };
ethernet.usb = {
vendor = "0x0bda";
product = "0x8153";
enable = true;
};
l2tp = {
host = "l2tp.aa.net.uk";
};

60
ci.nix
View File

@ -1,12 +1,12 @@
{
nixpkgs
, unstable
, liminix
, ... }:
nixpkgs,
unstable,
liminix,
...
}:
let
inherit (builtins) map;
pkgs = (import nixpkgs {});
borderVmConf = ./bordervm.conf-example.nix;
pkgs = (import nixpkgs { });
borderVmConf = ./bordervm.conf-example.nix;
inherit (pkgs.lib.attrsets) genAttrs;
devices = [
"gl-ar750"
@ -27,33 +27,35 @@ let
}).outputs.default;
tests = import ./tests/ci.nix;
jobs =
(genAttrs devices for-device) //
tests //
{
buildEnv = (import liminix {
inherit nixpkgs borderVmConf;
device = import (liminix + "/devices/qemu");
liminix-config = vanilla;
}).buildEnv;
(genAttrs devices for-device)
// tests
// {
buildEnv =
(import liminix {
inherit nixpkgs borderVmConf;
device = import (liminix + "/devices/qemu");
liminix-config = vanilla;
}).buildEnv;
doc =
let json =
(import liminix {
inherit nixpkgs borderVmConf;
device = import (liminix + "/devices/qemu");
liminix-config = {...} : {
let
json =
(import liminix {
inherit nixpkgs borderVmConf;
device = import (liminix + "/devices/qemu");
liminix-config =
{ ... }:
{
imports = [ ./modules/all-modules.nix ];
};
}).outputs.optionsJson;
installers = map (f: "system.outputs.${f}") [
"vmroot"
"mtdimage"
"ubimage"
];
inherit (pkgs.lib) concatStringsSep;
in pkgs.stdenv.mkDerivation {
}).outputs.optionsJson;
in
pkgs.stdenv.mkDerivation {
name = "liminix-doc";
nativeBuildInputs = with pkgs; [
gnumake sphinx fennel luaPackages.lyaml
gnumake
sphinx
fennel
luaPackages.lyaml
];
src = ./.;
buildPhase = ''

View File

@ -1,31 +1,39 @@
{
device
, liminix-config ? <liminix-config>
, nixpkgs ? <nixpkgs>
, borderVmConf ? ./bordervm.conf.nix
, imageType ? "primary"
deviceName ? null,
device ? (import ./devices/${deviceName}),
liminix-config ? <liminix-config>,
nixpkgs ? <nixpkgs>,
borderVmConf ? ./bordervm.conf.nix,
imageType ? "primary",
}:
let
overlay = import ./overlay.nix;
pkgs = import nixpkgs (device.system // {
overlays = [overlay];
config = {
allowUnsupportedSystem = true; # mipsel
permittedInsecurePackages = [
"python-2.7.18.6" # kernel backports needs python <3
"python-2.7.18.7"
];
};
});
pkgs = import nixpkgs (
device.system
// {
overlays = [ overlay ];
config = {
allowUnsupportedSystem = true; # mipsel
permittedInsecurePackages = [
"python-2.7.18.6" # kernel backports needs python <3
"python-2.7.18.7"
];
};
}
);
eval = pkgs.lib.evalModules {
specialArgs = {
modulesPath = builtins.toString ./modules;
};
modules = [
{ _module.args = { inherit pkgs; inherit (pkgs) lim; }; }
./modules/hardware.nix
./modules/base.nix
./modules/busybox.nix
./modules/hostname.nix
./modules/kernel
device.module
liminix-config
./modules/s6
@ -41,7 +49,14 @@ let
borderVm = ((import <nixpkgs/nixos/lib/eval-config.nix>) {
system = builtins.currentSystem;
modules = [
({ ... } : { nixpkgs.overlays = [ overlay ]; })
{
nixpkgs.overlays = [
(final: prev: {
go-l2tp = final.callPackage ./pkgs/go-l2tp {};
tufted = final.callPackage ./pkgs/tufted {};
})
];
}
(import ./bordervm-configuration.nix)
borderVmConf
];
@ -72,6 +87,7 @@ in {
min-copy-closure
fennelrepl
lzma
lua
];
};
}

View File

@ -73,7 +73,7 @@
MTK_INFRACFG = "y";
MTK_PMIC_WRAP = "y";
MTK_EFUSE="y";
NVMEM_MTK_EFUSE="y";
# MTK_HSDMA="y";
MTK_SCPSYS="y";
MTK_SCPSYS_PM_DOMAINS="y";
@ -92,7 +92,6 @@
MEDIATEK_GE_PHY = "y";
# MEDIATEK_MT6577_AUXADC = "y";
# MEDIATEK_WATCHDOG = "y";
NET_MEDIATEK_SOC = "y";
NET_MEDIATEK_SOC_WED = "y";
NET_MEDIATEK_STAR_EMAC = "y"; # this enables REGMAP_MMIO
@ -214,7 +213,6 @@
networkInterfaces =
let
inherit (config.system.service.network) link;
inherit (config.system.service) bridge;
in rec {
wan = link.build { ifname = "wan"; };
lan1 = link.build { ifname = "lan1"; };

View File

@ -23,12 +23,17 @@
VIRTIO_BLK = "y";
VIRTIO_NET = "y";
};
conditionalConfig = {
WLAN= {
MAC80211_HWSIM = "m";
};
};
};
hardware =
let
mac80211 = pkgs.mac80211.override {
drivers = ["mac80211_hwsim"];
klibBuild = config.system.outputs.kernel.modulesupport;
mac80211 = pkgs.kmodloader.override {
inherit (config.system.outputs) kernel;
targets = ["mac80211_hwsim"];
};
in {
defaultOutput = "vmroot";

View File

@ -92,7 +92,6 @@
'';
};
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs.liminix.networking) interface;
in {
imports = [
../../modules/network
@ -125,8 +124,14 @@
networkInterfaces =
let inherit (config.system.service.network) link;
in {
lan = link.build { ifname = "eth0"; };
wan = link.build { ifname = "eth1"; };
lan = link.build {
ifname = "lan";
devpath = "/devices/platform/ahb/19000000.eth";
};
wan = link.build {
ifname = "wan";
devpath = "/devices/platform/ahb/1a000000.eth";
};
wlan = link.build {
ifname = "wlan0";
dependencies = [ mac80211 ];
@ -149,6 +154,7 @@
};
boot.tftp = {
loadAddress = lim.parseInt "0x00A00000";
appendDTB = true;
};
kernel = {
src = pkgs.pkgsBuildBuild.fetchurl {

View File

@ -45,7 +45,6 @@
module = { pkgs, config, lib, lim, ...}:
let
inherit (pkgs.liminix.networking) interface;
inherit (pkgs) openwrt;
mac80211 = pkgs.kmodloader.override {
targets = ["rt2800soc"];
@ -90,19 +89,6 @@
let
inherit (config.system.service.network) link;
inherit (config.system.service) vlan;
inherit (pkgs.liminix.services) oneshot;
swconfig = oneshot {
name = "swconfig";
up = ''
PATH=${pkgs.swconfig}/bin:$PATH
swconfig dev switch0 set reset
swconfig dev switch0 set enable_vlan 1
swconfig dev switch0 vlan 1 set ports '1 2 3 4 6t'
swconfig dev switch0 vlan 2 set ports '0 6t'
swconfig dev switch0 set apply
'';
down = "${pkgs.swconfig}/bin/swconfig dev switch0 set reset";
};
in rec {
eth = link.build { ifname = "eth0"; };
# lan and wan ports are both behind a switch on eth0
@ -110,13 +96,11 @@
ifname = "eth0.1";
primary = eth;
vid = "1";
dependencies = [swconfig eth];
};
wan = vlan.build {
ifname = "eth0.2";
primary = eth;
vid = "2";
dependencies = [swconfig eth];
};
wlan = link.build {
ifname = "wlan0";
@ -126,7 +110,8 @@
};
boot.tftp = {
loadAddress = lim.parseInt "0x00A00000";
};
appendDTB = true;
};
kernel = {
src = pkgs.fetchurl {
@ -136,6 +121,7 @@
};
extraPatchPhase = ''
${openwrt.applyPatches.ramips}
${openwrt.applyPatches.rt2x00}
'';
config = {

View File

@ -38,7 +38,6 @@
module = { pkgs, config, lib, lim, ...}:
let
inherit (pkgs.liminix.networking) interface;
inherit (pkgs.liminix.services) oneshot;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) openwrt;
@ -97,7 +96,7 @@
swconfig dev switch0 vlan 2 set ports '0 6t'
swconfig dev switch0 set apply
'';
down = "swconfig dev switch0 set reset";
down = "${pkgs.swconfig}/bin/swconfig dev switch0 set reset";
};
in rec {
eth = link.build { ifname = "eth0"; dependencies = [swconfig]; };
@ -122,6 +121,7 @@
# 20MB seems to give enough room to uncompress the kernel
# without anything getting trodden on. 10MB was too small
loadAddress = lim.parseInt "0x1400000";
appendDTB = true;
};
kernel = {

View File

@ -26,7 +26,7 @@
# this device is described by the "qemu" device
installer = "vmroot";
module = {pkgs, config, lim, ... }: {
module = { config, lim, ... }: {
imports = [
../../modules/arch/aarch64.nix
../families/qemu.nix

View File

@ -24,7 +24,7 @@
'';
installer = "vmroot";
module = {pkgs, config, lim, ... }: {
module = { config, lim, ... }: {
imports = [
../../modules/arch/arm.nix
../families/qemu.nix

View File

@ -36,7 +36,7 @@
in the Development manual.
'';
module = {pkgs, config, lib, lim, ... }: {
module = { config, lib, lim, ... }: {
imports = [
../../modules/arch/mipseb.nix
../families/qemu.nix

View File

@ -419,7 +419,6 @@
networkInterfaces =
let
inherit (config.system.service.network) link;
inherit (config.system.service) bridge;
in rec {
lan1 = link.build { ifname = "lan1"; };
lan2 = link.build { ifname = "lan2"; };

View File

@ -155,8 +155,6 @@
module = {pkgs, config, lib, lim, ... }:
let
openwrt = pkgs.openwrt;
inherit (lib) mkOption types;
inherit (pkgs.liminix.services) oneshot;
inherit (pkgs) liminix;
mtd_by_name_links = pkgs.liminix.services.oneshot rec {
@ -358,7 +356,6 @@
networkInterfaces =
let
inherit (config.system.service.network) link;
inherit (config.system.service) bridge;
in rec {
en70000 = link.build {
# in armada-38x.dtsi this is eth0.

View File

@ -103,8 +103,6 @@
module = { pkgs, config, lib, lim, ...}:
let
inherit (pkgs.liminix.networking) interface;
inherit (pkgs.liminix.services) oneshot;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) openwrt;

View File

@ -1,11 +1,9 @@
{ eval, lib, pkgs }:
let
inherit (lib) types;
conf = eval.config;
rootDir = builtins.toPath ./..;
stripAnyPrefixes = lib.flip (lib.fold lib.removePrefix)
["${rootDir}/"];
optToDoc = name: opt : {
stripAnyPrefixes = lib.flip (lib.fold lib.removePrefix) [ "${rootDir}/" ];
optToDoc = name: opt: {
inherit name;
description = opt.description or null;
default = opt.default or null;
@ -26,7 +24,6 @@ let
let x = lib.mapAttrsToList optToDoc sd.parameters; in x;
}
else
item // { declarations = map stripAnyPrefixes item.declarations; };
item // { declarations = map stripAnyPrefixes item.declarations; };
in
builtins.map spliceServiceDefn
(pkgs.lib.optionAttrSetToDocList eval.options)
builtins.map spliceServiceDefn (pkgs.lib.optionAttrSetToDocList eval.options)

View File

@ -1,24 +1,18 @@
with import <nixpkgs> {} ;
with import <nixpkgs> { };
let
inherit (builtins) stringLength readDir filter;
devices = filter (n: n != "families")
(lib.mapAttrsToList (n: t: n) (readDir ../devices));
texts = map (n:
let d = import ../devices/${n}/default.nix;
d' = {
description = "${n}\n${substring 0 (stringLength n) "********************************"}\n";
} // d;
installer =
if d ? description && d ? installer
then ''
The default installation route for this device is
:ref:`system-outputs-${d.installer}`
''
else "";
in d'.description)
devices;
devices = filter (n: n != "families") (lib.mapAttrsToList (n: t: n) (readDir ../devices));
texts = map (
n:
let
d = import ../devices/${n}/default.nix;
d' = {
description = "${n}\n${substring 0 (stringLength n) "********************************"}\n";
} // d;
in
d'.description
) devices;
in
writeText "hwdoc" ''
Supported hardware

View File

@ -11,15 +11,15 @@
...
}: let
secrets = import ./extneder-secrets.nix;
inherit (pkgs.liminix.services) oneshot longrun bundle target;
inherit (pkgs.liminix.services) oneshot longrun target;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) writeText dropbear ifwait serviceFns;
inherit (pkgs) writeText serviceFns;
svc = config.system.service;
in rec {
boot = {
tftp = {
serverip = "192.168.8.148";
ipaddr = "192.168.8.251";
serverip = "10.0.0.1";
ipaddr = "10.0.0.8";
};
};
@ -28,34 +28,12 @@ in rec {
../modules/network
../modules/vlan
../modules/ssh
../modules/usb.nix
../modules/watchdog
../modules/mount
];
hostname = "arhcive";
kernel = {
config = {
USB = "y";
USB_EHCI_HCD = "y";
USB_EHCI_HCD_PLATFORM = "y";
USB_OHCI_HCD = "y";
USB_OHCI_HCD_PLATFORM = "y";
USB_SUPPORT = "y";
USB_COMMON = "y";
USB_STORAGE = "y";
USB_STORAGE_DEBUG = "n";
USB_UAS = "y";
USB_ANNOUNCE_NEW_DEVICES = "y";
SCSI = "y";
BLK_DEV_SD = "y";
USB_PRINTER = "y";
MSDOS_PARTITION = "y";
EFI_PARTITION = "y";
EXT4_FS = "y";
EXT4_USE_FOR_EXT2 = "y";
FS_ENCRYPTION = "y";
};
};
services.dhcpc =
let iface = config.hardware.networkInterfaces.lan;
@ -105,7 +83,7 @@ in rec {
};
services.mount_external_disk = svc.mount.build {
device = "LABEL=backup-disk";
partlabel = "backup-disk";
mountpoint = "/srv";
fstype = "ext4";
};
@ -141,23 +119,37 @@ in rec {
secrets_file
services.mount_external_disk
config.hardware.networkInterfaces.lan
] ;
];
};
users.root = {
passwd = lib.mkForce secrets.root.passwd;
# openssh.authorizedKeys.keys = [
# (builtins.readFile "/home/dan/.ssh/id_rsa.pub")
# ];
openssh.authorizedKeys.keys = secrets.root.keys;
};
users.backup = {
uid=500; gid=500; gecos="Storage owner"; dir="/srv";
shell="/dev/null";
uid = 500;
gid = 500;
gecos = "Storage owner";
dir = "/srv";
shell = "/dev/null";
};
groups.backup = {
gid=500; usernames = ["backup"];
gid = 500;
usernames = [ "backup" ];
};
defaultProfile.packages = with pkgs; [e2fsprogs strace tcpdump ];
defaultProfile.packages = with pkgs; [
e2fsprogs
mtdutils
(levitate.override {
config = {
services = {
inherit (config.services) dhcpc sshd watchdog;
};
defaultProfile.packages = [ mtdutils ];
users.root.openssh.authorizedKeys.keys = secrets.root.keys;
};
})
];
}

View File

@ -5,9 +5,9 @@
# wherever the text "EDIT" appears - please consult the tutorial
# documentation for details.
{ config, pkgs, lib, ... } :
{ config, pkgs, ... }:
let
inherit (pkgs.liminix.services) bundle oneshot longrun;
inherit (pkgs.liminix.services) bundle oneshot;
inherit (pkgs) serviceFns;
# EDIT: you can pick your preferred RFC1918 address space
# for NATted connections, if you don't like this one.
@ -49,31 +49,40 @@ in rec {
country_code = "GB";
wpa_passphrase = "not a real wifi password";
hw_mode="g";
hw_mode = "g";
ieee80211n = 1;
auth_algs = 1; # 1=wpa2, 2=wep, 3=both
wpa = 2; # 1=wpa, 2=wpa2, 3=both
wpa = 2; # 1=wpa, 2=wpa2, 3=both
wpa_key_mgmt = "WPA-PSK";
wpa_pairwise = "TKIP CCMP"; # auth for wpa (may not need this?)
rsn_pairwise = "CCMP"; # auth for wpa2
wpa_pairwise = "TKIP CCMP"; # auth for wpa (may not need this?)
rsn_pairwise = "CCMP"; # auth for wpa2
wmm_enabled = 1;
};
};
services.int = svc.network.address.build {
interface = svc.bridge.primary.build { ifname = "int"; };
family = "inet"; address = "${ipv4LocalNet}.1"; prefixLength = 16;
family = "inet";
address = "${ipv4LocalNet}.1";
prefixLength = 16;
};
services.bridge = svc.bridge.members.build {
services.bridge = svc.bridge.members.build {
primary = services.int;
members = with config.hardware.networkInterfaces;
[ wlan lan ];
members = with config.hardware.networkInterfaces; [
wlan
lan
];
};
services.ntp = svc.ntp.build {
pools = { "pool.ntp.org" = ["iburst"]; };
makestep = { threshold = 1.0; limit = 3; };
pools = {
"pool.ntp.org" = [ "iburst" ];
};
makestep = {
threshold = 1.0;
limit = 3;
};
};
services.sshd = svc.ssh.build { };
@ -157,9 +166,7 @@ in rec {
interface = services.wan;
};
services.firewall = svc.firewall.build {
ruleset = import ./demo-firewall.nix;
};
services.firewall = svc.firewall.build { };
services.packet_forwarding = svc.network.forward.build { };
@ -196,7 +203,5 @@ in rec {
];
};
defaultProfile.packages = with pkgs; [
min-collect-garbage
];
defaultProfile.packages = with pkgs; [ min-collect-garbage ];
}

View File

@ -8,9 +8,11 @@
config,
pkgs,
lib,
modulesPath,
...
}: let
secrets = import ./extneder-secrets.nix;
svc = config.system.service;
in rec {
boot = {
tftp = {
@ -20,47 +22,13 @@ in rec {
};
imports = [
../modules/profiles/wap.nix
../modules/vlan
"${modulesPath}/profiles/wap.nix"
"${modulesPath}/vlan"
"${modulesPath}/ssh"
];
hostname = "extneder";
kernel = {
config = {
NETFILTER_XT_MATCH_CONNTRACK = "y";
IP6_NF_IPTABLES = "y"; # do we still need these
IP_NF_IPTABLES = "y"; # if using nftables directly
# these are copied from rotuer and need review.
# we're not running a firewall, so why do we need
# nftables config?
IP_NF_NAT = "y";
IP_NF_TARGET_MASQUERADE = "y";
NETFILTER = "y";
NETFILTER_ADVANCED = "y";
NETFILTER_XTABLES = "y";
NFT_COMPAT = "y";
NFT_CT = "y";
NFT_LOG = "y";
NFT_MASQ = "y";
NFT_NAT = "y";
NFT_REJECT = "y";
NFT_REJECT_INET = "y";
NF_CONNTRACK = "y";
NF_NAT = "y";
NF_NAT_MASQUERADE = "y";
NF_TABLES = "y";
NF_TABLES_INET = "y";
NF_TABLES_IPV4 = "y";
NF_TABLES_IPV6 = "y";
};
};
profile.wap = {
interfaces = with config.hardware.networkInterfaces; [
lan
@ -79,6 +47,7 @@ in rec {
};
};
services.sshd = svc.ssh.build {};
users.root.passwd = lib.mkForce secrets.root.passwd;
defaultProfile.packages = with pkgs; [nftables strace tcpdump swconfig];
}

View File

@ -1,6 +1,5 @@
{ config, pkgs, lib, ... } :
{ config, pkgs, ... } :
let
inherit (pkgs) serviceFns;
svc = config.system.service;
in rec {

View File

@ -1,6 +1,5 @@
{ config, pkgs, lib, ... } :
{ config, pkgs, ... } :
let
inherit (pkgs) serviceFns;
svc = config.system.service;
in rec {

141
examples/l2tp.nix Normal file
View File

@ -0,0 +1,141 @@
{
config,
pkgs,
lib,
...
}: let
secrets = import ./extneder-secrets.nix;
rsecrets = import ./rotuer-secrets.nix;
# https://support.aa.net.uk/Category:Incoming_L2TP says:
# "Please use the DNS name (l2tp.aa.net.uk) instead of hardcoding an
# IP address; IP addresses can and do change. If you have to use an
# IP, use 194.4.172.12, but do check the DNS for l2tp.aa.net.uk in
# case it changes."
# but (1) we don't want to use the wwan stick's dns as our main
# resolver: it's provided by some mobile ISP and they aren't
# necessarily the best at providing unfettered services without
# deciding to do something weird; (2) it's not simple to arrange
# that xl2tpd gets a different resolver than every other process;
# (3) there's no way to specify an lns address to xl2tpd at runtime
# except by rewriting its config file. So what we will do is lookup
# the lns hostname using the mobile ISP's dns server and then refuse
# to start l2tp unless the expected lns address is one of the
# addresses returned. I think this satisfies "do check the DNS"
lns = { hostname = "l2tp.aaisp.net.uk"; address = "194.4.172.12"; };
inherit (pkgs.liminix.services) oneshot target;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) serviceFns;
svc = config.system.service;
in rec {
boot = {
tftp = {
serverip = "10.0.0.1";
ipaddr = "10.0.0.8";
};
};
imports = [
../modules/cdc-ncm
../modules/network
../modules/vlan
../modules/ssh
../modules/usb.nix
../modules/watchdog
../modules/mount
../modules/ppp
];
hostname = "thing";
services.wwan = svc.wwan.build {
apn = "data.uk";
username = "user";
password = "one2one";
authType = "chap";
};
services.dhcpc = svc.network.dhcp.client.build {
interface = config.services.wwan;
dependencies = [ config.services.hostname ];
};
services.sshd = svc.ssh.build { };
services.resolvconf = oneshot rec {
dependencies = [ services.l2tp ];
name = "resolvconf";
up = ''
. ${serviceFns}
( in_outputs ${name}
for i in ns1 ns2 ; do
ns=$(output ${services.l2tp} $i)
echo "nameserver $ns" >> resolv.conf
done
)
'';
};
filesystem = dir {
etc = dir {
"resolv.conf" = symlink "${services.resolvconf}/.outputs/resolv.conf";
};
};
services.lns-address = let
ns = "$(output_word ${services.dhcpc} dns 1)";
route-to-bootstrap-nameserver = svc.network.route.build {
via = "$(output ${services.dhcpc} router)";
target = ns;
dependencies = [services.dhcpc];
};
in oneshot rec {
name = "resolve-l2tp-server";
dependencies = [ services.dhcpc route-to-bootstrap-nameserver ];
up = ''
(in_outputs ${name}
DNSCACHEIP="${ns}" ${pkgs.s6-dns}/bin/s6-dnsip4 ${lns.hostname} \
> addresses
)
'';
};
services.l2tp =
let
check-address = oneshot rec {
name = "check-lns-address";
up = ''
grep -Fx ${lns.address} $(output_path ${services.lns-address} addresses)
'';
dependencies = [ services.lns-address ];
};
route = svc.network.route.build {
via = "$(output ${services.dhcpc} router)";
target = lns.address;
dependencies = [services.dhcpc check-address];
};
in svc.l2tp.build {
lns = lns.address;
ppp-options = [
"debug" "+ipv6" "noauth"
"name" rsecrets.l2tp.name
"connect-delay" "5000"
"password" rsecrets.l2tp.password
];
dependencies = [config.services.lns-address route check-address];
};
services.defaultroute4 = svc.network.route.build {
via = "$(output ${services.l2tp} peer-address)";
target = "default";
dependencies = [services.l2tp];
};
# defaultProfile.packages = [ pkgs.go-l2tp ];
users.root = {
passwd = lib.mkForce secrets.root.passwd;
openssh.authorizedKeys.keys = secrets.root.keys;
};
}

View File

@ -1,7 +1,6 @@
{ config, pkgs, ... } :
let
inherit (pkgs.liminix.services) oneshot longrun bundle target;
inherit (pkgs) writeText;
inherit (pkgs.liminix.services) target;
svc = config.system.service;
secrets-1 = {
ssid = "Zyxel 2G (N)";

View File

@ -3,8 +3,8 @@ let
inherit (pkgs) serviceFns;
svc = config.system.service;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs.liminix.services) oneshot longrun bundle target;
some-util-linux = pkgs.runCommand "some-util-linux" {} ''
inherit (pkgs.liminix.services) oneshot target;
some-util-linux = pkgs.runCommand "some-util-linux" { } ''
mkdir -p $out/bin
cd ${pkgs.util-linux-small}/bin
cp fdisk sfdisk mkswap $out/bin
@ -53,7 +53,7 @@ in rec {
services.defaultroute4 = svc.network.route.build {
via = "$(output ${services.dhcpc} router)";
target = "default";
dependencies = [services.dhcpc];
dependencies = [ services.dhcpc ];
};
services.resolvconf = oneshot rec {

View File

@ -8,12 +8,10 @@
root = {
# mkpasswd -m sha512crypt
passwd = "$6$6pt0mpbgcB7kC2RJ$kSBoCYGyi1.qxt7dqmexLj1l8E6oTZJZmfGyJSsMYMW.jlsETxdgQSdv6ptOYDM7DHAwf6vLG0pz3UD31XBfC1";
openssh.authorizedKeys.keys = [
];
openssh.authorizedKeys.keys = [ ];
};
lan = {
prefix = "10.8.0";
};
}

View File

@ -6,23 +6,16 @@
# problems.
{ config, pkgs, lib, ... } :
{ config, pkgs, lib, modulesPath, ... } :
let
secrets = {
domainName = "fake.liminix.org";
firewallRules = {};
firewallRules = { };
} // (import ./rotuer-secrets.nix);
inherit (pkgs.liminix.services) oneshot longrun bundle;
inherit (pkgs) serviceFns;
svc = config.system.service;
wirelessConfig = {
wirelessConfig = {
country_code = "GB";
inherit (secrets) wpa_passphrase;
auth_algs = 1; # 1=wpa2, 2=wep, 3=both
wpa = 2; # 1=wpa, 2=wpa2, 3=both
wpa_key_mgmt = "WPA-PSK";
wpa_pairwise = "TKIP CCMP"; # auth for wpa (may not need this?)
rsn_pairwise = "CCMP"; # auth for wpa2
wmm_enabled = 1;
};
@ -36,65 +29,62 @@ in rec {
};
imports = [
../modules/wlan.nix
../modules/network
../modules/ppp
../modules/dnsmasq
../modules/dhcp6c
../modules/firewall
../modules/hostapd
../modules/bridge
../modules/ntp
../modules/schnapps
../modules/ssh
../modules/outputs/btrfs.nix
../modules/outputs/extlinux.nix
"${modulesPath}/profiles/gateway.nix"
"${modulesPath}/schnapps"
"${modulesPath}/outputs/btrfs.nix"
"${modulesPath}/outputs/extlinux.nix"
];
hostname = "rotuer";
rootfsType = "btrfs";
rootOptions = "subvol=@";
boot.loader.extlinux.enable = true;
services.hostap = svc.hostapd.build {
interface = config.hardware.networkInterfaces.wlan;
params = {
ssid = secrets.ssid;
hw_mode="g";
channel = "2";
ieee80211n = 1;
} // wirelessConfig;
};
services.hostap5 = svc.hostapd.build {
interface = config.hardware.networkInterfaces.wlan5;
params = rec {
ssid = "${secrets.ssid}5";
hw_mode="a";
channel = 36;
ht_capab = "[HT40+]";
vht_oper_chwidth = 1;
vht_oper_centr_freq_seg0_idx = channel + 6;
ieee80211n = 1;
ieee80211ac = 1;
} // wirelessConfig;
};
services.int = svc.network.address.build {
interface = svc.bridge.primary.build { ifname = "int"; };
family = "inet"; address ="${secrets.lan.prefix}.1"; prefixLength = 24;
};
services.bridge = svc.bridge.members.build {
primary = services.int;
members = with config.hardware.networkInterfaces;
[ wlan
wlan5
lan0
lan1
lan2
lan3
lan4
];
profile.gateway = {
lan = {
interfaces = with config.hardware.networkInterfaces;
[
wlan wlan5
lan0 lan1 lan2 lan3 lan4
];
inherit (secrets.lan) prefix;
address = {
family = "inet"; address ="${secrets.lan.prefix}.1"; prefixLength = 24;
};
dhcp = {
start = 10;
end = 240;
hosts = { } // lib.optionalAttrs (builtins.pathExists ./static-leases.nix) (import ./static-leases.nix);
localDomain = "lan";
};
};
wan = {
interface = config.hardware.networkInterfaces.wan;
username = secrets.l2tp.name;
password = secrets.l2tp.password;
dhcp6.enable = true;
};
firewall = {
enable = true;
rules = secrets.firewallRules;
};
wireless.networks = {
"${secrets.ssid}" = {
interface = config.hardware.networkInterfaces.wlan;
hw_mode = "g";
channel = "2";
ieee80211n = 1;
} // wirelessConfig;
"${secrets.ssid}5" = rec {
interface = config.hardware.networkInterfaces.wlan5;
hw_mode = "a";
channel = 36;
ht_capab = "[HT40+]";
vht_oper_chwidth = 1;
vht_oper_centr_freq_seg0_idx = channel + 6;
ieee80211n = 1;
ieee80211ac = 1;
} // wirelessConfig;
};
};
services.ntp = svc.ntp.build {
@ -106,95 +96,6 @@ in rec {
users.root = secrets.root;
services.dns =
let interface = services.int;
in svc.dnsmasq.build {
resolvconf = services.resolvconf;
inherit interface;
ranges = [
"${secrets.lan.prefix}.10,${secrets.lan.prefix}.240"
# ra-stateless: 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.
"::,constructor:$(output ${interface} ifname),ra-stateless"
];
# You can add static addresses for the DHCP server here. I'm
# not putting my actual MAC addresses in a public git repo ...
hosts = { } // lib.optionalAttrs (builtins.pathExists ./static-leases.nix) (import ./static-leases.nix);
upstreams = [ "/${secrets.domainName}/" ];
domain = secrets.domainName;
};
services.wan = svc.pppoe.build {
interface = config.hardware.networkInterfaces.wan;
ppp-options = [
"debug" "+ipv6" "noauth"
"name" secrets.l2tp.name
"password" secrets.l2tp.password
];
};
services.resolvconf = oneshot rec {
dependencies = [ services.wan ];
name = "resolvconf";
up = ''
. ${serviceFns}
( in_outputs ${name}
echo "nameserver $(output ${services.wan} ns1)" > resolv.conf
echo "nameserver $(output ${services.wan} ns2)" >> resolv.conf
chmod 0444 resolv.conf
)
'';
};
filesystem =
let inherit (pkgs.pseudofile) dir symlink;
in dir {
etc = dir {
"resolv.conf" = symlink "${services.resolvconf}/.outputs/resolv.conf";
};
};
services.defaultroute4 = svc.network.route.build {
via = "$(output ${services.wan} address)";
target = "default";
dependencies = [ services.wan ];
};
services.defaultroute6 = svc.network.route.build {
via = "$(output ${services.wan} ipv6-peer-address)";
target = "default";
interface = services.wan;
};
services.firewall = svc.firewall.build {
ruleset =
let defaults = import ./demo-firewall.nix;
in lib.recursiveUpdate defaults secrets.firewallRules;
};
services.packet_forwarding = svc.network.forward.build { };
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; [
min-collect-garbage
nftables

View File

@ -1,6 +1,5 @@
{ config, pkgs, lib, lim, ... } :
{ config, pkgs, lim, ... } :
let
inherit (pkgs) serviceFns;
svc = config.system.service;
in rec {

View File

@ -9,29 +9,29 @@
./busybox.nix
./dhcp6c
./dnsmasq
./outputs/ext4fs.nix
./firewall
./hardware.nix
./hostapd
./hostname.nix
./outputs/initramfs.nix
./outputs/jffs2.nix
./kernel
./outputs/kexecboot.nix
./mdevd.nix
./mount
./network
./ntp
./outputs.nix
./outputs/vmroot.nix
./outputs/ubimage.nix
./outputs/ext4fs.nix
./outputs/initramfs.nix
./outputs/jffs2.nix
./outputs/kexecboot.nix
./outputs/mtdimage.nix
./outputs/tftpboot.nix
./outputs/ubifs.nix
./outputs/ubimage.nix
./outputs/vmroot.nix
./ppp
./ramdisk.nix
./squashfs.nix
./ssh
./outputs/tftpboot.nix
./outputs/ubifs.nix
./ubinize.nix
./users.nix
./vlan
./watchdog

View File

@ -1,4 +1,4 @@
{ lib, lim, pkgs, config, ...}:
{ lim, pkgs, config, ...}:
{
config = {
kernel.config = {

View File

@ -1,4 +1,4 @@
{ lib, lim, pkgs, config, ...}:
{ lim, pkgs, config, ...}:
{
config = {
kernel.config = {

View File

@ -1,4 +1,4 @@
{ lib, pkgs, config, lim, ...}:
{ config, lim, ...}:
{
config = {
kernel.config = {

View File

@ -1,4 +1,4 @@
{ lib, pkgs, config, ...}:
{ pkgs, config, ...}:
{
imports = [ ./mips.nix ];
config = {

View File

@ -1,4 +1,4 @@
{ lib, pkgs, config, ...}:
{ config, ...}:
{
imports = [ ./mips.nix ];
config = {

View File

@ -4,17 +4,12 @@
{ lib, pkgs, config, ...}:
let
inherit (lib) mkEnableOption mkOption types isDerivation hasAttr ;
inherit (lib) mkOption types;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs.liminix.networking) address interface;
inherit (pkgs.liminix.services) bundle;
type_service = pkgs.liminix.lib.types.service;
in {
imports = [
./kernel # kernel is a separate module for doc purposes
];
options = {
defaultProfile = {
packages = mkOption {
@ -29,6 +24,10 @@ in {
services = mkOption {
type = types.attrsOf type_service;
};
system.callService = mkOption {
type = types.functionTo (types.functionTo types.anything);
};
filesystem = mkOption {
type = types.anything;
description = ''
@ -37,7 +36,7 @@ in {
'';
# internal = true; # probably a good case to make this internal
};
rootfsType = mkOption {
rootfsType = mkOption {
default = "squashfs";
type = types.enum [
"btrfs"
@ -47,7 +46,7 @@ in {
"ubifs"
];
};
rootOptions = mkOption {
rootOptions = mkOption {
type = types.nullOr types.str;
default = null;
};
@ -55,20 +54,29 @@ in {
boot = {
commandLine = mkOption {
type = types.listOf types.nonEmptyStr;
default = [];
default = [ ];
description = "Kernel command line";
};
commandLineDtbNode = mkOption {
type = types.enum [ "bootargs" "bootargs-override" ];
type = types.enum [
"bootargs"
"bootargs-override"
];
default = "bootargs";
description = "Kernel command line's devicetree node";
};
imageType = mkOption {
type = types.enum [ "primary" "secondary" ];
type = types.enum [
"primary"
"secondary"
];
default = "primary";
};
imageFormat = mkOption {
type = types.enum ["fit" "uimage"];
type = types.enum [
"fit"
"uimage"
];
default = "uimage";
};
tftp = {
@ -84,7 +92,7 @@ in {
};
# These names match the uboot environment variables. I reserve
# the right to change them if I think of better ones.
ipaddr = mkOption {
ipaddr = mkOption {
type = types.str;
description = ''
Our IP address to use when creating scripts to
@ -111,6 +119,29 @@ in {
"fw_devlink=off"
] ++ lib.optional (config.rootOptions != null) "rootflags=${config.rootOptions}";
system.callService = path : parameters :
let
typeChecked = caller: type: value:
let
inherit (lib) types mergeDefinitions;
defs = [{ file = caller; inherit value; }];
type' = types.submodule { options = type; };
in (mergeDefinitions [] type' defs).mergedValue;
cp = lib.callPackageWith(pkgs // { svc = config.system.service; });
pkg = cp path {};
checkTypes = t : p : typeChecked (builtins.toString path) t p;
in {
inherit parameters;
build = { dependencies ? [], ... } @ args :
let
s = pkg (checkTypes parameters
(builtins.removeAttrs args ["dependencies"]));
in s.overrideAttrs (o: {
dependencies = dependencies ++ o.dependencies;
buildInputs = dependencies ++ o.buildInputs;
});
};
users.root = {
uid = 0; gid= 0; gecos = "Root of all evaluation";
dir = "/home/root/";

View File

@ -10,10 +10,11 @@
{ lib, pkgs, config, ...}:
let
inherit (lib) mkOption types;
inherit (pkgs.liminix.services) oneshot;
inherit (pkgs) liminix;
in
{
imports = [ ../ifwait ];
options = {
system.service.bridge = {
primary = mkOption { type = liminix.lib.types.serviceDefn; };
@ -27,7 +28,7 @@ in
description = "bridge interface name to create";
};
};
members = liminix.callService ./members.nix {
members = config.system.callService ./members.nix {
primary = mkOption {
type = liminix.lib.types.interface;
description = "primary bridge interface";
@ -47,5 +48,5 @@ in
# a better way to test for the existence of vlan config:
# maybe the module should set an `enabled` attribute?
BRIDGE_VLAN_FILTERING = "y";
};
};
}

View File

@ -1,23 +1,28 @@
{
liminix
, ifwait
, lib
, svc
}:
{ members, primary } :
let
inherit (liminix.networking) interface;
inherit (liminix.services) bundle oneshot;
inherit (lib) mkOption types;
addif = member :
oneshot {
name = "${primary.name}.member.${member.name}";
up = ''
dev=$(output ${member} ifname)
${ifwait}/bin/ifwait $dev running && ip link set dev $dev master $(output ${primary} ifname)
'';
down = "ip link set dev $(output ${member} ifname) nomaster";
# how do we get sight of services from here? maybe we need to
# implement ifwait as a regualr derivation instead of a
# servicedefinition
svc.ifwait.build {
state = "running";
interface = member;
dependencies = [ primary member ];
service = oneshot {
name = "${primary.name}.member.${member.name}";
up = ''
ip link set dev $(output ${member} ifname) master $(output ${primary} ifname)
'';
down = "ip link set dev $(output ${member} ifname) nomaster";
};
};
in bundle {
name = "${primary.name}.members";

View File

@ -1,12 +1,10 @@
{
liminix
, ifwait
, lib
}:
{ ifname } :
let
inherit (liminix.services) bundle oneshot;
inherit (lib) mkOption types;
inherit (liminix.services) oneshot;
in oneshot rec {
name = "${ifname}.link";
up = ''

View File

@ -8,7 +8,7 @@
{ lib, pkgs, config, ...}:
let
inherit (lib) mkOption mkEnableOption types mapAttrsToList;
inherit (lib) mkOption types mapAttrsToList;
inherit (pkgs.pseudofile) dir symlink;
inherit (lib.strings) toUpper;
@ -85,10 +85,13 @@ in {
};
};
filesystem = dir {
bin = dir ({
busybox = symlink "${busybox}/bin/busybox";
sh = symlink "${busybox}/bin/busybox";
} // makeLinks);
bin = dir (
{
busybox = symlink "${busybox}/bin/busybox";
sh = symlink "${busybox}/bin/busybox";
}
// makeLinks
);
};
};
}

View File

@ -0,0 +1,31 @@
{ config, pkgs, lib, ... }:
let
inherit (pkgs) liminix;
inherit (lib) mkOption types;
in {
imports = [
../service-trigger
];
options = {
system.service.wwan = mkOption {
type = liminix.lib.types.serviceDefn;
};
};
config = {
kernel.config = {
USB_NET_HUAWEI_CDC_NCM = "y";
USB_USBNET = "y";
USB_SERIAL = "y";
USB_SERIAL_OPTION = "y";
};
# https://www.0xf8.org/2017/01/flashing-a-huawei-e3372h-4g-lte-stick-from-hilink-to-stick-mode/
system.service.wwan = config.system.callService ./wwan.nix {
apn = mkOption { type = types.str; };
username = mkOption { type = types.str; };
password = mkOption { type = types.str; };
authType = mkOption { type = types.enum [ "pap" "chap" ]; };
};
};
}

67
modules/cdc-ncm/wwan.nix Normal file
View File

@ -0,0 +1,67 @@
{
liminix
, usb-modeswitch
, ppp
, lib
, svc
, uevent-watch
}:
{ apn, username, password, authType }:
let
inherit (liminix.services) oneshot;
authTypeNum = if authType == "pap" then "1" else "2";
chat = lib.escapeShellArgs [
# Your usb modem thing might present as a tty that you run PPP
# over, or as a network device ("ndis" or "ncm"). The latter
# kind is to be preferred, at least in principle, because it's
# faster. This initialization sequence works for the Huawei
# E3372, and took much swearing: the error messages are *awful*
"" "AT"
"OK" "ATZ"
# create PDP context
"OK" "AT+CGDCONT=1,\"IP\",\"${apn}\""
# activate PDP context
"OK" "AT+CGACT=1,1"
# setup username and password per requirements of sim provider.
# (caret is special to chat, so needs escaping in AT commands)
"OK" "AT\\^AUTHDATA=1,${authTypeNum},\"\",\"${password}\",\"${username}\""
# start the thing (I am choosing to read this as "NDIS DialUP")
"OK" "AT\\^NDISDUP=1,1"
"OK"
];
modeswitch = oneshot rec {
name = "modem-modeswitch";
controller = (svc.uevent-rule.build {
serviceName = name;
terms = { devtype = "usb_device"; product = "12d1/14fe/102"; };
});
up = ''
${usb-modeswitch}/bin/usb_modeswitch -v 12d1 -p 14fe --huawei-new-mode
'';
};
atz = oneshot rec {
name = "modem-atz";
dependencies = [ modeswitch ];
controller = (svc.uevent-rule.build {
serviceName = name;
terms = {
subsystem = "tty";
attrs = {
idVendor = "12d1";
idProduct = "1506";
};
};
symlink = "/dev/modem";
});
up = ''
ls -l /dev/modem
test -L /dev/modem || exit 1
${ppp}/bin/chat -s -v ${chat} 0<>/dev/modem 1>&0
'';
down = "${ppp}/bin/chat -v '' ATZ OK 0<>/dev/modem 1>&0";
};
in svc.network.link.build {
ifname = "wwan0";
dependencies = [ atz ];
}

View File

@ -2,9 +2,9 @@
writeFennel
, linotify
, anoia
, lua
, lualinux
}:
writeFennel "acquire-delegated-prefix" {
packages = [ linotify anoia lua.pkgs.luafilesystem ];
packages = [ linotify anoia lualinux ];
mainFunction = "run";
} ./acquire-delegated-prefix.fnl

View File

@ -1,7 +1,8 @@
(local subject (require :acquire-wan-address))
(local { : view } (require :fennel))
(import-macros { : expect= } :anoia.assert)
(local { : merge : dup } (require :anoia))
;; nix-shell --run "cd modules/dhcp6c && fennelrepl acquire-wan-address-test.fnl"
(local a1
{
@ -47,19 +48,6 @@
}
)
(macro expect [assertion]
(let [msg (.. "expectation failed: " (view assertion))]
`(when (not ,assertion)
(assert false ,msg))))
(macro expect= [actual expected]
`(let [ve# (view ,expected)
va# (view ,actual)]
(when (not (= ve# va#))
(assert false
(.. "\nexpected " ve# "\ngot " va#)
))))
(fn first-address []
(let [deleted
(subject.deletions

View File

@ -2,9 +2,10 @@
writeFennel
, linotify
, anoia
, lualinux
, lua
}:
writeFennel "acquire-wan-address" {
packages = [ linotify anoia lua.pkgs.luafilesystem ];
packages = [ linotify anoia lualinux ];
mainFunction = "run";
} ./acquire-wan-address.fnl

View File

@ -1,12 +1,10 @@
{
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 {

View File

@ -1,13 +1,11 @@
{
liminix
, lib
, odhcp6c
, odhcp-script
}:
{ interface } :
let
inherit (liminix.services) longrun;
inherit (lib) mkOption types;
name = "dhcp6c.${interface.name}";
in longrun {
inherit name;

View File

@ -12,7 +12,6 @@
{ lib, pkgs, config, ...}:
let
inherit (lib) mkOption types;
inherit (pkgs.liminix.services) oneshot;
inherit (pkgs) liminix;
in
{

View File

@ -1,12 +1,10 @@
{
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 {

View File

@ -18,7 +18,7 @@ let
name = "${interface.name}.dnsmasq";
inherit (liminix.services) longrun;
inherit (lib) concatStrings concatStringsSep mapAttrsToList;
hostOpt = name : { mac, v4, v6, leasetime } @ attrs:
hostOpt = name : { mac, v4, v6, leasetime }:
let v6s = concatStrings (map (a : ",[${a}]") v6);
in "--dhcp-host=${mac},${v4}${v6s},${name},${builtins.toString leasetime}";
in

View File

@ -8,7 +8,6 @@
let
inherit (lib) mkOption types;
inherit (pkgs) liminix;
inherit (pkgs.liminix.services) oneshot;
kmodules = pkgs.kmodloader.override {
inherit (config.system.outputs) kernel;
@ -56,8 +55,14 @@ in
config = {
system.service.firewall =
let svc = liminix.callService ./service.nix {
ruleset = mkOption {
extraRules = mkOption {
type = types.attrsOf types.attrs;
description = "firewall ruleset";
default = {};
};
rules = mkOption {
type = types.attrsOf types.attrs; # we could usefully tighten this a bit :-)
default = import ./default-rules.nix;
description = "firewall ruleset";
};
};
@ -68,13 +73,17 @@ in
};
in svc.build args' ;
};
programs.busybox.applets = [
"insmod" "rmmod"
];
kernel.config = {
NETFILTER = "y";
NETFILTER_ADVANCED = "y";
NETFILTER_NETLINK = "m";
NF_CONNTRACK = "m";
NETLINK_DIAG = "y";
IP6_NF_IPTABLES= "m";
IP_NF_IPTABLES = "m";
IP_NF_NAT = "m";

View File

@ -4,12 +4,10 @@
, firewallgen
, nftables
}:
{ ruleset }:
{ rules, extraRules }:
let
inherit (liminix.services) oneshot;
inherit (liminix.lib) typeChecked;
inherit (lib) mkOption types;
script = firewallgen "firewall.nft" ruleset;
script = firewallgen "firewall.nft" (lib.recursiveUpdate rules extraRules);
in oneshot {
name = "firewall";
up = script;

View File

@ -5,14 +5,13 @@
## you want to run on it, and would usually be set in the "device" file:
## :file:`devices/manuf-model/default.nix`
{ lib, pkgs, config, ...}:
{ lib, ... }:
let
inherit (lib) mkEnableOption mkOption types isDerivation hasAttr ;
in {
inherit (lib) mkOption types;
in
{
options = {
boot = {
};
boot = { };
hardware = {
dts = {
src = mkOption {
@ -26,7 +25,7 @@ in {
'';
};
includes = mkOption {
default = [];
default = [ ];
description = "List of directories to search for DTS includes (.dtsi files)";
type = types.listOf types.path;
};

View File

@ -8,8 +8,6 @@
let
inherit (liminix.services) longrun;
inherit (lib) concatStringsSep mapAttrsToList;
inherit (liminix.lib) typeChecked;
inherit (lib) mkOption types;
# This is not a friendly interface to configuring a wireless AP: it
# just passes everything straight through to the hostapd config.

View File

@ -0,0 +1,18 @@
{ config, pkgs, lib, ... } :
let
inherit (pkgs) liminix;
inherit (lib) mkOption types;
in {
options.system.service.ifwait =
mkOption { type = liminix.lib.types.serviceDefn; };
config.system.service.ifwait = config.system.callService ./ifwait.nix {
state = mkOption { type = types.str; };
interface = mkOption {
type = liminix.lib.types.interface;
};
service = mkOption {
type = liminix.lib.types.service;
};
};
}

16
modules/ifwait/ifwait.nix Normal file
View File

@ -0,0 +1,16 @@
{ ifwait, liminix } :
{
state
, interface
, service
}:
let
inherit (liminix.services) longrun;
in longrun {
name = "ifwait.${interface.name}";
buildInputs = [ service ];
restart-on-upgrade = true;
run = ''
${ifwait}/bin/ifwait -s ${service.name} $(output ${interface} ifname) ${state}
'';
}

View File

@ -5,14 +5,9 @@
{ lib, pkgs, config, ...}:
let
inherit (lib) mkEnableOption mkOption types isDerivation hasAttr ;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs.liminix.networking) address interface;
inherit (pkgs.liminix.services) bundle;
inherit (lib) mkOption types ;
inherit (pkgs) liminix;
type_service = pkgs.liminix.lib.types.service;
mergeConditionals = conf : conditions :
# for each key in conditions, if it is present in conf
# then merge the associated value into conf

30
modules/mdevd.nix Normal file
View File

@ -0,0 +1,30 @@
{ config, pkgs, ...} :
let inherit (pkgs.liminix.services) oneshot longrun;
in {
config = {
services = rec {
mdevd = longrun {
name = "mdevd";
notification-fd = 3;
run = "${pkgs.mdevd}/bin/mdevd -D 3 -b 200000 -O4";
};
devout = longrun {
name = "devout";
notification-fd = 10;
run = "exec ${pkgs.devout}/bin/devout /run/devout.sock 4";
};
coldplug = oneshot {
name = "coldplug";
# would love to know what mdevd-coldplug/udevadm trigger does
# that this doesn't
up = ''
for i in $(find /sys -name uevent); do ( echo change > $i ) ; done
'';
dependencies = [
devout
mdevd
];
};
};
};
}

View File

@ -7,11 +7,6 @@
let
inherit (lib) mkOption types;
inherit (pkgs) liminix;
mkBoolOption = description : mkOption {
type = types.bool;
inherit description;
default = true;
};
in {
options = {
@ -19,28 +14,39 @@ in {
type = liminix.lib.types.serviceDefn;
};
};
config.system.service = {
mount = liminix.callService ./service.nix {
device = mkOption {
type = types.str;
example = "/dev/sda1";
};
mountpoint = mkOption {
type = types.str;
example = "/mnt/media";
};
options = mkOption {
type = types.listOf types.str;
default = [];
example = ["noatime" "ro" "sync"];
};
fstype = mkOption {
type = types.str;
default = "auto";
example = "vfat";
};
imports = [ ../mdevd.nix ../service-trigger ];
config.system.service.mount =
let svc = config.system.callService ./service.nix {
partlabel = mkOption {
type = types.str;
example = "my-usb-stick";
};
mountpoint = mkOption {
type = types.str;
example = "/mnt/media";
};
options = mkOption {
type = types.listOf types.str;
default = [];
example = ["noatime" "ro" "sync"];
};
fstype = mkOption {
type = types.str;
default = "auto";
example = "vfat";
};
};
in svc // {
build = args:
let args' = args // {
dependencies = (args.dependencies or []) ++ [
config.services.mdevd
config.services.devout
];
};
in svc.build args' ;
};
};
config.programs.busybox = {
applets = ["blkid" "findfs"];
options = {

View File

@ -1,18 +1,27 @@
{
liminix
, lib
, svc
}:
{ device, mountpoint, options, fstype }:
{ partlabel, mountpoint, options, fstype }:
let
inherit (liminix.services) oneshot;
device = "/dev/disk/by-partlabel/${partlabel}";
name = "mount.${lib.strings.sanitizeDerivationName (lib.escapeURL mountpoint)}";
options_string =
if options == [] then "" else "-o ${lib.concatStringsSep "," options}";
controller = svc.uevent-rule.build {
serviceName = name;
symlink = device;
terms = {
partname = partlabel;
devtype = "partition";
};
};
in oneshot {
name = "mount.${lib.escapeURL mountpoint}";
up = ''
while ! findfs ${device}; do
echo waiting for device ${device}
sleep 1
done
mount -t ${fstype} -o ${lib.concatStringsSep "," options} ${device} ${mountpoint}
'';
inherit name;
timeout-up = 3600;
up = "mount -t ${fstype} ${options_string} ${device} ${mountpoint}";
down = "umount ${mountpoint}";
inherit controller;
}

View File

@ -1,6 +1,5 @@
{
liminix
, ifwait
, serviceFns
, lib
}:

View File

@ -17,7 +17,7 @@ let
ip address replace $ip/$mask dev $interface
(in_outputs ${name}
for i in lease mask ip router siaddr dns serverid subnet opt53 interface ; do
printenv $i > $i
(printenv $i || true) > $i
done)
}
case $action in
@ -40,7 +40,7 @@ let
'';
in longrun {
inherit name;
run = "/bin/udhcpc -f -i $(output ${interface} ifname) -x hostname:$(cat /proc/sys/kernel/hostname) -s ${script}";
run = "exec /bin/udhcpc -f -i $(output ${interface} ifname) -x hostname:$(cat /proc/sys/kernel/hostname) -s ${script}";
notification-fd = 10;
dependencies = [ interface ];
}

View File

@ -1,7 +1,5 @@
{
liminix
, ifwait
, serviceFns
, lib
}:
{ enableIPv4, enableIPv6 }:

View File

@ -1,7 +1,5 @@
{
liminix
, ifwait
, serviceFns
, lib
}:
{
@ -11,8 +9,7 @@
# if devpath is supplied, we rename the interface at that
# path to have the specified name.
let
inherit (liminix.services) longrun oneshot;
inherit (lib) concatStringsSep;
inherit (liminix.services) oneshot;
name = "${ifname}.link";
rename = if devpath != null
then ''

View File

@ -1,15 +1,15 @@
{
liminix
, ifwait
, serviceFns
, lib
}:
{ target, via, interface ? null, metric }:
let
inherit (liminix.services) oneshot;
with_dev = if interface != null then "dev $(output ${interface} ifname)" else "";
target_hash = builtins.substring 0 12 (builtins.hashString "sha256" target);
via_hash = builtins.substring 0 12 (builtins.hashString "sha256" via);
in oneshot {
name = "route-${target}-${builtins.substring 0 12 (builtins.hashString "sha256" "${via}-${if interface!=null then interface.name else ""}")}";
name = "route-${target_hash}-${builtins.substring 0 12 (builtins.hashString "sha256" "${via_hash}-${if interface!=null then interface.name else ""}")}";
up = ''
ip route add ${target} via ${via} metric ${toString metric} ${with_dev}
'';

View File

@ -1,7 +1,6 @@
{
liminix
, chrony
, serviceFns
, lib
, writeText
}:
@ -9,10 +8,6 @@ params:
let
inherit (liminix.services) longrun;
inherit (lib) concatStringsSep mapAttrsToList;
inherit (liminix.lib) typeChecked;
inherit (lib) mkOption types;
serverOpts = types.listOf types.str;
configFile = p:
(mapAttrsToList (name: opts: "server ${name} ${concatStringsSep "" opts}")
p.servers)

View File

@ -1,12 +1,12 @@
{
config
, pkgs
, lib
, ...
config,
pkgs,
lib,
...
}:
let
inherit (lib) mkOption types concatStringsSep;
inherit (pkgs) liminix callPackage writeText;
inherit (pkgs) liminix writeText;
o = config.system.outputs;
in
{
@ -22,7 +22,7 @@ in
# but only part of one.
kernel = mkOption {
type = types.package;
internal = true;
internal = true;
description = ''
kernel
******
@ -42,7 +42,7 @@ in
};
dtb = mkOption {
type = types.package;
internal = true;
internal = true;
description = ''
dtb
***
@ -52,7 +52,7 @@ in
};
uimage = mkOption {
type = types.package;
internal = true;
internal = true;
description = ''
uimage
******
@ -68,7 +68,7 @@ in
};
manifest = mkOption {
type = types.package;
internal = true;
internal = true;
description = ''
Debugging aid. JSON rendition of config.filesystem, on
which can run "nix-store -q --tree" on it and find

View File

@ -5,7 +5,7 @@
, ...
}:
let
inherit (lib) mkIf mkOption types;
inherit (lib) mkIf;
o = config.system.outputs;
in
{

View File

@ -5,7 +5,7 @@
, ...
}:
let
inherit (lib) mkIf mkOption types;
inherit (lib) mkIf;
o = config.system.outputs;
in
{

View File

@ -6,7 +6,7 @@
}:
let
inherit (lib) mkEnableOption mkOption mkIf types;
inherit (pkgs) runCommand callPackage writeText;
inherit (pkgs) runCommand;
in
{
options = {

View File

@ -5,7 +5,7 @@
, ...
}:
let
inherit (lib) mkIf mkOption types;
inherit (lib) mkIf;
o = config.system.outputs;
in
{

View File

@ -5,7 +5,7 @@
, ...
}:
let
inherit (lib) mkOption mkForce types concatStringsSep;
inherit (lib) mkOption types concatStringsSep;
in {
imports = [ ../ramdisk.nix ];
options.system.outputs = {
@ -42,8 +42,7 @@ in {
boot-sh =
let
inherit (pkgs.lib.trivial) toHexString;
inherit (config.system.outputs) rootfs kernel;
inherit (config.system.outputs) rootfs;
cmdline = concatStringsSep " " config.boot.commandLine;
in
pkgs.buildPackages.runCommand "boot.sh.sh" {

View File

@ -5,7 +5,7 @@
, ...
}:
let
inherit (lib) mkOption types concatStringsSep;
inherit (lib) mkOption types;
o = config.system.outputs;
phram_address = lib.toHexString (config.hardware.ram.startAddress + 256 * 1024 * 1024);
in {

View File

@ -58,7 +58,6 @@ in {
system.outputs = rec {
tftpboot =
let
inherit (pkgs.lib.trivial) toHexString;
o = config.system.outputs;
image = let choices = {
uimage = o.uimage;
@ -122,7 +121,7 @@ in {
fdtput -p -t lx dtb /reserved-memory/$node reg $ac_prefix $(hex $rootfsStart) $sz_prefix $(hex $rootfsSize)
cmd="liminix ${cmdline} mtdparts=phram0:''${rootfsSize}(rootfs) phram.phram=phram0,''${rootfsStart},''${rootfsSize},${toString config.hardware.flash.eraseBlockSize} root=/dev/mtdblock0";
fdtput -t s dtb /chosen bootargs "$cmd"
fdtput -t s dtb /chosen ${config.boot.commandLineDtbNode} "$cmd"
dtbSize=$(binsize ./dtb )

View File

@ -5,7 +5,7 @@
, ...
}:
let
inherit (lib) mkOption types concatStringsSep;
inherit (lib) mkOption types;
o = config.system.outputs;
cfg = config.tplink-safeloader;
in {

View File

@ -5,7 +5,7 @@
, ...
}:
let
inherit (lib) mkIf mkEnableOption mkOption types concatStringsSep;
inherit (lib) mkIf mkOption types;
cfg = config.boot.tftp;
instructions = pkgs.writeText "env.scr" ''
setenv serverip ${cfg.serverip}

View File

@ -5,7 +5,6 @@
, ...
}:
let
inherit (pkgs) liminix;
inherit (lib) mkIf mkOption types concatStringsSep optionalString;
in
{

View File

@ -5,7 +5,7 @@
, ...
}:
let
inherit (lib) mkIf mkEnableOption mkOption types concatStringsSep;
inherit (lib) mkIf mkOption types;
models = "6b e1 6f e1 ff ff ff ff ff ff";
in {
options.system.outputs = {

View File

@ -17,6 +17,9 @@ in {
system.service.pppoe = mkOption {
type = liminix.lib.types.serviceDefn;
};
system.service.l2tp = mkOption {
type = liminix.lib.types.serviceDefn;
};
};
config = {
system.service.pppoe = pkgs.liminix.callService ./pppoe.nix {
@ -29,6 +32,16 @@ in {
description = "options supplied on ppp command line";
};
};
system.service.l2tp = pkgs.liminix.callService ./l2tp.nix {
lns = mkOption {
type = types.str;
description = "hostname or address of the L2TP network server";
};
ppp-options = mkOption {
type = types.listOf types.str;
description = "options supplied on ppp command line";
};
};
kernel = {
config = {
PPP = "y";
@ -36,6 +49,8 @@ in {
PPP_DEFLATE = "y";
PPP_ASYNC = "y";
PPP_SYNC_TTY = "y";
PPPOL2TP = "y";
L2TP = "y";
};
};
};

59
modules/ppp/l2tp.nix Normal file
View File

@ -0,0 +1,59 @@
{
liminix
, writeAshScript
, writeText
, serviceFns
, xl2tpd
} :
{ lns, ppp-options }:
let
inherit (liminix.services) longrun;
name = "${lns}.l2tp";
ip-up = writeAshScript "ip-up" {} ''
. ${serviceFns}
(in_outputs ${name}
echo $1 > ifname
echo $2 > tty
echo $3 > speed
echo $4 > address
echo $5 > peer-address
echo $DNS1 > ns1
echo $DNS2 > ns2
)
echo >/proc/self/fd/10
'';
ip6-up = writeAshScript "ip6-up" {} ''
. ${serviceFns}
(in_outputs ${name}
echo $4 > ipv6-address
echo $5 > ipv6-peer-address
)
echo >/proc/self/fd/10
'';
ppp-options' = ppp-options ++ [
"ip-up-script" ip-up
"ipv6-up-script" ip6-up
"ipparam" name
"nodetach"
"usepeerdns"
"logfd" "2"
];
conf = writeText "xl2tpd.conf" ''
[lac upstream]
lns = ${lns}
require authentication = no
pppoptfile = ${writeText "ppp-options" ppp-options'}
autodial = yes
redial = yes
'';
control = "/run/xl2tpd/control-${name}";
in
longrun {
inherit name;
run = ''
mkdir -p /run/xl2tpd
touch ${control}
exec ${xl2tpd}/bin/xl2tpd -D -p /run/xl2tpd/${name}.pid -c ${conf} -C ${control}
'';
notification-fd = 10;
}

View File

@ -0,0 +1,178 @@
{ config, pkgs, lib, ... } :
let
svc = config.system.service;
cfg = config.profile.gateway;
inherit (lib) mkOption mkEnableOption mkIf types;
inherit (pkgs) liminix serviceFns;
inherit (liminix.services) bundle oneshot;
hostaps =
let
defaults = {
auth_algs = 1; # 1=wpa2, 2=wep, 3=both
wpa = 2; # 1=wpa, 2=wpa2, 3=both
wpa_key_mgmt = "WPA-PSK";
wpa_pairwise = "TKIP CCMP"; # auth for wpa (may not need this?)
rsn_pairwise = "CCMP"; # auth for wpa2
};
in lib.mapAttrs'
(name : value :
let
attrs = defaults // { ssid = name; } // value;
in lib.nameValuePair
"hostap-${name}"
(svc.hostapd.build {
interface = attrs.interface;
params = lib.filterAttrs (k: v: k != "interface") attrs;
}))
cfg.wireless.networks;
in {
options.profile.gateway = {
lan = {
interfaces = mkOption {
type = types.listOf liminix.lib.types.interface;
default = [];
};
address = mkOption {
type = types.attrs;
};
prefix = mkOption { type = types.str; };
dhcp = {
start = mkOption { type = types.int; };
end = mkOption { type = types.int; };
hosts = mkOption { type = types.attrs; };
localDomain = mkOption { type = types.str; };
};
};
firewall = {
enable = mkEnableOption "firewall";
rules = mkOption { type = types.attrsOf types.attrs; };
};
wan = {
interface = mkOption { type = liminix.lib.types.interface; };
username = mkOption { type = types.str; };
password = mkOption { type = types.str; };
dhcp6.enable = mkOption { type = types.bool; };
};
wireless = mkOption {
type = types.attrsOf types.anything;
};
};
imports = [
../wlan.nix
../network
../ppp
../dnsmasq
../dhcp6c
../firewall
../hostapd
../bridge
../ntp
../ssh
{ config.services = hostaps; }
];
config = {
services.int = svc.network.address.build ({
interface = svc.bridge.primary.build { ifname = "int"; };
} // cfg.lan.address);
services.bridge = svc.bridge.members.build {
primary = config.services.int;
members = cfg.lan.interfaces;
};
services.wan = svc.pppoe.build {
inherit (cfg.wan) interface;
ppp-options = [
"debug" "+ipv6" "noauth"
"name" cfg.wan.username
"password" cfg.wan.password
];
};
services.packet_forwarding = svc.network.forward.build { };
services.dhcp6c =
let
client = svc.dhcp6c.client.build {
interface = config.services.wan;
};
bundl = bundle {
name = "dhcp6c";
contents = [
(svc.dhcp6c.prefix.build {
inherit client;
interface = config.services.int;
})
(svc.dhcp6c.address.build {
inherit client;
interface = config.services.wan;
})
];
};
in mkIf cfg.wan.dhcp6.enable bundl;
services.dns =
let interface = config.services.int;
dcfg = cfg.lan.dhcp;
in svc.dnsmasq.build {
resolvconf = config.services.resolvconf;
inherit interface;
ranges = [
"${cfg.lan.prefix}.${toString dcfg.start},${cfg.lan.prefix}.${toString dcfg.end}"
# ra-stateless: 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.
"::,constructor:$(output ${interface} ifname),ra-stateless"
];
hosts = dcfg.hosts;
upstreams = [ "/${dcfg.localDomain}/" ];
domain = dcfg.localDomain;
};
services.defaultroute4 = svc.network.route.build {
via = "$(output ${config.services.wan} address)";
target = "default";
dependencies = [ config.services.wan ];
};
services.defaultroute6 = svc.network.route.build {
via = "$(output ${config.services.wan} ipv6-peer-address)";
target = "default";
interface = config.services.wan;
};
services.firewall = mkIf cfg.firewall.enable
(svc.firewall.build {
extraRules = cfg.firewall.rules;
});
services.resolvconf = oneshot rec {
dependencies = [ config.services.wan ];
name = "resolvconf";
up = ''
. ${serviceFns}
( in_outputs ${name}
echo "nameserver $(output ${config.services.wan} ns1)" > resolv.conf
echo "nameserver $(output ${config.services.wan} ns2)" >> resolv.conf
chmod 0444 resolv.conf
)
'';
};
filesystem =
let inherit (pkgs.pseudofile) dir symlink;
in dir {
etc = dir {
"resolv.conf" = symlink "${config.services.resolvconf}/.outputs/resolv.conf";
};
};
};
}

View File

@ -5,9 +5,9 @@
...
}: let
inherit (pkgs) liminix;
inherit (lib) mkEnableOption mkOption types isDerivation hasAttr ;
inherit (lib) mkOption types ;
inherit (pkgs.liminix.services) oneshot longrun bundle target;
inherit (pkgs.liminix.services) oneshot target;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) serviceFns;
svc = config.system.service;
@ -40,7 +40,6 @@ in {
../network
../hostapd
../bridge
../ssh
{ config.services = hostaps; }
];
@ -54,7 +53,6 @@ in {
};
};
config = {
services.sshd = svc.ssh.build {};
services.int = svc.bridge.primary.build {
ifname = "int";

View File

@ -1,11 +1,6 @@
{
config
, pkgs
, lib
, ...
}:
{ config, lib, ... }:
let
inherit (lib) mkIf mkEnableOption mkOption; # types concatStringsSep;
inherit (lib) mkIf mkEnableOption; # types concatStringsSep;
in {
options = {
boot = {

View File

@ -1,4 +1,4 @@
{ config, pkgs, ... }:
{ config, pkgs, lib, ... }:
let
inherit (pkgs)
execline
@ -6,14 +6,50 @@ let
s6-init-bin
s6-linux-init
stdenvNoCC;
inherit (lib.lists) unique concatMap;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs.liminix.services) bundle;
inherit (pkgs.liminix.services) oneshot bundle;
s6-rc-db =
let
# In the default bundle we need to have all the services
# in config.services except for controlled services and
# anything that depends on one. But we do need the controllers
# themselves.
# So, find all required services and their transitive
# dependencies and their controllers. remove all controlled
# services and all services that have a controlled service as
# dependency
isControlled = s : s ? controller && s.controller != null;
deps = s : s.dependencies ++
lib.optional (isControlled s) s.controller;
flatDeps = s : [s] ++ concatMap flatDeps (deps s);
allServices = unique (concatMap flatDeps (builtins.attrValues config.services));
isDependentOnControlled = s :
isControlled s ||
(lib.lists.any isDependentOnControlled s.dependencies);
# all controlled services depend on this oneshot, which
# makes a list of them so we can identify them at runtime
controlled = oneshot {
name = "controlled";
up = ''
mkdir -p /run/services/controlled
for s in $(s6-rc-db -d dependencies controlled); do
touch /run/services/controlled/$s
done
'';
down = "rm -r /run/services/controlled";
};
defaultStart =
builtins.filter
(s: !(isDependentOnControlled s)) allServices;
defaultDefaultTarget = bundle {
name = "default";
contents = builtins.attrValues config.services;
contents = defaultStart ++ [controlled];
};
servicesAttrs = {
default = defaultDefaultTarget;

View File

@ -34,7 +34,7 @@ fi
### If your services are managed by s6-rc:
### (replace /run/service with your scandir)
s6-rc-init /run/service -d -c /etc/s6-rc/compiled
s6-rc-init -d -c /etc/s6-rc/compiled /run/service
### 2. Starting the wanted set of services

View File

@ -1,4 +1,4 @@
{ config, pkgs, lib, ... } :
{ config, pkgs, ... } :
{
config = {
programs.busybox = {

View File

@ -0,0 +1,37 @@
# this is unlikely to be the final form or location of this code, it's
# an interim module which wraps the uevent-watch command
{ lib, pkgs, config, ... }:
let
inherit (lib) mkOption types;
inherit (pkgs) liminix;
# inherit (pkgs.liminix.services) bundle;
in {
options = {
system.service.uevent-rule = mkOption {
description = "a service which starts other services based on device state (sysfs)";
type = liminix.lib.types.serviceDefn;
};
};
config = {
system.service.uevent-rule = liminix.callService ./rule.nix {
serviceName = mkOption {
description = "name of the service to run when the rule matches";
type = types.str;
};
terms = mkOption {
type = types.attrs;
example = {
devtype = "usb_device";
attrs.idVendor = "8086";
};
default = {};
};
symlink = mkOption {
description = "create symlink targeted on devpath";
type = types.nullOr types.str;
default = null;
};
};
};
}

View File

@ -0,0 +1,23 @@
{
liminix
, uevent-watch
, lib }:
{
serviceName, terms, symlink
}:
let
inherit (liminix.services) longrun;
inherit (lib.attrsets) collect mapAttrsRecursive;
inherit (lib.strings) concatStringsSep;
stringify = attrs :
concatStringsSep " "
(collect lib.isString
(mapAttrsRecursive
(path : value : "${concatStringsSep "." path}=${value}")
attrs));
termsString = stringify terms;
in longrun {
name = "watch-for-${serviceName}";
restart-on-upgrade = true;
run = "${uevent-watch}/bin/uevent-watch ${if symlink != null then "-n ${symlink}" else ""} -s ${serviceName} ${termsString}";
}

View File

@ -1,8 +1,8 @@
{
config
, pkgs
, lib
, ...
config,
pkgs,
lib,
...
}:
let
inherit (pkgs) liminix;

View File

@ -1,7 +1,6 @@
{
liminix
, dropbear
, serviceFns
, lib
}:
p :

View File

@ -1,7 +1,7 @@
# support for USB block devices and the common filesystems
# they're likely to provide
{lib, config, ... }:
{ config, ... }:
{
kernel = {
config = {
@ -24,8 +24,6 @@
EXT4_FS = "y";
EXT4_USE_FOR_EXT2 = "y";
FS_ENCRYPTION = "y";
};
};
}

View File

@ -16,11 +16,17 @@ let
inherit (lib)
concatStrings concatStringsSep mapAttrsToList mkOption types;
inherit (builtins) toString;
inherit (pkgs.pseudofile) dir symlink;
passwd-file =
let lines = mapAttrsToList (name: u: "${name}:${if u ? passwd then u.passwd else "!!"}:${toString u.uid}:${toString u.gid}:${u.gecos}:${u.dir}:${u.shell}\n" )
config.users;
in concatStrings lines;
inherit (pkgs.pseudofile) dir;
passwd-file =
let
lines = mapAttrsToList (
name: u:
"${name}:${
if u ? passwd then u.passwd else "!!"
}:${toString u.uid}:${toString u.gid}:${u.gecos}:${u.dir}:${u.shell}\n"
) config.users;
in
concatStrings lines;
group-file =
let lines = mapAttrsToList
(name: {gid, usernames ? []}:

View File

@ -13,7 +13,6 @@
{ lib, pkgs, config, ...}:
let
inherit (lib) mkOption types;
inherit (pkgs.liminix.services) oneshot;
inherit (pkgs) liminix;
in
{

View File

@ -15,4 +15,5 @@ in oneshot rec {
)
'';
down = "ip link set down dev ${ifname}";
dependencies = [ primary ];
}

View File

@ -1,6 +1,7 @@
{
liminix
, lib
, s6
}:
{ watched, headStart } :
let
@ -8,5 +9,5 @@ let
in longrun {
name = "watchdog";
run =
"HEADSTART=${toString headStart} ${./gaspode.sh} ${lib.concatStringsSep " " (builtins.map (s: s.name) watched)}";
"PATH=${s6}/bin:$PATH HEADSTART=${toString headStart} ${./gaspode.sh} ${lib.concatStringsSep " " (builtins.map (s: s.name) watched)}";
}

View File

@ -1,11 +1,10 @@
{ lib, pkgs, config, ...}:
let
inherit (lib) mkEnableOption mkOption types isDerivation hasAttr ;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) stdenv wireless-regdb;
regulatory = stdenv.mkDerivation {
name = "regulatory.db";
phases = ["installPhase"];
phases = [ "installPhase" ];
installPhase = ''
mkdir -p $out
cp ${wireless-regdb}/lib/firmware/regulatory.db $out/

View File

@ -46,7 +46,7 @@ in
extraPkgs // {
# liminix library functions
lim = {
parseInt = s : (builtins.fromTOML "r=${s}").r;
parseInt = s: (builtins.fromTOML "r=${s}").r;
};
# keep these alphabetical
@ -74,9 +74,24 @@ extraPkgs // {
# should texinfo be in nativeBuildInputs instead of
# buildInputs?
texinfo = null;
};
# luarocks wants a cross-compiled cmake (which seems like a bug,
# we're never going to run luarocks on the device, but ...)
# but https://github.com/NixOS/nixpkgs/issues/284734
# so we do surgery on the cmake derivation until that's fixed
cmake = prev.cmake.overrideAttrs(o:
# don't override the build cmake or we'll have to rebuild
# half the known universe to no useful benefit
if final.stdenv.buildPlatform != final.stdenv.hostPlatform
then {
preConfigure =
builtins.replaceStrings
["$configureFlags"] ["$configureFlags $cmakeFlags"] o.preConfigure;
}
else {}
);
dnsmasq =
let d = prev.dnsmasq.overrideAttrs(o: {
@ -170,9 +185,12 @@ extraPkgs // {
# done. Do it the ugly way..
postPatch =
o.postPatch
+ (with final;
lib.optionalString (stdenv.buildPlatform != stdenv.hostPlatform)
"\nsed -i.bak 's/linux.*-mips/linux-mops/' Configure\n");
+ (
with final;
lib.optionalString (
stdenv.buildPlatform != stdenv.hostPlatform
) "\nsed -i.bak 's/linux.*-mips/linux-mops/' Configure\n"
);
});
pppBuild = prev.ppp;
@ -184,13 +202,12 @@ extraPkgs // {
}); in q.override { nixosTestRunner = true; sdlSupport = false; };
rsyncSmall =
let r = prev.rsync.overrideAttrs(o: {
configureFlags = o.configureFlags ++ [
"--disable-openssl"
];
});
in r.override { openssl = null; };
let
r = prev.rsync.overrideAttrs (o: {
configureFlags = o.configureFlags ++ [ "--disable-openssl" ];
});
in
r.override { openssl = null; };
inherit s6;
s6-linux-init = prev.s6-linux-init.override {
@ -208,14 +225,14 @@ extraPkgs // {
ubootQemuAarch64 = final.buildUBoot {
defconfig = "qemu_arm64_defconfig";
extraMeta.platforms = ["aarch64-linux"];
filesToInstall = ["u-boot.bin"];
extraMeta.platforms = [ "aarch64-linux" ];
filesToInstall = [ "u-boot.bin" ];
};
ubootQemuArm = final.buildUBoot {
defconfig = "qemu_arm_defconfig";
extraMeta.platforms = ["armv7l-linux"];
filesToInstall = ["u-boot.bin"];
extraMeta.platforms = [ "armv7l-linux" ];
filesToInstall = [ "u-boot.bin" ];
extraConfig = ''
CONFIG_CMD_UBI=y
CONFIG_CMD_UBIFS=y
@ -229,8 +246,8 @@ extraPkgs // {
ubootQemuMips = final.buildUBoot {
defconfig = "malta_defconfig";
extraMeta.platforms = ["mips-linux"];
filesToInstall = ["u-boot.bin"];
extraMeta.platforms = [ "mips-linux" ];
filesToInstall = [ "u-boot.bin" ];
# define the prompt to be the same as arm{32,64} so
# we can use the same expect script for both
extraPatches = [ ./pkgs/u-boot/0002-virtio-init-for-malta.patch ];
@ -252,9 +269,20 @@ extraPkgs // {
CONFIG_MIPS_BOOT_FDT=y
CONFIG_OF_LIBFDT=y
CONFIG_OF_STDOUT_VIA_ALIAS=y
'';
'';
};
libusb1 =
let u = prev.libusb1.overrideAttrs(o: {
# don't use gcc libatomic because it vastly increases the
# closure size
preConfigure = "sed -i.bak /__atomic_fetch_add_4/c\: configure.ac";
});
in u.override {
enableUdev = final.stdenv.buildPlatform == final.stdenv.hostPlatform;
withDocs = false;
};
util-linux-small = prev.util-linux.override {
ncursesSupport = false;
pamSupport = false;
@ -263,5 +291,4 @@ extraPkgs // {
translateManpages = false;
capabilitiesSupport = false;
};
}

Some files were not shown because too many files have changed in this diff Show More