mod detectors;
mod install;
mod output;
mod types;
#[derive(clap::Parser, Debug)]
#[command(
name = "snortal",
about = "Detect captive portal URLs on the current Linux network",
after_help = "\
Examples:
snortal Run all detectors with defaults
snortal --verbose Include SSID and empty detectors
snortal --json Machine-readable output
snortal --timeout 10 Raise HTTP/subprocess timeout
snortal -e http://captive.apple.com/ Use a custom probe endpoint
snortal --gateway-ip 192.168.0.1 Skip route auto-detection
snortal install-deps Install nmcli and wpa_cli",
version
)]
struct Cli {
#[arg(short, long, default_value = "5")]
timeout: u64,
#[arg(short, long)]
verbose: bool,
#[arg(long)]
json: bool,
#[arg(short = 'e', long = "probe-endpoint", value_name = "URL")]
probe_endpoints: Vec<String>,
#[arg(short = 'd', long = "dhcp-file", value_name = "PATH")]
dhcp_files: Vec<String>,
#[arg(short = 'g', long = "gateway-ip", value_name = "IP")]
gateway_ip: Option<String>,
#[command(subcommand)]
command: Option<Subcommand>,
}
#[derive(clap::Subcommand, Debug)]
enum Subcommand {
InstallDeps,
}
#[tokio::main]
async fn main() {
let cli = <Cli as clap::Parser>::parse();
if let Some(Subcommand::InstallDeps) = cli.command {
install::run();
return;
}
let results = detectors::run_all(&detectors::DetectorConfig {
timeout_secs: cli.timeout,
verbose: cli.verbose,
probe_endpoints: cli.probe_endpoints,
dhcp_files: cli.dhcp_files,
gateway_ip: cli.gateway_ip,
})
.await;
output::print_results(results.urls, results.notes, cli.json, cli.verbose);
}