ppp modules: permit (mostly) same params for l2tp as pppoe

this also means that l2tp can use secrets for username/password
This commit is contained in:
Daniel Barlow 2024-08-21 23:10:28 +01:00
parent 531cb113be
commit a6128955e7
3 changed files with 95 additions and 28 deletions

View File

@ -1,12 +1,18 @@
## PPP
## ===
##
## A PPPoE (PPP over Ethernet) configuration to address the case where
## your Liminix device is connected to an upstream network using
## ``ppoe`` (PPP over Ethernet) provides a service to address the case
## where your Liminix device is connected to an upstream network using
## PPPoE. This is typical for UK broadband connections where the
## physical connection is made by OpenReach ("Fibre To The X") and
## common in some other localities as well: ask your ISP if this is
## common in some other localities as well: check with your ISP if this is
## you.
##
## ``l2tp`` (Layer 2 Tunelling Protocol) provides a service that
## tunnels PPP over the Internet. This may be used by some ISPs in
## conjunction with a DHCP uplink, or other more creative forms of
## network connection
{ lib, pkgs, config, ...}:
let
@ -34,11 +40,13 @@ in {
description = "ethernet interface to run PPPoE over";
};
username = mkOption {
type = liminix.lib.types.replacable;
type = types.nullOr liminix.lib.types.replacable;
default = null;
description = "username";
};
password = mkOption {
type = liminix.lib.types.replacable;
type = types.nullOr liminix.lib.types.replacable;
default = null;
description = "password";
};
lcpEcho = {
@ -74,6 +82,38 @@ in {
type = types.str;
description = "hostname or address of the L2TP network server";
};
username = mkOption {
type = types.nullOr liminix.lib.types.replacable;
default = null;
description = "username";
};
password = mkOption {
type = types.nullOr liminix.lib.types.replacable;
default = null;
description = "password";
};
lcpEcho = {
adaptive = mkOption {
description = "send LCP echo-request frames only if no traffic was received from the peer since the last echo-request was sent";
type = types.bool;
default = true;
};
interval = mkOption {
type = types.nullOr types.int;
default = 3;
description = "send an LCP echo-request frame to the peer every n seconds";
};
failure = mkOption {
type = types.nullOr types.int;
default = 3;
description = "terminate connection if n LCP echo-requests are sent without receiving a valid LCP echo-reply";
};
};
debug = mkOption {
description = "log the contents of all control packets sent or received";
default = false;
type = types.bool;
};
ppp-options = mkOption {
type = types.listOf types.str;
description = "options supplied on ppp command line";

View File

@ -1,15 +1,22 @@
{
liminix
, lib
, output-template
, writeAshScript
, writeText
, serviceFns
, xl2tpd
} :
{ lns, ppp-options }:
{ lns,
ppp-options,
lcpEcho,
username,
password,
debug
}:
let
inherit (liminix.services) longrun;
lcp-echo-interval = 4;
lcp-echo-failure = 3;
inherit (lib) optional optionals escapeShellArgs concatStringsSep;
name = "${lns}.l2tp";
ip-up = writeAshScript "ip-up" {} ''
. ${serviceFns}
@ -32,35 +39,55 @@ let
)
echo >/proc/self/fd/10
'';
ppp-options' = ppp-options ++ [
"ip-up-script" ip-up
"ipv6-up-script" ip6-up
"ipparam" name
"nodetach"
"usepeerdns"
"lcp-echo-interval" (builtins.toString lcp-echo-interval)
"lcp-echo-failure" (builtins.toString lcp-echo-failure)
"logfd" "2"
];
literal_or_output =
let v = o: ({
string = builtins.toJSON;
int = builtins.toJSON;
set = (o: "output(${builtins.toJSON o.service}, ${builtins.toJSON o.path})");
}.${builtins.typeOf o}) o;
in o: "{{ ${v o} }}";
ppp-options' =
["+ipv6" "noauth"]
++ optional debug "debug"
++ optionals (username != null) ["name" (literal_or_output username)]
++ optionals (password != null) ["password" (literal_or_output password)]
++ optional lcpEcho.adaptive "lcp-echo-adaptive"
++ optionals (lcpEcho.interval != null)
["lcp-echo-interval" (builtins.toString lcpEcho.interval)]
++ optionals (lcpEcho.failure != null)
["lcp-echo-failure" (builtins.toString lcpEcho.failure)]
++ 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'}
pppoptfile = /run/${name}/ppp-options
autodial = yes
redial = yes
redial timeout = 1
max redials = 2 # this gives 1 actual retry, as xl2tpd can't count
'';
control = "/run/xl2tpd/control-${name}";
control = "/run/${name}/control";
in
longrun {
inherit name;
run = ''
mkdir -p /run/xl2tpd
mkdir -p /run/${name}
chmod 0700 /run/${name}
touch ${control}
in_outputs $name
exec ${xl2tpd}/bin/xl2tpd -D -p /run/xl2tpd/${name}.pid -c ${conf} -C ${control}
in_outputs ${name}
echo ${escapeShellArgs ppp-options'} | ${output-template}/bin/output-template '{{' '}}' > /run/${name}/ppp-options
exec ${xl2tpd}/bin/xl2tpd -D -p /run/${name}/${name}.pid -c ${conf} -C ${control}
'';
notification-fd = 10;
}

View File

@ -47,7 +47,8 @@ let
set = (o: "output(${builtins.toJSON o.service}, ${builtins.toJSON o.path})");
}.${builtins.typeOf o}) o;
in o: "{{ ${v o} }}";
ppp-options' = ["+ipv6" "noauth"]
ppp-options' =
["+ipv6" "noauth"]
++ optional debug "debug"
++ optionals (username != null) ["name" (literal_or_output username)]
++ optionals (password != null) ["password" (literal_or_output password)]
@ -69,12 +70,11 @@ in
longrun {
inherit name;
run = ''
. ${serviceFns}
mkdir -p /run/${name}
chmod 0700 /run/${name}
echo ${escapeShellArgs ppp-options'} | ${output-template}/bin/output-template '{{' '}}' > /run/${name}/${name}.conf
echo Starting pppoe, pppd pid is $$
exec ${ppp}/bin/pppd pty "${pppoe}/bin/pppoe ${timeoutOpt} -I $(output ${interface} ifname)" file /run/${name}/${name}.conf
in_outputs ${name}
echo ${escapeShellArgs ppp-options'} | ${output-template}/bin/output-template '{{' '}}' > /run/${name}/ppp-options
exec ${ppp}/bin/pppd pty "${pppoe}/bin/pppoe ${timeoutOpt} -I $(output ${interface} ifname)" file /run/${name}/ppp-options
'';
notification-fd = 10;
timeout-up = if lcpEcho.failure != null