# Get a Mullvad api access token from an account number def "m token" [ account: string # Mullvad account number ] { (http post https://api.mullvad.net/auth/v1/token -t application/json {account_number: $account} ).access_token } # Add a device to a mullvad account def "m add device" [ account: string # Mullvad account number ] { let token = (m-token $account) let bearer = ("Bearer " + $token) (http post https://api.mullvad.net/accounts/v1/devices -t application/json -H [Authorization $bearer] { pubkey: (wg genkey | wg pubkey), hijack_dns: false, kind: "App", }) } # Get mullvad-daemon system path def "m daemon path" []: nothing -> string { match (uname).kernel-name { Linux => "/usr/bin/mullvad-daemon", Darwin => "/Applications/Mullvad VPN.app/Contents/Resources/mullvad-daemon", _ => (panic "Unknown Kernel"), } } # Return true if mullvad-daemon is running def "m daemon is-running" [ # Only return true if mullvad-daemon is running as a launch daemon --system (-s), ] { let procs = (^ps aux | lines) if $system { $procs | any { |line| $line =~ (m daemon path) } } else { $procs | any { |line| $line =~ "mullvad-daemon" } } } def dns [ --server (-s): string, name: string, ] { # HACK: turn the optional argument into a list. not sure how to pass it to nslookup otherwise. let server = ([$server] | compact) let ipv4 = (dig $name A | lines | skip until {|l| $l =~ "ANSWER SECTION" } | skip 1 | take until { |l| $l == "" } | split column "\t" -c | rename host ttl _ type addr) | reject _ let ipv6 = (dig $name AAAA | lines | skip until {|l| $l =~ "ANSWER SECTION" } | skip 1 | take until { |l| $l == "" } | split column "\t" -c | rename host ttl _ type addr) | reject _ $ipv4 | append $ipv6 } # Build and run mullvad-daemon def "m daemon" [ --release (-r) # Force userspace wireguard --userwg # Use wireguard-go over GotaTun --wggo # Use stagemole --stagemole # Attach GDB --gdb # Add counters and such to nft rules --debug-fw ] { mut daemon_args = [] mut cargo_flags = [] mut envs = [ MULLVAD_RESOURCE_DIR=./dist-assets/ ] if $release { $cargo_flags ++= [--release] } if $stagemole { $cargo_flags ++= [--features api-override] $envs ++= [ MULLVAD_API_HOST=api.stagemole.eu MULLVAD_API_ADDR=(dns api.stagemole.eu | where type == A | get 0.addr):443 ] } if $debug_fw { $envs ++= [TALPID_FIREWALL_DEBUG=1] } if $userwg { $envs ++= [TALPID_FORCE_USERSPACE_WIREGUARD=1] } if $wggo { $cargo_flags ++= [--features wireguard-go] } if (m daemon is-running --system) { print "daemon is loaded, stopping..." match (uname).kernel-name { Linux => { sudo systemctl stop mullvad-daemon }, Darwin => { sudo launchctl unload -w /Library/LaunchDaemons/net.mullvad.daemon.plist }, _ => (panic "Unknown Kernel"), } } else if (m daemon is-running) { print "mulvad-daemon is running in another terminal" return } if $gdb { $daemon_args ++= [gdb --args] } let daemon_path = if $release { $daemon_args ++= [$"($env.CARGO_TARGET_DIR)/release/mullvad-daemon"] } else { $daemon_args ++= [$"($env.CARGO_TARGET_DIR)/debug/mullvad-daemon"] } # increase verbosity $daemon_args ++= ["-vv"] cargo b ...$cargo_flags sudo ...$envs ...$daemon_args } def "m android cli" [ ...args ] { let socket_filename = "rpc-socket" sudo MULLVAD_RPC_SOCKET_PATH=(sudo fd $socket_filename ~/.local/share/waydroid) mullvad ...$args } def "m android start" [ ] { print "starting net.mullvad.mullvadvpn" adb shell am start -n net.mullvad.mullvadvpn/.ui.MainActivity; # TODO: the waydroid cli is bork in the nix flake # waydroid app launch net.mullvad.mullvadvpn } def "m android stop" [ ] { let app_pid = (ps | where name =~ mullvadvpn | get -o pid.0) if $app_pid != null { print $"kill net.mullvad.mullvadvpn [($app_pid)]" sudo kill $app_pid } else { print "net.mullvad.mullvadvpn is not running" } } def "m android run" [ ] { print "hack: making sure we're disconnected" do --ignore-errors { m android cli disconnect } print "compiling apk" ./gradlew installOssProdDebug m android start } def "m android reload-daemon" [ ] { let daemon_path = (fd libmullvad_jni.so ~/.local/share/waydroid/ | lines | get -o 0) if $daemon_path == null { print "Can't find libmullvad_jni.so, hot-reload not available. Is the app installed?" exit } m android stop print "re-compiling libmullvad_jni.so" ./gradlew app:cargoBuildX86_64; print "Executing hot-swap!" sudo cp ~/.cargo/target/x86_64-linux-android/debug/libmullvad_jni.so $daemon_path; m android start } def "m e2e list" [ ...args ] { print "Building test utils" cargo b --target aarch64-apple-darwin let test_manager = $"($env.CARGO_TARGET_DIR)/aarch64-apple-darwin/debug/test-manager" print "Listing tests" ^$test_manager list-tests ...$args | from tsv | into int priority | sort-by priority name } def "m e2e run" [ account: string vm: string --skip: list --display (-d) ...tests ] { let commit = (git rev-parse HEAD | take 6 | decode) print $"Current commit: ($commit)" let dist = "../dist" print $"Looking in ($dist)" let pkg_ext = match (uname).kernel-name { "Linux" => "rpm", # TODO: rpm "Darwin" => "pkg", _ => (panic "Unknown kernel"), } let target = match (uname).kernel-name { "Linux" => "x86_64-unknown-linux-musl", "Darwin" => "aarch64-apple-darwin", _ => (panic "Unknown kernel"), } let pkgs = (ls $dist | where name =~ $".*\\.($pkg_ext)") let pkgs = ($pkgs | where name =~ $commit) if ($pkgs | is-empty) { print $"No .($pkg_ext) for current commit found." print "Run ./build.sh" return } if ($pkgs | length) > 1 { print $"Multiple .($pkg_ext):s for current commit found." print "Make sure there's only one" print ...$pkgs return } let pkg = ($pkgs | get 0.name) print $"Using ($pkg)" print "Building test utils" cargo b --release --target $target -p test-runner -p connection-checker cargo b -p test-manager let test_manager = $"($env.CARGO_TARGET_DIR)/debug/test-manager" let bin_dir = $"($env.CARGO_TARGET_DIR)/($target)/release/" mut args = [ --vm $vm --account $account --app-package $pkg --runner-dir $bin_dir ] if $display { $args ++= [--display] } for s in $skip { $args ++= ["--skip" $s] } let args = $args print "Running tests" RUST_LOG=debug ^$test_manager run-tests -v ...$args ...$tests }