Compare commits
62 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 26b4a7a145 | |||
| 2663f58807 | |||
| 9dbc285605 | |||
| 8b6aa2134e | |||
| 3df1ec76ff | |||
| 0d3218127f | |||
| e94bf62ec1 | |||
| 16a2499d74 | |||
| d4d8093f97 | |||
| 7c9c801afc | |||
| c4185617c0 | |||
| 06d28e9b08 | |||
| 9540fc2641 | |||
| adc84108ad | |||
| eae99051fa | |||
| 49d1703428 | |||
| 1d337588f9 | |||
| 29a869b4fa | |||
| 5ae1b0a193 | |||
| 473a4947a5 | |||
| 50bad5c604 | |||
| c22e3fb2ef | |||
| f898e4dca2 | |||
| 5121a8563d | |||
| 78be354b6e | |||
| be13ab23ca | |||
| 4b30cd7a75 | |||
| b15542b668 | |||
| 6daeaf29a0 | |||
| e6ca5ea064 | |||
| e6e4665a18 | |||
| 2c10790a6d | |||
| 571adf84c0 | |||
| c8c79fd75a | |||
| 884d8d194e | |||
| f091bbd706 | |||
| 37d7e20582 | |||
| 04b068f7a3 | |||
| 53f57c1a8c | |||
| 19aba0d873 | |||
| 7d00b39249 | |||
| 7aa8633cde | |||
| 58bec8a40f | |||
| a3fca5bf05 | |||
| e0bd7aec1e | |||
| e815f61bb5 | |||
| af9200a136 | |||
| 898958fa10 | |||
| fa0f262706 | |||
| 71aeb27b2f | |||
| 530b4080c9 | |||
| 58cd007ccc | |||
| 3a56798eb5 | |||
| 758c7ef657 | |||
| 73225a70b2 | |||
| ab304dd3f1 | |||
| 0d49f0f7a7 | |||
| e64390460a | |||
| c0ef6ce282 | |||
| bd6ec5201f | |||
| b4068da9fe | |||
| aa4b09da85 |
+423
-3
@@ -4726,9 +4726,9 @@ outside of it
|
||||
[X] 2) if so, convert it to lualinux
|
||||
[X] 3) add netlink socket to event loop
|
||||
[X] 4) make it send messages to subscribers
|
||||
5) package it
|
||||
6) make uevent-watcher use it instead of netlink directly
|
||||
7) write an inout test variant that has the stick inserted
|
||||
[X] 5) package it
|
||||
[X] 6) make uevent-watcher use it instead of netlink directly
|
||||
[X] 7) write an inout test variant that has the stick inserted
|
||||
at boot time already
|
||||
|
||||
I'm also thinking we could wrap the raw fds from lualinux into small
|
||||
@@ -4741,3 +4741,423 @@ state before subscribing them [ needs a test ]
|
||||
figure out what event format the subscribers want? lua-ish or send the
|
||||
same messages as udev would? If we're going to send the originals,
|
||||
should we store them alongside the parsed, or reconstruct from parsed?
|
||||
|
||||
Sat Apr 27 21:52:11 BST 2024
|
||||
|
||||
We have a passing inout test. Next thing to do is try it on
|
||||
the actual arhcive hardware
|
||||
|
||||
Next big thing is some kind of failovery service. Almost-obvious
|
||||
candidate is LTE failover with aaisp l2tp tunnel
|
||||
|
||||
Tue Apr 30 23:27:30 BST 2024
|
||||
|
||||
I want to connect my new ip camera to arthur without letting it reach the
|
||||
internet, or the internet reach it.
|
||||
|
||||
we could plug it into a gl.inet box running dhcp server on lan
|
||||
and client on wan, then use NAT to expose the camera's http and rtsp
|
||||
ports on whatever address it has on the wan interface
|
||||
|
||||
Tue May 7 22:23:49 BST 2024
|
||||
|
||||
If we want to build a config with an l2tp upstream, it needs an
|
||||
underlying dhcp interface not pppoe as we can't use the bordervm l2tp
|
||||
account simultaneously. Having bordervm do dhcp might be quite useful
|
||||
anyway for other applications, although it will have to double-nat to
|
||||
the internet. We could give it an aaisp /64 and have routable ipv6 but
|
||||
maybe that's a level of faff too high.
|
||||
|
||||
Given that we can build xl2tpd and a service for it.
|
||||
|
||||
|
||||
're using the same l2tp account for thingy that we use to simulate ppp,
|
||||
we need an upstream which is not ppp
|
||||
|
||||
We need a less shit coldplug that copes with filenames containing spaces (!)
|
||||
|
||||
Fri May 10 00:33:14 BST 2024
|
||||
|
||||
Getting xl2tp hackily running turned out to be not a lot of work. However,
|
||||
we need to figure out routing
|
||||
|
||||
- we need a route on lan device to the dns to lookup l2tp.aaisp.net.uk
|
||||
- we need a route on lan device to l2tp.aaisp.net.uk
|
||||
|
||||
also it doesn't die when the tunnel closes, which is a bit shit
|
||||
|
||||
maybe this is where we lean into health check services
|
||||
|
||||
a health check service is just a service that watches another service
|
||||
and kills it if it's not healthy.
|
||||
|
||||
for xl2tpd, "not healthy" is "there is no ppp process" or "there is no
|
||||
tunnel" or "the tunnel has no sessions". I don't know how we
|
||||
(robustly) test for no ppp process associated with the l2tp peer
|
||||
|
||||
when ppp quits, does the tunnel come down?
|
||||
in xl2tld.c child_handler we respond to sigchld by closing c->fd
|
||||
and setting it to -1
|
||||
|
||||
Sat May 11 17:55:04 BST 2024
|
||||
|
||||
A better way to monitor the connection health would be to ping a
|
||||
computer on the internet (preferably one that doesn't mind being
|
||||
pinged). If we combine autodial with "is $isp still there" then we
|
||||
should have something fairly robust.
|
||||
|
||||
xl2tpd spawns pppd, we should equip it with config that writes the
|
||||
ppp outputs (ip address etc) to the xl2tp service directory so
|
||||
that it can be used like a regular ppp. This will also make
|
||||
it possible to have the health check work by pinging the peer address
|
||||
|
||||
Sun May 12 22:33:09 BST 2024
|
||||
|
||||
sleep until the interface is probably up
|
||||
failure counter = 0
|
||||
loop indefinitely
|
||||
get outputs/peer-address of watched ppp service
|
||||
ping it
|
||||
if ok
|
||||
reset failure counter
|
||||
else
|
||||
increment failure counter
|
||||
fi
|
||||
if failure counter > threshold
|
||||
bounce the ppp service
|
||||
exit, if previous action didn't do that already
|
||||
end
|
||||
sleep(check interval)
|
||||
end loop
|
||||
|
||||
|
||||
# ps ax | grep l2tp
|
||||
72 root 1316 S s6-supervise l2tp.aaisp.net.uk.l2tp
|
||||
73 root 1316 S s6-supervise l2tp.aaisp.net.uk.l2tp-log
|
||||
122 root 1428 S {run.user} /bin/sh ./run.user l2tp.aaisp.net.uk.l2tp
|
||||
1099 root 1428 S {run.user} /bin/sh ./run.user l2tp.aaisp.net.uk.l2tp
|
||||
1102 root 1104 S {xl2tpd} /nix/store/i1bbqh7vybam03l6jzf4sm4np3k4ack5
|
||||
1115 root 1420 S grep l2tp
|
||||
# s6-rc -d change l2tp.aaisp.net.uk.l2tp
|
||||
# ps ax | grep l2tp
|
||||
72 root 1316 S s6-supervise l2tp.aaisp.net.uk.l2tp
|
||||
73 root 1316 S s6-supervise l2tp.aaisp.net.uk.l2tp-log
|
||||
122 root 1428 S {run.user} /bin/sh ./run.user l2tp.aaisp.net.uk.l2tp
|
||||
1102 root 1104 S {xl2tpd} /nix/store/i1bbqh7vybam03l6jzf4sm4np3k4ack5
|
||||
1122 root 1420 S grep l2tp
|
||||
|
||||
|
||||
Mon May 13 19:45:59 BST 2024
|
||||
|
||||
We need to do the usb id swithcing dance thing for the lte modem.
|
||||
At startup it's 12d1:14fe, which is "mass storage mode", although the
|
||||
disks seem to disappear as soon as they appear which is weird
|
||||
|
||||
probably the mode switch should be triggered by device insertion
|
||||
|
||||
usb_modeswitch -v 12d1 -p 14fe --huawei-new-mode
|
||||
|
||||
https://github.com/pixelspark/tymodem?tab=readme-ov-file
|
||||
|
||||
|
||||
Tue May 14 21:58:25 BST 2024
|
||||
|
||||
[ we didn't need this. the first form is the default, the second
|
||||
is what something on the internet said we should change it to, the
|
||||
third is setting it back to default ]
|
||||
|
||||
^SETPORT:A1,A2;12,1,16,A1,A2
|
||||
AT^SETPORT="FF;12,16"
|
||||
AT^SETPORT="A1,A2;12,1,16,A1,A2"
|
||||
|
||||
|
||||
|
||||
Wed May 15 21:55:11 BST 2024
|
||||
|
||||
we can use uevent-watch to look for devtype=usb_device product=12d1/14fe/102
|
||||
and trigger a oneshot that runs usb-modeswitch
|
||||
|
||||
we can use uevent-watch to look for devtype=usb_device product=12d1/1506/102
|
||||
and trigger a oneshot that runs the AT commands
|
||||
|
||||
if wwan0 is a triggered service how can dhcp depend on it? arse
|
||||
|
||||
- we can get reverse dependencies from s6-rc-db, so the sematics of
|
||||
starting a triggered service could include starting everything it
|
||||
enables
|
||||
|
||||
- we don't want to inadvertently start it on boot by putting it in the
|
||||
global config.services
|
||||
|
||||
Thu May 16 09:09:44 BST 2024
|
||||
|
||||
we could do something cleverish with the config.services at build time
|
||||
by stripping from it everything depending on a trigger. but then how
|
||||
_do_ they get started? the intent of putting it in config.services
|
||||
is that it will be started when conditions are suitable.
|
||||
|
||||
can we: go through each service in config.services, detect the trigger
|
||||
that started it, and add it to a bundle named for that trigger?
|
||||
|
||||
we need something in the triggering service to mark the triggered
|
||||
service as not-for-boot, and then to apply that transitively to
|
||||
everyting depending on it
|
||||
|
||||
I don't think we have common code for triggers, so either we need to
|
||||
add some or put this marking in all of the current examples
|
||||
|
||||
Wed May 22 22:29:46 BST 2024
|
||||
|
||||
# cat /sys/bus/usb/devices/1-1.2:1.2/uevent
|
||||
DEVTYPE=usb_interface
|
||||
DRIVER=huawei_cdc_ncm
|
||||
PRODUCT=12d1/1506/102
|
||||
TYPE=0/0/0
|
||||
INTERFACE=255/2/22
|
||||
MODALIAS=usb:v12D1p1506d0102dc00dsc00dp00icFFisc02ip16in02
|
||||
|
||||
# cat /sys/bus/usb/devices/1-1.2:1.0/uevent
|
||||
DEVTYPE=usb_interface
|
||||
DRIVER=option
|
||||
PRODUCT=12d1/1506/102
|
||||
TYPE=0/0/0
|
||||
INTERFACE=255/2/18
|
||||
MODALIAS=usb:v12D1p1506d0102dc00dsc00dp00icFFisc02ip12in00
|
||||
|
||||
neither of these is a tty. however, there's a ttyUSB0
|
||||
diretory in there -
|
||||
|
||||
# cat /sys/bus/usb/devices/1-1.2:1.0/ttyUSB0/uevent
|
||||
DRIVER=option1
|
||||
|
||||
# cat /sys/bus/usb/devices/1-1.2:1.0/ttyUSB0/tty/ttyUSB0/uevent
|
||||
MAJOR=188
|
||||
MINOR=0
|
||||
DEVNAME=ttyUSB0
|
||||
|
||||
|
||||
We can query devout using s6-ipcclient:
|
||||
|
||||
$ s6-ipcclient -v /run/devout.sock sh -c "echo devtype=wwan >&7; cat <&6 >&2"
|
||||
|
||||
|
||||
we're going to need to expose sysfs parent attributes in devout,
|
||||
so that we can tie together vendor/product and tty name
|
||||
|
||||
- they don't come from netlink socket so we'll have to read the
|
||||
filesystem
|
||||
- we don't know if we can cache them indefinitely or if they change
|
||||
- we also will want to match on parent attributes
|
||||
- per https://www.kernel.org/doc/html/v4.16/admin-guide/sysfs-rules.html
|
||||
we should do that by getting the parent directory, not by
|
||||
following symlinks
|
||||
|
||||
I think we are going to document "a rule depending on attrs won't
|
||||
trigger if those attrs change silently without a uevent". attrs for a
|
||||
path are rescanned only when a event for that path (or a child?)
|
||||
is received.
|
||||
|
||||
we need to avoid using stdio to read sysfs attributes because of the
|
||||
need for atomicity
|
||||
|
||||
Sun May 26 12:24:45 BST 2024
|
||||
|
||||
cd /
|
||||
mkdir -p /tmp/sys/devices
|
||||
find /sys/devices -type f | while read F ; do
|
||||
D=/tmp/$(dirname $F)
|
||||
test -d $D || mkdir -p $D
|
||||
test -r $F && cat $F > /tmp/$F
|
||||
done
|
||||
|
||||
Tue May 28 20:58:58 BST 2024
|
||||
|
||||
To make testing easier, we pass the /sys mount point as a param
|
||||
to (sysfs) via (database)
|
||||
|
||||
This means that for event:match to work with attributes, the event
|
||||
also has to point back to the database, or at least to sysfs. However
|
||||
we'd like to do the attr tests after the regular uevent key tests
|
||||
and the attrs tests after even that, because they're that mich slower.
|
||||
|
||||
-----
|
||||
|
||||
Let's change it up. The database contains kobjects not events. A
|
||||
kobject knows its mountpoint as well as its path, and implements the
|
||||
attr and attrs methods
|
||||
|
||||
|
||||
Sun Jun 2 20:58:47 BST 2024
|
||||
|
||||
we have a new uevent-rule service that can start/stop its controlled
|
||||
service based on uevent fields and sysfs attrs for the corresponding
|
||||
device/any ancestor of its sysfs path
|
||||
|
||||
we need
|
||||
- a way of starting _dependent_ services of the controlled service:
|
||||
we want to activate that whole sub-branch of the dependency tree
|
||||
|
||||
- a way to not attempt to start dependents of the controlled service
|
||||
at boot time: we don't want to put them in the default bundle if
|
||||
they depend on stuff that's part of the default service set.
|
||||
|
||||
what happens when a service depends on _two_ controlled services?
|
||||
we want to start it only when _both_ of them are up. That discourages
|
||||
any idea of creating a bundle for each controlled service and its
|
||||
dependants
|
||||
|
||||
Tue Jun 4 19:07:44 BST 2024
|
||||
|
||||
we have to do it at runtime. I think we can add a file in the service
|
||||
directory to identify that it's triggered (i.e. only run in response
|
||||
to an event, we could use better terminology here(
|
||||
|
||||
|
||||
for s in the reverse deps of $triggered
|
||||
unless any? (s1: { s1.triggered && s1.down } )
|
||||
s.dependencies
|
||||
start s
|
||||
|
||||
we can do this in ci, maybe adapt the inout test
|
||||
|
||||
two triggered services, A with a uevent that does happen
|
||||
and B which doesn't
|
||||
|
||||
two dependent services; C depends on A only and D on A+B.
|
||||
|
||||
each should write an output
|
||||
we check that the output from C is present but not the one from D
|
||||
|
||||
|
||||
|
||||
Tue Jun 4 22:22:20 BST 2024
|
||||
|
||||
We can't have dependencies of triggered services unless we expose the
|
||||
triggered service instead of the watcher from the module that sets up
|
||||
uevent-watch. otherwise the user will be declaring their dependencies
|
||||
on the watcher and they will start when the watcher does. We need to
|
||||
invert it.
|
||||
|
||||
Bother.
|
||||
|
||||
services.mount-foo = oneshot {
|
||||
name = "blah";
|
||||
up = "mount /dev/disk/by-partlabel/mydisk";
|
||||
runCondition = conditions.sysfs {
|
||||
terms = { partlabel = "blah"; };
|
||||
symlink = "/dev/disk/by-partlabel/mydisk";
|
||||
}
|
||||
}
|
||||
|
||||
To process this, we need to
|
||||
|
||||
- remove it from the default bundle
|
||||
- create a service that _is_ in the default bundle which
|
||||
starts this one when runCondition is true
|
||||
|
||||
|
||||
How would it look for service conditions other than uevents
|
||||
|
||||
Thu Jun 6 21:49:10 BST 2024
|
||||
|
||||
runCondition can be a function that accepts the service to be
|
||||
watched and returns a service that does the watching. The
|
||||
derivation calls this function and makes the watched service
|
||||
depend on the watcher.
|
||||
|
||||
When adding services to the default bundle (wherever that happens, I
|
||||
no longer remember) we need to check if the service has a controller
|
||||
and add that instead of the service itself.
|
||||
|
||||
s6-ipcclient -v /run/devout.sock sh -c "echo subsystem=tty attrs.idVendor=12d1 >&7; cat <&6 >&2"
|
||||
|
||||
Sun Jun 9 22:55:05 BST 2024
|
||||
|
||||
services which depend on services that have controllers should not be
|
||||
added to default bundle, otherwise they will try to start the controlled
|
||||
service before its ready
|
||||
|
||||
Tue Jun 11 20:00:04 BST 2024
|
||||
|
||||
we can't look in /run/service/name to see if it's controlled, because
|
||||
if it's a oneshot that directory won't exist. likewise /run/s6-rc/servicedirs/
|
||||
|
||||
we could add the controller to the dependencies, then
|
||||
controlled? = (any dependency is a controller)
|
||||
|
||||
what about generating a script at build time that has the knowledge
|
||||
baked in?
|
||||
|
||||
|
||||
to_start = reverse deps of service
|
||||
print "to_start=$to_start"
|
||||
for each service s1 in to_start
|
||||
if isControlled s1
|
||||
rd = reverse deps of s1
|
||||
print "test_stopped s1 && not_to_start="$not_to_start $rd"
|
||||
print ''
|
||||
for s in $to_start; do
|
||||
case " $not_to_start " in
|
||||
*" $s "*) true;;
|
||||
*) s6-rc -u change $s ;;
|
||||
esac
|
||||
done
|
||||
''
|
||||
|
||||
---
|
||||
|
||||
would it help to make an empty bundle called "controlled" and have all
|
||||
controlled services depend on it? no, because the condition for
|
||||
skipping a service is that it depends on a _different_ controlled
|
||||
service that's down
|
||||
|
||||
s6-rc -u change $service
|
||||
for s in $(s6-rc-db -d all-dependencies $service); do
|
||||
if (s6-rc-db all-dependencies $s | grep controlled); do
|
||||
# do nothing: if it's stopped, we don't want to start it,
|
||||
# and if it's already running there's no need to.
|
||||
# XXX what if it's running but its children are not?
|
||||
# XXX 2 this fails as written because _every_ service $s depends
|
||||
# on the controlled service $service
|
||||
else
|
||||
start s
|
||||
|
||||
"[service] Names cannot be duplicated and cannot contain a slash or a
|
||||
newline; they can contain spaces and tabs, but using anything else
|
||||
than alphanumerical characters, underscores and dashes is discouraged"
|
||||
|
||||
would this be simpler in fennel?
|
||||
|
||||
(each [l (lines (io.popen (%. "s6-rc-db -d all-dependencies %s" service)))]
|
||||
(if (not (controlled-ancestor l))
|
||||
(tset to-start l true)))
|
||||
|
||||
Sat Jun 15 08:51:21 BST 2024
|
||||
|
||||
# do this at boot
|
||||
for s in $(s6-rc-db -d dependencies controlled); do
|
||||
mkdir -p /run/services/controlled
|
||||
touch /run/services/controlled/$s
|
||||
done
|
||||
|
||||
|
||||
# now we can do this to start a service tree
|
||||
|
||||
for controlled in $(cd /run/services/controlled/ && echo *); do
|
||||
if down $controlled; then
|
||||
blocks="$blocks $controlled "
|
||||
fi
|
||||
done
|
||||
|
||||
for s in $(s6-rc-db -d all-dependencies $service); do
|
||||
for dep in $(s6-rc-db all-dependencies $s)
|
||||
case "$blocks" in
|
||||
"* $dep *")
|
||||
: don't start
|
||||
;;
|
||||
*)
|
||||
s6-rc -u change $s
|
||||
;;
|
||||
esac
|
||||
done
|
||||
done
|
||||
|
||||
+20
@@ -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
|
||||
+35
-19
@@ -6,7 +6,7 @@ in {
|
||||
options.bordervm = {
|
||||
keys = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
default = [ ];
|
||||
};
|
||||
l2tp = {
|
||||
host = mkOption {
|
||||
@@ -55,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 = {
|
||||
@@ -80,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";
|
||||
};
|
||||
@@ -122,11 +133,16 @@ 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";
|
||||
|
||||
@@ -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";
|
||||
};
|
||||
|
||||
@@ -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 = ''
|
||||
|
||||
+27
-17
@@ -1,24 +1,27 @@
|
||||
{
|
||||
deviceName ? null
|
||||
, device ? (import ./devices/${deviceName} )
|
||||
, 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 = {
|
||||
@@ -46,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
|
||||
];
|
||||
|
||||
@@ -213,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"; };
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -92,7 +92,6 @@
|
||||
'';
|
||||
};
|
||||
inherit (pkgs.pseudofile) dir symlink;
|
||||
inherit (pkgs.liminix.networking) interface;
|
||||
in {
|
||||
imports = [
|
||||
../../modules/network
|
||||
@@ -125,8 +124,16 @@
|
||||
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";
|
||||
devpath = "/devices/platform/ahb/1a000000.eth";
|
||||
};
|
||||
wan = link.build {
|
||||
ifname = "wan";
|
||||
devpath = "/devices/platform/ahb/19000000.eth";
|
||||
# devpath = "/devices/platform/ahb/1a000000.eth";
|
||||
};
|
||||
wlan = link.build {
|
||||
ifname = "wlan0";
|
||||
dependencies = [ mac80211 ];
|
||||
@@ -149,6 +156,7 @@
|
||||
};
|
||||
boot.tftp = {
|
||||
loadAddress = lim.parseInt "0x00A00000";
|
||||
appendDTB = true;
|
||||
};
|
||||
kernel = {
|
||||
src = pkgs.pkgsBuildBuild.fetchurl {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
'';
|
||||
installer = "vmroot";
|
||||
|
||||
module = {pkgs, config, lim, ... }: {
|
||||
module = { config, lim, ... }: {
|
||||
imports = [
|
||||
../../modules/arch/arm.nix
|
||||
../families/qemu.nix
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"; };
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
+12
-18
@@ -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
|
||||
|
||||
+14
-12
@@ -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";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -119,29 +119,31 @@ 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
|
||||
mtdutils
|
||||
(levitate.override {
|
||||
config = {
|
||||
config = {
|
||||
services = {
|
||||
inherit (config.services) dhcpc sshd watchdog;
|
||||
};
|
||||
|
||||
+23
-17
@@ -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,8 +166,7 @@ in rec {
|
||||
interface = services.wan;
|
||||
};
|
||||
|
||||
services.firewall = svc.firewall.build {
|
||||
};
|
||||
services.firewall = svc.firewall.build { };
|
||||
|
||||
services.packet_forwarding = svc.network.forward.build { };
|
||||
|
||||
@@ -195,7 +203,5 @@ in rec {
|
||||
];
|
||||
};
|
||||
|
||||
defaultProfile.packages = with pkgs; [
|
||||
min-collect-garbage
|
||||
];
|
||||
defaultProfile.packages = with pkgs; [ min-collect-garbage ];
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
{ config, pkgs, lib, ... } :
|
||||
{ config, pkgs, ... } :
|
||||
let
|
||||
inherit (pkgs) serviceFns;
|
||||
svc = config.system.service;
|
||||
|
||||
in rec {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
{ config, pkgs, lib, ... } :
|
||||
{ config, pkgs, ... } :
|
||||
let
|
||||
inherit (pkgs) serviceFns;
|
||||
svc = config.system.service;
|
||||
|
||||
in rec {
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
{
|
||||
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 longrun 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.wan =
|
||||
let
|
||||
z = final : prev: {
|
||||
controller = longrun rec {
|
||||
name = "wan-switcher";
|
||||
run = ''
|
||||
(in_outputs ${name}
|
||||
${pkgs.s6-rc-round-robin}/bin/s6-rc-round-robin \
|
||||
-p ${final.proxy.name} \
|
||||
${lib.concatStringsSep " "
|
||||
(builtins.map (f: f.name) [final.pppoe final.l2tp])}
|
||||
)
|
||||
'';
|
||||
};
|
||||
pppoe = (svc.pppoe.build {
|
||||
interface = config.hardware.networkInterfaces.wan;
|
||||
|
||||
ppp-options = [
|
||||
"debug" "+ipv6" "noauth"
|
||||
"name" rsecrets.l2tp.name
|
||||
"password" rsecrets.l2tp.password
|
||||
];
|
||||
}).overrideAttrs(o: { inherit (final) controller; });
|
||||
|
||||
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];
|
||||
}).overrideAttrs(o: { inherit (final) controller; });
|
||||
proxy = oneshot rec {
|
||||
name = "wan-proxy";
|
||||
inherit (final) controller;
|
||||
buildInputs = with final; [ pppoe l2tp];
|
||||
up = ''
|
||||
echo start proxy ${name}
|
||||
set -x
|
||||
(in_outputs ${name}
|
||||
cp -rv $(output_path ${final.controller} active)/* .
|
||||
)
|
||||
'';
|
||||
};
|
||||
};
|
||||
in (lib.fix (lib.extends z (prev : { }))).proxy;
|
||||
|
||||
services.sshd = svc.ssh.build { };
|
||||
|
||||
services.resolvconf = oneshot rec {
|
||||
dependencies = [ services.wan ];
|
||||
name = "resolvconf";
|
||||
up = ''
|
||||
. ${serviceFns}
|
||||
( in_outputs ${name}
|
||||
for i in ns1 ns2 ; do
|
||||
ns=$(output ${services.wan} $i)
|
||||
echo "nameserver $ns" >> resolv.conf
|
||||
done
|
||||
)
|
||||
'';
|
||||
};
|
||||
filesystem = dir {
|
||||
etc = dir {
|
||||
"resolv.conf" = symlink "${services.resolvconf}/.outputs/resolv.conf";
|
||||
};
|
||||
};
|
||||
|
||||
services.dhcpc = svc.network.dhcp.client.build {
|
||||
interface = config.services.wwan;
|
||||
dependencies = [ config.services.hostname ];
|
||||
};
|
||||
|
||||
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.defaultroute4 = svc.network.route.build {
|
||||
via = "$(output ${services.wan} peer-address)";
|
||||
target = "default";
|
||||
dependencies = [services.wan];
|
||||
};
|
||||
|
||||
# defaultProfile.packages = [ pkgs.go-l2tp ];
|
||||
|
||||
users.root = {
|
||||
passwd = lib.mkForce secrets.root.passwd;
|
||||
openssh.authorizedKeys.keys = secrets.root.keys;
|
||||
};
|
||||
}
|
||||
@@ -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)";
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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";
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+4
-6
@@ -10,12 +10,10 @@
|
||||
let
|
||||
secrets = {
|
||||
domainName = "fake.liminix.org";
|
||||
firewallRules = {};
|
||||
firewallRules = { };
|
||||
} // (import ./rotuer-secrets.nix);
|
||||
inherit (pkgs.liminix.services) oneshot bundle;
|
||||
inherit (pkgs) serviceFns;
|
||||
svc = config.system.service;
|
||||
wirelessConfig = {
|
||||
wirelessConfig = {
|
||||
country_code = "GB";
|
||||
inherit (secrets) wpa_passphrase;
|
||||
wmm_enabled = 1;
|
||||
@@ -72,13 +70,13 @@ in rec {
|
||||
wireless.networks = {
|
||||
"${secrets.ssid}" = {
|
||||
interface = config.hardware.networkInterfaces.wlan;
|
||||
hw_mode="g";
|
||||
hw_mode = "g";
|
||||
channel = "2";
|
||||
ieee80211n = 1;
|
||||
} // wirelessConfig;
|
||||
"${secrets.ssid}5" = rec {
|
||||
interface = config.hardware.networkInterfaces.wlan5;
|
||||
hw_mode="a";
|
||||
hw_mode = "a";
|
||||
channel = 36;
|
||||
ht_capab = "[HT40+]";
|
||||
vht_oper_chwidth = 1;
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
{ config, pkgs, lib, lim, ... } :
|
||||
{ config, pkgs, lim, ... } :
|
||||
let
|
||||
inherit (pkgs) serviceFns;
|
||||
svc = config.system.service;
|
||||
|
||||
in rec {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{ lib, lim, pkgs, config, ...}:
|
||||
{ lim, pkgs, config, ...}:
|
||||
{
|
||||
config = {
|
||||
kernel.config = {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{ lib, lim, pkgs, config, ...}:
|
||||
{ lim, pkgs, config, ...}:
|
||||
{
|
||||
config = {
|
||||
kernel.config = {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{ lib, pkgs, config, lim, ...}:
|
||||
{ config, lim, ...}:
|
||||
{
|
||||
config = {
|
||||
kernel.config = {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{ lib, pkgs, config, ...}:
|
||||
{ pkgs, config, ...}:
|
||||
{
|
||||
imports = [ ./mips.nix ];
|
||||
config = {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{ lib, pkgs, config, ...}:
|
||||
{ config, ...}:
|
||||
{
|
||||
imports = [ ./mips.nix ];
|
||||
config = {
|
||||
|
||||
+18
-13
@@ -4,10 +4,8 @@
|
||||
|
||||
{ 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;
|
||||
|
||||
@@ -38,7 +36,7 @@ in {
|
||||
'';
|
||||
# internal = true; # probably a good case to make this internal
|
||||
};
|
||||
rootfsType = mkOption {
|
||||
rootfsType = mkOption {
|
||||
default = "squashfs";
|
||||
type = types.enum [
|
||||
"btrfs"
|
||||
@@ -48,7 +46,7 @@ in {
|
||||
"ubifs"
|
||||
];
|
||||
};
|
||||
rootOptions = mkOption {
|
||||
rootOptions = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
};
|
||||
@@ -56,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 = {
|
||||
@@ -85,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
|
||||
@@ -130,13 +137,11 @@ in {
|
||||
s = pkg (checkTypes parameters
|
||||
(builtins.removeAttrs args ["dependencies"]));
|
||||
in s.overrideAttrs (o: {
|
||||
dependencies = (builtins.map (d: d.name) dependencies) ++ o.dependencies;
|
||||
dependencies = dependencies ++ o.dependencies;
|
||||
buildInputs = dependencies ++ o.buildInputs;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
users.root = {
|
||||
uid = 0; gid= 0; gecos = "Root of all evaluation";
|
||||
dir = "/home/root/";
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
{ lib, pkgs, config, ...}:
|
||||
let
|
||||
inherit (lib) mkOption types;
|
||||
inherit (pkgs.liminix.services) oneshot;
|
||||
inherit (pkgs) liminix;
|
||||
in
|
||||
{
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
{
|
||||
liminix
|
||||
, ifwait
|
||||
, lib
|
||||
, svc
|
||||
}:
|
||||
{ members, primary } :
|
||||
@@ -9,7 +8,6 @@
|
||||
let
|
||||
inherit (liminix.networking) interface;
|
||||
inherit (liminix.services) bundle oneshot;
|
||||
inherit (lib) mkOption types;
|
||||
addif = member :
|
||||
# how do we get sight of services from here? maybe we need to
|
||||
# implement ifwait as a regualr derivation instead of a
|
||||
|
||||
@@ -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 = ''
|
||||
|
||||
+8
-5
@@ -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
|
||||
);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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" ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -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 ];
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
writeFennel
|
||||
, linotify
|
||||
, anoia
|
||||
, lua
|
||||
, lualinux
|
||||
}:
|
||||
writeFennel "acquire-delegated-prefix" {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
{ lib, pkgs, config, ...}:
|
||||
let
|
||||
inherit (lib) mkOption types;
|
||||
inherit (pkgs.liminix.services) oneshot;
|
||||
inherit (pkgs) liminix;
|
||||
in
|
||||
{
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
{ rules, extraRules }:
|
||||
let
|
||||
inherit (liminix.services) oneshot;
|
||||
inherit (liminix.lib) typeChecked;
|
||||
inherit (lib) mkOption types;
|
||||
script = firewallgen "firewall.nft" (lib.recursiveUpdate rules extraRules);
|
||||
in oneshot {
|
||||
name = "firewall";
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -9,7 +9,7 @@ let
|
||||
in longrun {
|
||||
name = "ifwait.${interface.name}";
|
||||
buildInputs = [ service ];
|
||||
isTrigger = true;
|
||||
restart-on-upgrade = true;
|
||||
run = ''
|
||||
${ifwait}/bin/ifwait -s ${service.name} $(output ${interface} ifname) ${state}
|
||||
'';
|
||||
|
||||
@@ -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
|
||||
|
||||
+7
-4
@@ -1,4 +1,4 @@
|
||||
{ config, pkgs, lib, ...} :
|
||||
{ config, pkgs, ...} :
|
||||
let inherit (pkgs.liminix.services) oneshot longrun;
|
||||
in {
|
||||
config = {
|
||||
@@ -11,16 +11,19 @@ in {
|
||||
devout = longrun {
|
||||
name = "devout";
|
||||
notification-fd = 10;
|
||||
run = "${pkgs.devout}/bin/devout /run/devout.sock 4";
|
||||
run = "exec ${pkgs.devout}/bin/devout /run/devout.sock 4";
|
||||
};
|
||||
coldplug = oneshot {
|
||||
name ="coldplug";
|
||||
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];
|
||||
dependencies = [
|
||||
devout
|
||||
mdevd
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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,9 +14,9 @@ in {
|
||||
type = liminix.lib.types.serviceDefn;
|
||||
};
|
||||
};
|
||||
imports = [ ../mdevd.nix ];
|
||||
imports = [ ../mdevd.nix ../service-trigger ];
|
||||
config.system.service.mount =
|
||||
let svc = liminix.callService ./service.nix {
|
||||
let svc = config.system.callService ./service.nix {
|
||||
partlabel = mkOption {
|
||||
type = types.str;
|
||||
example = "my-usb-stick";
|
||||
|
||||
+16
-15
@@ -1,26 +1,27 @@
|
||||
{
|
||||
liminix
|
||||
, uevent-watch
|
||||
, lib
|
||||
, svc
|
||||
}:
|
||||
{ partlabel, mountpoint, options, fstype }:
|
||||
let
|
||||
inherit (liminix.services) longrun oneshot;
|
||||
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}";
|
||||
mount_service = oneshot {
|
||||
name = "mount.${lib.escapeURL mountpoint}";
|
||||
timeout-up = 3600;
|
||||
up = "mount -t ${fstype} ${options_string} ${device} ${mountpoint}";
|
||||
down = "umount ${mountpoint}";
|
||||
controller = svc.uevent-rule.build {
|
||||
serviceName = name;
|
||||
symlink = device;
|
||||
terms = {
|
||||
partname = partlabel;
|
||||
devtype = "partition";
|
||||
};
|
||||
};
|
||||
in longrun {
|
||||
name = "watch-mount.${lib.strings.sanitizeDerivationName mountpoint}";
|
||||
isTrigger = true;
|
||||
buildInputs = [ mount_service ];
|
||||
|
||||
run = ''
|
||||
${uevent-watch}/bin/uevent-watch -s ${mount_service.name} -n ${device} partname=${partlabel} devtype=partition
|
||||
'';
|
||||
in oneshot {
|
||||
inherit name;
|
||||
timeout-up = 3600;
|
||||
up = "mount -t ${fstype} ${options_string} ${device} ${mountpoint}";
|
||||
down = "umount ${mountpoint}";
|
||||
inherit controller;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
{
|
||||
liminix
|
||||
, ifwait
|
||||
, serviceFns
|
||||
, lib
|
||||
}:
|
||||
|
||||
@@ -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 ];
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
{
|
||||
liminix
|
||||
, ifwait
|
||||
, serviceFns
|
||||
, lib
|
||||
}:
|
||||
{ enableIPv4, enableIPv6 }:
|
||||
|
||||
@@ -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 ''
|
||||
|
||||
@@ -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}
|
||||
'';
|
||||
|
||||
@@ -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)
|
||||
|
||||
+9
-9
@@ -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
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
, ...
|
||||
}:
|
||||
let
|
||||
inherit (lib) mkIf mkOption types;
|
||||
inherit (lib) mkIf;
|
||||
o = config.system.outputs;
|
||||
in
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
, ...
|
||||
}:
|
||||
let
|
||||
inherit (lib) mkIf mkOption types;
|
||||
inherit (lib) mkIf;
|
||||
o = config.system.outputs;
|
||||
in
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
}:
|
||||
let
|
||||
inherit (lib) mkEnableOption mkOption mkIf types;
|
||||
inherit (pkgs) runCommand callPackage writeText;
|
||||
inherit (pkgs) runCommand;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
, ...
|
||||
}:
|
||||
let
|
||||
inherit (lib) mkIf mkOption types;
|
||||
inherit (lib) mkIf;
|
||||
o = config.system.outputs;
|
||||
in
|
||||
{
|
||||
|
||||
@@ -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" {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
, ...
|
||||
}:
|
||||
let
|
||||
inherit (lib) mkOption types concatStringsSep;
|
||||
inherit (lib) mkOption types;
|
||||
o = config.system.outputs;
|
||||
cfg = config.tplink-safeloader;
|
||||
in {
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
, ...
|
||||
}:
|
||||
let
|
||||
inherit (pkgs) liminix;
|
||||
inherit (lib) mkIf mkOption types concatStringsSep optionalString;
|
||||
in
|
||||
{
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
{
|
||||
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 = no
|
||||
max redials = 1
|
||||
'';
|
||||
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;
|
||||
timeout-up = 40 * 1000;
|
||||
}
|
||||
@@ -9,6 +9,8 @@
|
||||
{ interface, ppp-options }:
|
||||
let
|
||||
inherit (liminix.services) longrun;
|
||||
lcp-echo-interval = 4;
|
||||
lcp-echo-failure = 3;
|
||||
name = "${interface.name}.pppoe";
|
||||
ip-up = writeAshScript "ip-up" {} ''
|
||||
. ${serviceFns}
|
||||
@@ -37,15 +39,19 @@ let
|
||||
"ipparam" name
|
||||
"nodetach"
|
||||
"usepeerdns"
|
||||
"lcp-echo-interval" (builtins.toString lcp-echo-interval)
|
||||
"lcp-echo-failure" (builtins.toString lcp-echo-failure)
|
||||
"logfd" "2"
|
||||
];
|
||||
in
|
||||
longrun {
|
||||
inherit name;
|
||||
run = ''
|
||||
. ${serviceFns}
|
||||
${ppp}/bin/pppd pty "${pppoe}/bin/pppoe -I $(output ${interface} ifname)" ${lib.concatStringsSep " " ppp-options'}
|
||||
. ${serviceFns}
|
||||
echo Starting pppoe, pppd pid is $$
|
||||
exec ${ppp}/bin/pppd pty "${pppoe}/bin/pppoe -T ${builtins.toString (4 * lcp-echo-interval)} -I $(output ${interface} ifname)" ${lib.concatStringsSep " " ppp-options'}
|
||||
'';
|
||||
notification-fd = 10;
|
||||
timeout-up = (10 + lcp-echo-failure * lcp-echo-interval) * 1000;
|
||||
dependencies = [ interface ];
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
let
|
||||
svc = config.system.service;
|
||||
cfg = config.profile.gateway;
|
||||
inherit (lib) mkOption mkEnableOption mkIf mdDoc types optional optionals;
|
||||
inherit (lib) mkOption mkEnableOption mkIf types;
|
||||
inherit (pkgs) liminix serviceFns;
|
||||
inherit (liminix.services) bundle oneshot;
|
||||
hostaps =
|
||||
|
||||
@@ -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;
|
||||
|
||||
+2
-7
@@ -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 = {
|
||||
|
||||
+39
-3
@@ -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;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{ config, pkgs, lib, ... } :
|
||||
{ config, pkgs, ... } :
|
||||
{
|
||||
config = {
|
||||
programs.busybox = {
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -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}";
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
config
|
||||
, pkgs
|
||||
, lib
|
||||
, ...
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (pkgs) liminix;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
{
|
||||
liminix
|
||||
, dropbear
|
||||
, serviceFns
|
||||
, lib
|
||||
}:
|
||||
p :
|
||||
|
||||
+1
-3
@@ -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";
|
||||
|
||||
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
+11
-5
@@ -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 ? []}:
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
{ lib, pkgs, config, ...}:
|
||||
let
|
||||
inherit (lib) mkOption types;
|
||||
inherit (pkgs.liminix.services) oneshot;
|
||||
inherit (pkgs) liminix;
|
||||
in
|
||||
{
|
||||
|
||||
+1
-2
@@ -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/
|
||||
|
||||
+31
-20
@@ -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,7 +74,6 @@ extraPkgs // {
|
||||
# should texinfo be in nativeBuildInputs instead of
|
||||
# buildInputs?
|
||||
texinfo = null;
|
||||
|
||||
};
|
||||
|
||||
# luarocks wants a cross-compiled cmake (which seems like a bug,
|
||||
@@ -186,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;
|
||||
@@ -200,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 {
|
||||
@@ -224,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
|
||||
@@ -245,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 ];
|
||||
@@ -268,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;
|
||||
@@ -279,5 +291,4 @@ extraPkgs // {
|
||||
translateManpages = false;
|
||||
capabilitiesSupport = false;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
fennel
|
||||
, stdenv
|
||||
, linotify
|
||||
, lua
|
||||
, lualinux
|
||||
, cpio
|
||||
fennel,
|
||||
stdenv,
|
||||
linotify,
|
||||
lua,
|
||||
lualinux,
|
||||
cpio,
|
||||
}:
|
||||
let pname = "anoia";
|
||||
in stdenv.mkDerivation {
|
||||
|
||||
+58
-57
@@ -1,7 +1,4 @@
|
||||
{
|
||||
callPackage
|
||||
, lib
|
||||
}:
|
||||
{ callPackage, lib }:
|
||||
let
|
||||
typeChecked = caller: type: value:
|
||||
let
|
||||
@@ -11,11 +8,11 @@ let
|
||||
in (mergeDefinitions [] type' defs).mergedValue;
|
||||
in {
|
||||
liminix = {
|
||||
builders = {
|
||||
squashfs = callPackage ./liminix-tools/builders/squashfs.nix {};
|
||||
dtb = callPackage ./kernel/dtb.nix {};
|
||||
uimage = callPackage ./kernel/uimage.nix {};
|
||||
kernel = callPackage ./kernel {};
|
||||
builders = {
|
||||
squashfs = callPackage ./liminix-tools/builders/squashfs.nix { };
|
||||
dtb = callPackage ./kernel/dtb.nix { };
|
||||
uimage = callPackage ./kernel/uimage.nix { };
|
||||
kernel = callPackage ./kernel { };
|
||||
};
|
||||
callService = path : parameters :
|
||||
let pkg = callPackage path {};
|
||||
@@ -27,7 +24,7 @@ in {
|
||||
s = pkg (checkTypes parameters
|
||||
(builtins.removeAttrs args ["dependencies"]));
|
||||
in s.overrideAttrs (o: {
|
||||
dependencies = (builtins.map (d: d.name) dependencies) ++ o.dependencies;
|
||||
dependencies = dependencies ++ o.dependencies;
|
||||
buildInputs = dependencies ++ o.buildInputs;
|
||||
});
|
||||
};
|
||||
@@ -49,68 +46,72 @@ in {
|
||||
};
|
||||
inherit typeChecked;
|
||||
};
|
||||
networking = callPackage ./liminix-tools/networking {};
|
||||
services = callPackage ./liminix-tools/services {};
|
||||
networking = callPackage ./liminix-tools/networking { };
|
||||
services = callPackage ./liminix-tools/services { };
|
||||
};
|
||||
|
||||
# please keep the rest of this list alphabetised :-)
|
||||
|
||||
anoia = callPackage ./anoia {};
|
||||
devout = callPackage ./devout {};
|
||||
fennel = callPackage ./fennel {};
|
||||
fennelrepl = callPackage ./fennelrepl {};
|
||||
firewallgen = callPackage ./firewallgen {};
|
||||
firmware-utils = callPackage ./firmware-utils {};
|
||||
gen_init_cpio = callPackage ./gen_init_cpio {};
|
||||
go-l2tp = callPackage ./go-l2tp {};
|
||||
hi = callPackage ./hi {};
|
||||
ifwait = callPackage ./ifwait {};
|
||||
initramfs-peek = callPackage ./initramfs-peek {};
|
||||
kernel-backport = callPackage ./kernel-backport {};
|
||||
kmodloader = callPackage ./kmodloader {};
|
||||
levitate = callPackage ./levitate {};
|
||||
libubootenv = callPackage ./libubootenv {};
|
||||
linotify = callPackage ./linotify {};
|
||||
lualinux = callPackage ./lualinux {};
|
||||
anoia = callPackage ./anoia { };
|
||||
devout = callPackage ./devout { };
|
||||
fennel = callPackage ./fennel { };
|
||||
fennelrepl = callPackage ./fennelrepl { };
|
||||
firewallgen = callPackage ./firewallgen { };
|
||||
firmware-utils = callPackage ./firmware-utils { };
|
||||
gen_init_cpio = callPackage ./gen_init_cpio { };
|
||||
go-l2tp = callPackage ./go-l2tp { };
|
||||
hi = callPackage ./hi { };
|
||||
ifwait = callPackage ./ifwait { };
|
||||
initramfs-peek = callPackage ./initramfs-peek { };
|
||||
kernel-backport = callPackage ./kernel-backport { };
|
||||
kmodloader = callPackage ./kmodloader { };
|
||||
levitate = callPackage ./levitate { };
|
||||
libubootenv = callPackage ./libubootenv { };
|
||||
linotify = callPackage ./linotify { };
|
||||
lualinux = callPackage ./lualinux { };
|
||||
|
||||
# we need to build real lzma instead of using xz, because the lzma
|
||||
# decoder in u-boot doesn't understand streaming lzma archives
|
||||
# ("Stream with EOS marker is not supported") and xz can't create
|
||||
# non-streaming ones. See
|
||||
# https://sourceforge.net/p/squashfs/mailman/message/26599379/
|
||||
lzma = callPackage ./lzma {};
|
||||
lzma = callPackage ./lzma { };
|
||||
|
||||
mac80211 = callPackage ./mac80211 {};
|
||||
zyxel-bootconfig = callPackage ./zyxel-bootconfig {};
|
||||
min-collect-garbage = callPackage ./min-collect-garbage {};
|
||||
min-copy-closure = callPackage ./min-copy-closure {};
|
||||
minisock = callPackage ./minisock {};
|
||||
nellie = callPackage ./nellie {};
|
||||
netlink-lua = callPackage ./netlink-lua {};
|
||||
odhcp-script = callPackage ./odhcp-script {};
|
||||
odhcp6c = callPackage ./odhcp6c {};
|
||||
openwrt = callPackage ./openwrt {};
|
||||
ppp = callPackage ./ppp {};
|
||||
pppoe = callPackage ./pppoe {};
|
||||
preinit = callPackage ./preinit {};
|
||||
pseudofile = callPackage ./pseudofile {};
|
||||
routeros = callPackage ./routeros {};
|
||||
run-liminix-vm = callPackage ./run-liminix-vm {};
|
||||
s6-init-bin = callPackage ./s6-init-bin {};
|
||||
s6-rc-database = callPackage ./s6-rc-database {};
|
||||
mac80211 = callPackage ./mac80211 { };
|
||||
zyxel-bootconfig = callPackage ./zyxel-bootconfig { };
|
||||
min-collect-garbage = callPackage ./min-collect-garbage { };
|
||||
min-copy-closure = callPackage ./min-copy-closure { };
|
||||
minisock = callPackage ./minisock { };
|
||||
nellie = callPackage ./nellie { };
|
||||
netlink-lua = callPackage ./netlink-lua { };
|
||||
odhcp-script = callPackage ./odhcp-script { };
|
||||
odhcp6c = callPackage ./odhcp6c { };
|
||||
openwrt = callPackage ./openwrt { };
|
||||
ppp = callPackage ./ppp { };
|
||||
pppoe = callPackage ./pppoe { };
|
||||
preinit = callPackage ./preinit { };
|
||||
pseudofile = callPackage ./pseudofile { };
|
||||
routeros = callPackage ./routeros { };
|
||||
run-liminix-vm = callPackage ./run-liminix-vm { };
|
||||
s6-init-bin = callPackage ./s6-init-bin { };
|
||||
s6-rc-database = callPackage ./s6-rc-database { };
|
||||
s6-rc-round-robin = callPackage ./s6-rc-round-robin { };
|
||||
s6-rc-up-tree = callPackage ./s6-rc-up-tree { };
|
||||
|
||||
# schnapps is written by Turris and provides a high-level interface
|
||||
# to btrfs snapshots. It may be useful on the Turris Omnia to
|
||||
# install Liminix while retaining the ability to rollback to the
|
||||
# vendor OS, or even to derisk Liminix updates on that device
|
||||
schnapps = callPackage ./schnapps {};
|
||||
schnapps = callPackage ./schnapps { };
|
||||
|
||||
serviceFns = callPackage ./service-fns {};
|
||||
swconfig = callPackage ./swconfig {};
|
||||
systemconfig = callPackage ./systemconfig {};
|
||||
tufted = callPackage ./tufted {};
|
||||
uevent-watch = callPackage ./uevent-watch {};
|
||||
writeAshScript = callPackage ./write-ash-script {};
|
||||
writeFennel = callPackage ./write-fennel {};
|
||||
writeFennelScript = callPackage ./write-fennel-script {};
|
||||
serviceFns = callPackage ./service-fns { };
|
||||
swconfig = callPackage ./swconfig { };
|
||||
systemconfig = callPackage ./systemconfig { };
|
||||
tufted = callPackage ./tufted { };
|
||||
uevent-watch = callPackage ./uevent-watch { };
|
||||
usb-modeswitch = callPackage ./usb-modeswitch { };
|
||||
writeAshScript = callPackage ./write-ash-script { };
|
||||
writeAshScriptBin = callPackage ./write-ash-script/bin.nix { };
|
||||
writeFennel = callPackage ./write-fennel { };
|
||||
writeFennelScript = callPackage ./write-fennel-script { };
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
{
|
||||
lua
|
||||
, nellie
|
||||
, writeFennel
|
||||
, anoia
|
||||
, fennel
|
||||
, stdenv
|
||||
, fennelrepl
|
||||
, lualinux
|
||||
nellie,
|
||||
writeFennel,
|
||||
anoia,
|
||||
fennel,
|
||||
stdenv,
|
||||
fennelrepl,
|
||||
lualinux,
|
||||
}:
|
||||
stdenv.mkDerivation {
|
||||
name = "devout";
|
||||
|
||||
+71
-22
@@ -1,3 +1,4 @@
|
||||
(local { : dirname : merge } (require :anoia))
|
||||
(local ll (require :lualinux))
|
||||
(local {
|
||||
: AF_LOCAL
|
||||
@@ -21,28 +22,62 @@
|
||||
(..
|
||||
(string.format "%s@%s\0" e.action e.path)
|
||||
(table.concat
|
||||
(icollect [k v (pairs e.attributes)]
|
||||
(icollect [k v (pairs e.properties)]
|
||||
(string.format "%s=%s" (string.upper k) v ))
|
||||
"\n")))
|
||||
|
||||
(fn attrs-match? [event expected]
|
||||
(accumulate [match? true
|
||||
name value (pairs expected)]
|
||||
(and match? (= value (event:attr name)))))
|
||||
|
||||
(fn ancestor-attrs-match? [event expected]
|
||||
(accumulate [match? true
|
||||
name value (pairs expected)]
|
||||
(and match? (= value (event:ancestor-attr name)))))
|
||||
|
||||
(fn event-matches? [e terms]
|
||||
(accumulate [match? true
|
||||
name value (pairs terms)]
|
||||
(and match? (= value (. e.attributes name)))))
|
||||
(and match?
|
||||
(case name
|
||||
:attr (attrs-match? e value)
|
||||
:attrs (ancestor-attrs-match? e value)
|
||||
other (= value (. e.properties name))))))
|
||||
|
||||
(fn read-if-exists [pathname]
|
||||
(match (ll.open pathname 0 0)
|
||||
fd (let [s (ll.read fd 4096)
|
||||
s1 (string.gsub s "[ \n]*(.-)[ \n]*" "%1")]
|
||||
(ll.close fd)
|
||||
s1)
|
||||
nil nil))
|
||||
|
||||
(fn event-ancestor-attr [event name]
|
||||
(fn walk-up [sys-path path name]
|
||||
(when path
|
||||
(or (read-if-exists (.. sys-path "/" path "/" name))
|
||||
(walk-up sys-path (dirname path) name))))
|
||||
(walk-up event.sys-path event.path name))
|
||||
|
||||
(fn event-attr [event name]
|
||||
(read-if-exists (.. event.sys-path "/" event.path "/" name)))
|
||||
|
||||
(fn parse-event [s]
|
||||
(let [at (string.find s "@" 1 true)
|
||||
(nl nxt) (string.find s "\0" 1 true)
|
||||
attributes
|
||||
properties
|
||||
(collect [k v (string.gmatch
|
||||
(string.sub s (+ 1 nxt))
|
||||
"(%g-)=(%g+)")]
|
||||
(k:lower) v)]
|
||||
{ : attributes
|
||||
{ : properties
|
||||
:path (string.sub s (+ at 1) (- nl 1))
|
||||
:action (string.sub s 1 (- at 1))
|
||||
:format format-event
|
||||
:matches? event-matches?
|
||||
:attr event-attr
|
||||
:ancestor-attr event-ancestor-attr
|
||||
}))
|
||||
|
||||
(fn find-in-database [db terms]
|
||||
@@ -52,24 +87,28 @@
|
||||
(doto found (table.insert e))
|
||||
found)))
|
||||
|
||||
(fn record-event [db subscribers str]
|
||||
(let [e (parse-event str)]
|
||||
(match e.action
|
||||
:add (tset db e.path e)
|
||||
:change (tset db e.path e)
|
||||
;; should we do something for bind?
|
||||
:remove (tset db e.path nil)
|
||||
)
|
||||
(each [_ { : terms : callback } (pairs subscribers)]
|
||||
(if (e:matches? terms) (callback e)))
|
||||
e))
|
||||
(fn record-event [db subscribers e]
|
||||
(match e.action
|
||||
:add (tset db e.path e)
|
||||
:change (tset db e.path e)
|
||||
;; should we do something for bind?
|
||||
:remove (tset db e.path nil)
|
||||
)
|
||||
(each [_ { : terms : callback } (pairs subscribers)]
|
||||
(if (e:matches? terms) (callback e)))
|
||||
e)
|
||||
|
||||
(fn database []
|
||||
(fn database [options]
|
||||
(let [db {}
|
||||
subscribers []]
|
||||
subscribers []
|
||||
{ : sys-path } (or options {:sys-path "/sys" })]
|
||||
{
|
||||
:find (fn [_ terms] (find-in-database db terms))
|
||||
:add (fn [_ event-string] (when event-string (record-event db subscribers event-string)))
|
||||
:add (fn [_ event-string]
|
||||
(when event-string
|
||||
(let [e (doto (parse-event event-string)
|
||||
(tset :sys-path sys-path))]
|
||||
(record-event db subscribers e))))
|
||||
:at-path (fn [_ path] (. db path))
|
||||
:subscribe (fn [_ id callback terms]
|
||||
(let [past-events (find-in-database db terms)]
|
||||
@@ -108,8 +147,16 @@
|
||||
(values fd (if (> revent 0) revent nil)))))
|
||||
|
||||
(fn parse-terms [str]
|
||||
(collect [n (string.gmatch (str:gsub "\n+$" "") "([^ ]+)")]
|
||||
(string.match n "(.-)=(.+)")))
|
||||
(let [keys {}
|
||||
attr {}
|
||||
attrs {}]
|
||||
(each [term (string.gmatch (str:gsub "\n+$" "") "([^ ]+)")]
|
||||
(let [(k v) (string.match term "(.-)=(.+)")]
|
||||
(match (string.match k "(.+)%.(.+)")
|
||||
("attrs" a) (tset attrs a v)
|
||||
("attr" a) (tset attr a v)
|
||||
nil (tset keys k v))))
|
||||
(merge keys {: attr : attrs})))
|
||||
|
||||
(fn handle-client [db client]
|
||||
(match (ll.read client)
|
||||
@@ -131,7 +178,6 @@
|
||||
AF_NETLINK 0 0 groups)))
|
||||
(nil errno) (values nil errno)))
|
||||
|
||||
|
||||
(fn event-loop []
|
||||
(let [fds {}]
|
||||
{
|
||||
@@ -170,4 +216,7 @@
|
||||
(ll.poll pollfds 5000)
|
||||
(loop:feed (unpack-pollfds pollfds))))))
|
||||
|
||||
{ : database : run : event-loop : parse-event }
|
||||
{ : database : run : event-loop : parse-event
|
||||
|
||||
: parse-terms
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
0x0c0330
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
64
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user