From 1b1632dfb5cc363563e97a9b950a825b54cc8ece Mon Sep 17 00:00:00 2001 From: tv Date: Wed, 9 Nov 2022 15:44:06 +0100 Subject: tv iptables: admit wiregrill --- tv/3modules/iptables.nix | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'tv/3modules') diff --git a/tv/3modules/iptables.nix b/tv/3modules/iptables.nix index c4bf4644..5b36c5ac 100644 --- a/tv/3modules/iptables.nix +++ b/tv/3modules/iptables.nix @@ -34,6 +34,10 @@ with import ./lib; type = with types; listOf str; default = []; }; + filter.Wiregrill = mkOption { + type = with types; listOf str; + default = []; + }; }; }; }; @@ -66,6 +70,16 @@ with import ./lib; default = []; }; + input-wiregrill-accept-tcp = mkOption { + type = with types; listOf (either int str); + default = []; + }; + + input-wiregrill-accept-udp = mkOption { + type = with types; listOf (either int str); + default = []; + }; + extra = mkOption { default = {}; type = extraTypes.rules; @@ -141,6 +155,7 @@ with import ./lib; :FORWARD DROP [0:0] :OUTPUT ACCEPT [0:0] :Retiolum - [0:0] + :Wiregrill - [0:0] ${concatMapStringsSep "\n" (rule: "-A INPUT ${rule}") ([] ++ [ "-m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT" @@ -150,6 +165,7 @@ with import ./lib; ++ map accept-tcp (unique (map toString cfg.input-internet-accept-tcp)) ++ map accept-udp (unique (map toString cfg.input-internet-accept-udp)) ++ ["-i retiolum -j Retiolum"] + ++ ["-i wiregrill -j Wiregrill"] )} ${formatTable cfg.extra.filter} ${formatTable cfg."extra${toString iptables-version}".filter} @@ -170,6 +186,23 @@ with import ./lib; ]; }."ip${toString iptables-version}tables" )} + ${concatMapStringsSep "\n" (rule: "-A Wiregrill ${rule}") ([] + ++ optional (cfg.accept-echo-request == "wiregrill") accept-echo-request + ++ map accept-tcp (unique (map toString cfg.input-wiregrill-accept-tcp)) + ++ map accept-udp (unique (map toString cfg.input-wiregrill-accept-udp)) + ++ { + ip4tables = [ + "-p tcp -j REJECT --reject-with tcp-reset" + "-p udp -j REJECT --reject-with icmp-port-unreachable" + "-j REJECT --reject-with icmp-proto-unreachable" + ]; + ip6tables = [ + "-p tcp -j REJECT --reject-with tcp-reset" + "-p udp -j REJECT --reject-with icmp6-port-unreachable" + "-j REJECT" + ]; + }."ip${toString iptables-version}tables" + )} COMMIT ''; } -- cgit v1.2.3 From 70303049c0d169e3aece41d31015bca15a869c73 Mon Sep 17 00:00:00 2001 From: tv Date: Wed, 11 Jan 2023 19:35:55 +0100 Subject: tv lidControl: init --- tv/3modules/default.nix | 1 + tv/3modules/lidControl.nix | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 tv/3modules/lidControl.nix (limited to 'tv/3modules') diff --git a/tv/3modules/default.nix b/tv/3modules/default.nix index b6b4faa5..ea3efbcc 100644 --- a/tv/3modules/default.nix +++ b/tv/3modules/default.nix @@ -8,6 +8,7 @@ ./hw.nix ./im.nix ./iptables.nix + ./lidControl.nix ./org.freedesktop.machine1.host-shell.nix ./slock.nix ./x0vncserver.nix diff --git a/tv/3modules/lidControl.nix b/tv/3modules/lidControl.nix new file mode 100644 index 00000000..6a48da18 --- /dev/null +++ b/tv/3modules/lidControl.nix @@ -0,0 +1,45 @@ +with import ./lib; +{ config, pkgs, ... }: { + options = { + tv.lidControl.enable = mkEnableOption "tv.lidControl"; + }; + config = let + cfg = config.tv.lidControl; + in mkIf cfg.enable { + services.acpid.enable = true; + services.acpid.lidEventCommands = /* sh */ '' + set -- $1 + + # usage: vt_is_xserver NUMBER + vt_is_xserver() { + ${pkgs.iproute}/bin/ss -lp src unix:/tmp/.X11-unix/X* | + ${pkgs.gnused}/bin/sed -n 's|.*/tmp/.X11-unix/X\([0-9]\+\)\>.*|\1|p' | + ${pkgs.gnugrep}/bin/grep -Fqx "$1" + } + + console=$(${pkgs.kbd}/bin/fgconsole) + + if vt_is_xserver "$console"; then + # usage: run_on_display COMMAND [ARG...] + run_on_display() { + owner=$(${pkgs.coreutils}/bin/stat -c %u /tmp/.X11-unix/X$console) + ${pkgs.systemd}/bin/systemd-run -GPq \ + -E DISPLAY=:$console \ + --uid=$owner \ + "$@" + } + case $3 in + open) + run_on_display ${pkgs.xorg.xset}/bin/xset dpms force on + ;; + close) + run_on_display ${pkgs.xorg.xset}/bin/xset dpms force off + ;; + esac + fi + ''; + services.logind.lidSwitch = "ignore"; + services.logind.lidSwitchDocked = "ignore"; + services.logind.lidSwitchExternalPower = "ignore"; + }; +} -- cgit v1.2.3 From 5eb821ab1bea5efd2f845115b3dbc31f4f475ca9 Mon Sep 17 00:00:00 2001 From: tv Date: Wed, 18 Jan 2023 17:13:30 +0100 Subject: tv.systemd.services.*.operators: init --- tv/3modules/default.nix | 1 + tv/3modules/systemd.nix | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 tv/3modules/systemd.nix (limited to 'tv/3modules') diff --git a/tv/3modules/default.nix b/tv/3modules/default.nix index ea3efbcc..c49f1582 100644 --- a/tv/3modules/default.nix +++ b/tv/3modules/default.nix @@ -10,6 +10,7 @@ ./iptables.nix ./lidControl.nix ./org.freedesktop.machine1.host-shell.nix + ./systemd.nix ./slock.nix ./x0vncserver.nix ./Xresources.nix diff --git a/tv/3modules/systemd.nix b/tv/3modules/systemd.nix new file mode 100644 index 00000000..bbbab063 --- /dev/null +++ b/tv/3modules/systemd.nix @@ -0,0 +1,46 @@ +with import ./lib; +{ config, ... }: let + normalUsers = filterAttrs (_: getAttr "isNormalUser") config.users.users; +in { + options = { + tv.systemd.services = mkOption { + type = types.attrsOf (types.submodule (self: { + options = { + operators = mkOption { + type = with types; listOf (enum (attrNames normalUsers)); + default = []; + }; + }; + })); + }; + }; + config = { + security.polkit.extraConfig = let + access = + mapAttrs' + (name: cfg: + nameValuePair "${name}.service" + (genAttrs cfg.operators (const true)) + ) + config.tv.systemd.services; + in optionalString (access != {}) /* js */ '' + polkit.addRule(function () { + const access = ${lib.toJSON access}; + return function (action, subject) { + if (action.id === "org.freedesktop.systemd1.manage-units") { + const unit = action.lookup("unit"); + if ( + (access[unit]||{})[subject.user] || + ( + unit.includes("@") && + (access[unit.replace(/@[^.]+/, "@")]||{})[subject.user] + ) + ) { + return polkit.Result.YES; + } + } + } + }()); + ''; + }; +} -- cgit v1.2.3 From 1da6186814c94512c1cbc41f2dfd3b4ac7b2e44f Mon Sep 17 00:00:00 2001 From: tv Date: Wed, 18 Jan 2023 17:14:27 +0100 Subject: tv.wwan: init --- tv/3modules/default.nix | 1 + tv/3modules/wwan.nix | 163 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 164 insertions(+) create mode 100644 tv/3modules/wwan.nix (limited to 'tv/3modules') diff --git a/tv/3modules/default.nix b/tv/3modules/default.nix index c49f1582..8c1066b7 100644 --- a/tv/3modules/default.nix +++ b/tv/3modules/default.nix @@ -14,5 +14,6 @@ ./slock.nix ./x0vncserver.nix ./Xresources.nix + ./wwan.nix ]; } diff --git a/tv/3modules/wwan.nix b/tv/3modules/wwan.nix new file mode 100644 index 00000000..703a903c --- /dev/null +++ b/tv/3modules/wwan.nix @@ -0,0 +1,163 @@ +with import ./lib; +{ config, pkgs, ... }: { + options = { + tv.wwan.enable = mkEnableOption "tv.wwan"; + tv.wwan.apn = mkOption { + type = with types; filename; + }; + tv.wwan.device = mkOption { + type = with types; pathname; + default = "/dev/cdc-wdm0"; + }; + tv.wwan.interface = mkOption { + type = with types; nullOr filename; + default = null; + }; + tv.wwan.operators = mkOption { + type = with types; listOf username; + default = []; + }; + tv.wwan.secrets = mkOption { + type = with types; pathname; + default = toString ; + # format: {"pin1":number} + }; + }; + config = let + cfg = config.tv.wwan; + in mkIf cfg.enable { + systemd.services.wwan = { + environment = { + DEVICE = cfg.device; + SECRETS = "%d/secrets"; + }; + path = [ + pkgs.busybox + pkgs.coreutils + pkgs.iproute2 + pkgs.jq + (pkgs.symlinkJoin { + name = "uqmi-wrapper"; + paths = [ + (pkgs.writeDashBin "uqmi" '' + set -efu + exec ${pkgs.uqmi}/bin/uqmi --device="$DEVICE" "$@" + '') + pkgs.uqmi + ]; + }) + (pkgs.writeDashBin "get-interface" ( + if cfg.interface != null then /* sh */ '' + echo ${cfg.interface} + '' else /* sh */ '' + exec ${pkgs.libqmi}/bin/qmicli -d "$DEVICE" -p --get-wwan-iface + '' + )) + ]; + serviceConfig = { + LoadCredential = [ + "secrets:${cfg.secrets}" + ]; + Type = "oneshot"; + RemainAfterExit = true; + SyslogIdentifier = "wwan"; + ExecStart = pkgs.writeDash "tv.wwan.start.sh" '' + set -efu + + interface=$(get-interface) + + pin1_status=$( + uqmi --uim-get-sim-state | + jq -r '"\(.pin1_status)/\(.pin1_verify_tries)"' + ) + case $pin1_status in + verified/*) + : + ;; + not_verified/3) + pin1=$(jq .pin1 "$SECRETS") + echo "verifying PIN1" >&2 + if ! uqmi --uim-verify-pin1 "$pin1"; then + echo "error: failed to verify PIN1" >&2 + exit 1 + fi + ;; + not_verified/*) + echo "error: not trying to verify PIN1: not enough tries left" >&2 + echo \ + "please check your configuration in ${cfg.secrets}" \ + " and verify if manually using:" \ + " ${pkgs.uqmi}/bin/uqmi -d $device --uim-veriy-pin1 XXXX" \ + >&2 + exit 1 + esac + + raw_ip_path=/sys/class/net/$interface/qmi/raw_ip + raw_ip=$(cat "$raw_ip_path") + if [ "$raw_ip" != Y ]; then + echo "enabling raw-ip" >&2 + if ! echo Y > "$raw_ip_path"; then + echo "error: failed to enable raw-ip" >&2 + exit 1 + fi + fi + + operating_mode=$(uqmi --get-device-operating-mode | tr -d \") + case $operating_mode in + online) + : + ;; + persistent_low_power|low_power) + echo "settings device operating mode to online" >&2 + uqmi --set-device-operating-mode online + operating_mode=$(uqmi --get-device-operating-mode | tr -d \") + if test "$operating_mode" != online; then + echo "error: failed to set device operating mode to online" >&2 + exit 1 + fi + ;; + *) + echo "error: don't know how to change device operating mode to online: $operating_mode" >&2 + exit 1 + esac + + ip link set dev "$interface" up + + data_status=$(uqmi --get-data-status | tr -d \") + case $data_status in + connected) + : + ;; + disconnected) + echo "starting network (APN=${cfg.apn})" >&2 + sleep 1 + uqmi \ + --start-network \ + --autoconnect \ + --apn ${cfg.apn} \ + --ip-family ipv4 + sleep 1 + ;; + *) + echo "error: unsupported data status: $data_status" >&2 + exit 1 + esac + + udhcpc -q -f -n -i "$interface" + ''; + Restart = "on-failure"; + ExecStop = pkgs.writeDash "tv.wwan.stop.sh" '' + set -efu + + interface=$(get-interface) + + ip link set dev "$interface" down + uqmi --stop-network 0xFFFFFFFF --autoconnect + uqmi --sync + uqmi --set-device-operating-mode persistent_low_power + ''; + }; + }; + tv.systemd.services.wwan.operators = cfg.operators; + }; +} -- cgit v1.2.3 From 9a7e3bf96250d9f9090d4eebac18240f54167a84 Mon Sep 17 00:00:00 2001 From: tv Date: Wed, 18 Jan 2023 20:23:18 +0100 Subject: tv.systemd.services: add default value --- tv/3modules/systemd.nix | 1 + 1 file changed, 1 insertion(+) (limited to 'tv/3modules') diff --git a/tv/3modules/systemd.nix b/tv/3modules/systemd.nix index bbbab063..db8a5199 100644 --- a/tv/3modules/systemd.nix +++ b/tv/3modules/systemd.nix @@ -12,6 +12,7 @@ in { }; }; })); + default = {}; }; }; config = { -- cgit v1.2.3 From 3e5c82d968b571fe3ebd03dcef5d7021c277c01e Mon Sep 17 00:00:00 2001 From: tv Date: Thu, 19 Jan 2023 14:07:23 +0100 Subject: tv wwan: make uqmi-wrapper available to root --- tv/3modules/wwan.nix | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'tv/3modules') diff --git a/tv/3modules/wwan.nix b/tv/3modules/wwan.nix index 703a903c..a60d314f 100644 --- a/tv/3modules/wwan.nix +++ b/tv/3modules/wwan.nix @@ -26,9 +26,19 @@ with import ./lib; config = let cfg = config.tv.wwan; in mkIf cfg.enable { + nixpkgs.overlays = singleton (self: super: { + uqmi-wrapper = pkgs.symlinkJoin { + name = "uqmi-wrapper"; + paths = [ + (pkgs.writeDashBin "uqmi" '' + exec ${pkgs.uqmi}/bin/uqmi --device=${cfg.device} "$@" + '') + pkgs.uqmi + ]; + }; + }); systemd.services.wwan = { environment = { - DEVICE = cfg.device; SECRETS = "%d/secrets"; }; path = [ @@ -36,21 +46,12 @@ with import ./lib; pkgs.coreutils pkgs.iproute2 pkgs.jq - (pkgs.symlinkJoin { - name = "uqmi-wrapper"; - paths = [ - (pkgs.writeDashBin "uqmi" '' - set -efu - exec ${pkgs.uqmi}/bin/uqmi --device="$DEVICE" "$@" - '') - pkgs.uqmi - ]; - }) + pkgs.uqmi-wrapper (pkgs.writeDashBin "get-interface" ( if cfg.interface != null then /* sh */ '' echo ${cfg.interface} '' else /* sh */ '' - exec ${pkgs.libqmi}/bin/qmicli -d "$DEVICE" -p --get-wwan-iface + exec ${pkgs.libqmi}/bin/qmicli -d ${cfg.device} -p --get-wwan-iface '' )) ]; @@ -158,6 +159,9 @@ with import ./lib; ''; }; }; + users.users.root.packages = [ + pkgs.uqmi-wrapper + ]; tv.systemd.services.wwan.operators = cfg.operators; }; } -- cgit v1.2.3 From 57abca263fe86259807e5597d1c8f11c3c3acd44 Mon Sep 17 00:00:00 2001 From: tv Date: Thu, 19 Jan 2023 14:08:01 +0100 Subject: tv wwan: add uqmi bash-completion --- tv/3modules/wwan.nix | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'tv/3modules') diff --git a/tv/3modules/wwan.nix b/tv/3modules/wwan.nix index a60d314f..03cd512e 100644 --- a/tv/3modules/wwan.nix +++ b/tv/3modules/wwan.nix @@ -33,6 +33,20 @@ with import ./lib; (pkgs.writeDashBin "uqmi" '' exec ${pkgs.uqmi}/bin/uqmi --device=${cfg.device} "$@" '') + (pkgs.writeTextDir "share/bash-completion/completions/uqmi" /* sh */'' + _uqmi_complete() { + case ''${#COMP_WORDS[@]} in + 2) + COMPREPLY=($(compgen -W "$( + ${pkgs.uqmi}/bin/uqmi --help 2>&1 | + ${pkgs.coreutils}/bin/tr , \\n | + ${pkgs.gnused}/bin/sed -nr 's/^ *(-[a-z-]+).*/\1/p' + )" -- "''${COMP_WORDS[1]}")) + ;; + esac + } + complete -F _uqmi_complete uqmi + '') pkgs.uqmi ]; }; -- cgit v1.2.3