From c1835d97ee96031f61757b81d5e9d5120f0a65f5 Mon Sep 17 00:00:00 2001 From: Daniel Barlow Date: Sun, 25 Sep 2022 11:54:31 +0100 Subject: [PATCH] add pppoe --- README.md | 2 ++ overlay.nix | 46 ++++++++++++++++++++++++ pkgs/liminix-tools/default.nix | 1 + pkgs/liminix-tools/networking/pppoe.nix | 48 +++++++++++++++++++++++++ tests/pppoe/configuration.nix | 47 ++++++++++++++++++++++++ tests/pppoe/run.sh | 20 +++++++++++ 6 files changed, 164 insertions(+) create mode 100644 pkgs/liminix-tools/networking/pppoe.nix create mode 100644 tests/pppoe/configuration.nix create mode 100755 tests/pppoe/run.sh diff --git a/README.md b/README.md index ec457e5..9eac9ba 100644 --- a/README.md +++ b/README.md @@ -95,3 +95,5 @@ took full advantage of the basic application armoring features provided by the operating system. Indeed, only one or two models even came close, and no brand did well consistently across all models tested" + +* [A PPPoE Implementation for Linux](https://static.usenix.org/publications/library/proceedings/als00/2000papers/papers/full_papers/skoll/skoll_html/index.html): "Many DSL service providers use PPPoE for residential broadband Internet access. This paper briefly describes the PPPoE protocol, presents strategies for implementing it under Linux and describes in detail a user-space implementation of a PPPoE client." diff --git a/overlay.nix b/overlay.nix index bf6e47c..5dc9ef3 100644 --- a/overlay.nix +++ b/overlay.nix @@ -3,4 +3,50 @@ final: prev: { s6-init-files = final.callPackage ./pkgs/s6-init-files {}; strace = prev.strace.override { libunwind = null; }; liminix = final.callPackage ./pkgs/liminix-tools {}; + pppoe = prev.rpPPPoE.overrideAttrs (o: { + # use newer rp-pppoe, it builds cleanly + src = final.fetchFromGitHub { + owner = "dfskoll"; + repo = "rp-pppoe"; + rev = "7cfd8c0405d14cf1c8d799d41d8207fd707979c1"; + hash = "sha256-MFdCwNj8c52blxEuXH5ltT2yYDmKMH5MLUgtddZV25E="; + }; + }); + ppp = + (prev.ppp.override { + libpcap = null; + }).overrideAttrs (o : { + stripAllList = [ "bin" ]; + buildInputs = []; + + # patches = + # o.patches ++ + # [(final.fetchpatch { + # name = "ipv6-script-options.patch"; + # url = "https://github.com/ppp-project/ppp/commit/874c2a4a9684bf6938643c7fa5ff1dd1cf80aea4.patch"; + # sha256 = "sha256-K46CKpDpm1ouj6jFtDs9IUMHzlRMRP+rMPbMovLy3o4="; + # })]; + + postPatch = '' + sed -i -e 's@_PATH_VARRUN@"/run/"@' pppd/main.c + sed -i -e 's@^FILTER=y@# FILTER unset@' pppd/Makefile.linux + sed -i -e 's/-DIPX_CHANGE/-UIPX_CHANGE/g' pppd/Makefile.linux + ''; + buildPhase = '' + runHook preBuild + make -C pppd CC=$CC USE_TDB= HAVE_MULTILINK= USE_EAPTLS= USE_CRYPT=y + make -C pppd/plugins/pppoe CC=$CC + make -C pppd/plugins/pppol2tp CC=$CC + runHook postBuild; + ''; + installPhase = '' + runHook preInstall + mkdir -p $out/bin $out/lib/pppd/2.4.9 + cp pppd/pppd pppd/plugins/pppoe/pppoe-discovery $out/bin + cp pppd/plugins/pppoe/pppoe.so $out/lib/pppd/2.4.9 + cp pppd/plugins/pppol2tp/{open,pppo}l2tp.so $out/lib/pppd/2.4.9 + runHook postInstall + ''; + postFixup = ""; + }); } diff --git a/pkgs/liminix-tools/default.nix b/pkgs/liminix-tools/default.nix index 46852ee..3d5858c 100644 --- a/pkgs/liminix-tools/default.nix +++ b/pkgs/liminix-tools/default.nix @@ -77,6 +77,7 @@ in { name = "${interface.device}.odhcp"; run = "odhcpcd ${interface.device}"; }; + pppoe = callPackage ./networking/pppoe.nix {}; }; services = { inherit longrun oneshot bundle target; diff --git a/pkgs/liminix-tools/networking/pppoe.nix b/pkgs/liminix-tools/networking/pppoe.nix new file mode 100644 index 0000000..b98d9c4 --- /dev/null +++ b/pkgs/liminix-tools/networking/pppoe.nix @@ -0,0 +1,48 @@ +{ + liminix +, lib +, busybox +, ppp +, pppoe +, writeShellScript +} : +let + inherit (liminix.services) longrun; + ip-up = writeShellScript "ip-up" '' +action=$1 +env > /run/udhcp.values + +set_address() { + ip address replace $ip/$mask dev $interface + mkdir -p data/outputs + for i in lease mask ip router siaddr dns serverid subnet opt53 interface ; do + echo ''${!i} > data/outputs/$i + done +} +case $action in + deconfig) + ip address flush $interface + ip link set up dev $interface + ;; + bound) + # this doesn't actually replace, it adds a new address. + set_address + ;; + renew) + set_address + ;; + nak) + echo "received NAK on $interface" + ;; +esac +''; + +in +interface: { + synchronous ? false +, ppp-options ? [] +, ... +} @ args: longrun { + name = "${interface.device}.ppppoe"; + run = "${ppp}/bin/pppd pty '${pppoe}/bin/pppoe -I ${interface.device}' ${lib.concatStringsSep " " ppp-options}" ; +} diff --git a/tests/pppoe/configuration.nix b/tests/pppoe/configuration.nix new file mode 100644 index 0000000..75193ed --- /dev/null +++ b/tests/pppoe/configuration.nix @@ -0,0 +1,47 @@ +{ config, pkgs, ... } : +let + inherit (pkgs.liminix.networking) interface address pppoe; + inherit (pkgs.liminix.services) oneshot longrun bundle target output; +in rec { + services.loopback = + let iface = interface { type = "loopback"; device = "lo";}; + in bundle { + name = "loopback"; + contents = [ + (address iface { family = "inet4"; addr ="127.0.0.1";}) + (address iface { family = "inet6"; addr ="::1";}) + ]; + }; + + kernel.config = { + "PPP" = "y"; + "PPPOE" = "y"; + "PPPOL2TP" = "y"; + }; + + services.pppoe = + let iface = interface { type = "hardware"; device = "eth0"; }; + in pppoe iface {}; + + services.defaultroute4 = + let iface = services.pppoe; + in oneshot { + name = "defaultroute4"; + up = '' + ip route add default gw $(cat ${output iface "address"}) + echo "1" > /sys/net/ipv4/$(cat ${output iface "ifname"}) + ''; + down = '' + ip route del default gw $(cat ${output iface "address"}) + echo "0" > /sys/net/ipv4/$(cat ${output iface "ifname"}) + ''; + dependencies = [iface]; + }; + + services.default = target { + name = "default"; + contents = with services; [ loopback defaultroute4 ]; + }; + + systemPackages = [ pkgs.hello ] ; +} diff --git a/tests/pppoe/run.sh b/tests/pppoe/run.sh new file mode 100755 index 0000000..4c87b63 --- /dev/null +++ b/tests/pppoe/run.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env sh + + +set -e + +cleanup(){ + echo "do cleanup"; +} +trap cleanup EXIT +trap 'echo "command $(eval echo $BASH_COMMAND) failed with exit code $?"; exit $?' ERR + +NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM=1 nix-build '' -I liminix-config=./configuration.nix --arg device "import " -A outputs.default $* + + +if ! ( echo "cont" | socat - unix-connect:../support/ppp-server/qemu-monitor); then + echo "need pppoe server running" + exit 1 +fi + +../../scripts/run-qemu.sh result/vmlinux result/squashfs