use std::net::Ipv4Addr;
use std::sync::Arc;
use clap::{Parser, ValueEnum};
use crate::setting::sockets_iter::SocketIterator;
use super::parse::{parse_hosts, parse_ports};
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Debug, Default)]
pub enum ScanType {
#[default]
Icmp,
Tcp,
Udp,
Arp,
Show,
}
#[derive(Parser, Debug, Default, Clone)]
#[command(author, version, about, long_about = None)]
pub struct ScanOpts {
#[arg(value_enum)]
pub execute: ScanType,
#[arg(value_parser = parse_hosts)]
pub hosts: Arc<Vec<Ipv4Addr>>,
#[arg(short, long, value_parser = parse_ports, default_value = "")]
pub ports: Arc<Vec<u16>>,
#[arg(long, default_value_t = 1024)]
pub batch_size: usize,
#[arg(long, default_value_t = 10)]
pub timeout: u64,
#[arg(long, default_value_t = 3)]
pub retry: u64,
#[arg(long, default_value_t = 3)]
pub retry_interval: u64,
#[arg(long)]
pub filepath: Option<String>,
}
impl ScanOpts {
pub fn iter_sockets(&self) -> anyhow::Result<SocketIterator> {
Ok(SocketIterator::new(&self.hosts, &self.ports))
}
}
#[cfg(test)]
mod tests {
use std::net::{IpAddr, SocketAddr};
use std::str::FromStr;
use super::*;
#[test]
fn iter_sockets() {
let ports = vec![1, 2, 3, 4];
let hosts = ["127.0.0.1", "192.168.0.1"]
.into_iter()
.map(|x| Ipv4Addr::from_str(x).unwrap())
.collect::<Vec<Ipv4Addr>>();
let scan_opts = ScanOpts {
execute: ScanType::Tcp,
hosts: Arc::new(hosts.clone()),
ports: Arc::new(ports.clone()),
..Default::default()
};
let mut iter = scan_opts.iter_sockets().unwrap();
for port in &ports {
for host in &hosts {
assert_eq!(iter.next(), Some(SocketAddr::new(IpAddr::V4(*host), *port)));
}
}
}
}