# PPPoE uplink for IPv4. pppd owns the session (address, default route); the # VLAN device it runs on is created in networking.nix. { config, lib, pkgs, ... }: let cfg = config.router; wan = cfg.wan; pppoe = wan.ipv4.pppoe; # Device carrying the PPPoE session: the VLAN on the uplink, or the uplink itself. device = if pppoe.vlan == null then wan.interface else "${wan.interface}.${toString pppoe.vlan}"; # Unit that appears once udev has seen the device (VLAN devices are created # by networkd after boot has begun, so pppd must not start before it). deviceUnit = "sys-subsystem-net-devices-${lib.replaceStrings [ "-" ] [ "\\x2d" ] device}.device"; staticOptions = pkgs.writeText "router-pppoe-options" '' plugin pppoe.so nic-${device} ifname ${wan.ipv4.interface} user "${pppoe.username}" noauth hide-password defaultroute replacedefaultroute noipdefault ${ if wan.ipv6.enable && wan.ipv6.transport == "ppp" then "+ipv6\n ipv6cp-use-ipaddr" else "nodefaultroute6" } noccp mtu ${toString pppoe.mtu} mru ${toString pppoe.mtu} lcp-echo-interval 10 lcp-echo-failure 3 nodetach persist maxfail 0 holdoff 5 ''; prepare = pkgs.writeShellScript "router-pppoe-prepare" '' set -eu umask 077 password=$(cat ${lib.escapeShellArg (toString pppoe.passwordFile)}) # pppd option files use C-style escapes inside double quotes. password=''${password//\\/\\\\} password=''${password//\"/\\\"} { cat ${staticOptions} printf 'password "%s"\n' "$password" } > /run/router-pppoe/options ''; in { config = lib.mkIf (cfg.enable && wan.ipv4.type == "pppoe") { boot.kernelModules = [ "pppoe" "pppox" "ppp_generic" ]; # pppd refuses to start without a (possibly empty) system options file. environment.etc."ppp/options".text = ""; systemd.services.router-pppoe = { description = "PPPoE uplink (${device})"; wantedBy = [ "multi-user.target" ]; wants = [ deviceUnit ]; after = [ "network.target" "systemd-networkd.service" deviceUnit ]; serviceConfig = { RuntimeDirectory = "router-pppoe"; RuntimeDirectoryMode = "0700"; ExecStartPre = prepare; ExecStart = "${pkgs.ppp}/bin/pppd file /run/router-pppoe/options"; Restart = "always"; RestartSec = 5; }; }; }; }