dotfiles/nixos/tests/hel/pppoe-server.nix
magic_rb c234160635
Border router, hela
Signed-off-by: magic_rb <magic_rb@redalder.org>
2024-09-04 22:39:43 +02:00

219 lines
6.3 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
mkIf
;
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`.
'';
};
readyOnConnect = mkOption {
type = with types; bool;
default = false;
description = ''
Whether systemd should treat this service as starting, until a client
connects to the PPPoE server. Useful in tests.
'';
};
};
config = {
pppdSettings = {
ip-up-script = singleton (pkgs.writeShellScript "ip-up-${name}" ''
{
echo "Signalling ready to systemd"
${optionalString config.readyOnConnect "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"
${optionalString config.readyOnConnect "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 =
if v.readyOnConnect
then "notify"
else "simple";
NotifyAccess = mkIf v.readyOnConnect "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}"))
);
TimeoutStartSec = "infinity";
};
}
);
}