commit a6128955e70b330e09a1a9b2047f3d4ea9cf6a6d
parent 531cb113be45b9726806a2add4236394569ce600
Author: Daniel Barlow <dan@telent.net>
Date: Wed, 21 Aug 2024 23:10:28 +0100
ppp modules: permit (mostly) same params for l2tp as pppoe
this also means that l2tp can use secrets for username/password
Diffstat:
3 files changed, 95 insertions(+), 28 deletions(-)
diff --git a/modules/ppp/default.nix b/modules/ppp/default.nix
@@ -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";
diff --git a/modules/ppp/l2tp.nix b/modules/ppp/l2tp.nix
@@ -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;
}
diff --git a/modules/ppp/pppoe.nix b/modules/ppp/pppoe.nix
@@ -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