dotfiles/nixos/tests/hel/pppoe-server.nix
magic_rb 0e7389fcbd
More network test work
Signed-off-by: magic_rb <magic_rb@redalder.org>
2024-08-14 15:59:24 +02:00

205 lines
5.8 KiB
Nix

{
config,
pkgs,
lib,
options,
...
}: let
inherit
(lib)
mkOption
types
flip
mapAttrs'
nameValuePair
concatStringsSep
concatMapStringsSep
pipe
optional
mapAttrsToList
filterAttrs
elem
mkPackageOption
attrNames
singleton
optionalString
;
cfg = config.services.pppoe-server;
in {
options.services.pppoe-server = mkOption {
default = {};
type = types.attrsOf (types.submodule ({
name,
config,
...
}: {
freeformType = with types;
oneOf [int str];
options = {
package =
mkPackageOption pkgs "rp-pppoe" {};
interface = mkOption {
type = types.str;
description = ''
Which interface should `pppoe-server' bind to, this interface must
be an L2 interface and pass PPPoE packets through unchanged.
`pppoe-server' initially broadcasts a PADI packet.
'';
};
localAddress = mkOption {
type = types.str;
description = ''
Which address should be assigned to the local PPP interface. Only
one such IP address per daemon is possible.
'';
};
startingRemoteAddress = mkOption {
type = types.nullOr types.str;
description = ''
Which starting address to utilize, `pppoe-server' will keep track
of assigned addresses and automatically reclaim them as clients
disconnect.
'';
default = null;
};
maxNumberOfConnections = mkOption {
type = types.int;
description = ''
The maximum number of concurrent connections to allow, also limits
the number of IP addresses and therefore the range, as a side
effect.
'';
default = 64;
};
remoteAddressFile = mkOption {
type = types.nullOr types.path;
description = ''
Reads the specified file fname which is a text file
consisting of one IP address per line. These IP addresses
will be assigned to clients. The number of sessions allowed
will equal the number of addresses found in the file.
The `remoteAddressFile' option overrides both
`startingRemoteAddress' and `maxNumberOfConnections'.
In addition to containing IP addresses, the pool file can
contain lines of the form:
- `a.b.c.d-e` which includes all IP addresses from`a.b.c.d` to
`a.b.c.e`.
For example, the line:
- `1.2.3.4-7` is equivalent to:
```
1.2.3.4
1.2.3.5
1.2.3.6
1.2.3.7
```
'';
default = null;
};
ifUpScript = mkOption {
type = with types; nullOr path;
description = ''
Script to run, when the `ppp` interface goes up.
'';
default = null;
};
ifDownScript = mkOption {
type = with types; nullOr path;
description = ''
Script to run, when the `ppp` interface goes down.
'';
default = null;
};
pppdSettings = mkOption {
type = with types; attrsOf (listOf (oneOf [str int path]));
default = {};
description = ''
Settings passed to PPPD after it is started by `pppoe-server`.
'';
};
};
config = {
pppdSettings = {
ip-up-script = singleton (pkgs.writeShellScript "ip-up-${name}" ''
{
echo "Signalling ready to systemd"
systemd-notify --ready
${optionalString (config.ifUpScript != null) config.ifUpScript}
} | logger -t pppd-ip-up
'');
ip-down-script = singleton (pkgs.writeShellScript "ip-down-${name}" ''
{
echo "Signalling stopping to systemd"
systemd-notify --stopping
${optionalString (config.ifDownScript != null) config.ifDownScript}
} | logger -t pppd-ip-down
'');
};
};
}));
};
config.systemd.services = flip mapAttrs' cfg (
n: v: let
pppdSettingsFile =
pkgs.writeText "pppd-${n}.conf"
((pipe v.pppdSettings [
(mapAttrsToList (n: v: n + " " + concatMapStringsSep " " toString v))
(concatStringsSep "\n")
])
+ "\n");
in
nameValuePair
"pppoe-server-${n}"
{
before = ["network.target"];
wants = ["network.target"];
after = ["network-pre.target" "ifstate.service"];
wantedBy = ["multi-user.target"];
path = [
pkgs.util-linux
];
serviceConfig = {
Type = "notify";
NotifyAccess = "all";
ExecStart =
"${v.package}/bin/pppoe-server "
+ concatStringsSep " " (
[
"-F"
"-k"
"-I ${v.interface}"
"-L ${v.localAddress}"
"-g ${v.package}/etc/ppp/plugins/rp-pppoe.so"
"-O ${pppdSettingsFile}"
]
++ optional (v.startingRemoteAddress != null)
"-R ${v.startingRemoteAddress}"
++ optional (v.maxNumberOfConnections != null)
"-N ${toString v.maxNumberOfConnections}"
++ optional (v.remoteAddressFile != null)
"-p ${v.remoteAddressFile}"
++ (flip mapAttrsToList
(filterAttrs (
n: _:
!(elem n (attrNames (options.services.pppoe-server.type.getSubOptions [])))
)
v)
(n: v: "-${n} ${toString v}"))
);
};
}
);
}