use crate::async_io::{scan_hosts, scan_ports};
use crate::host::HostInfo;
use crate::result::{HostScanResult, PortScanResult, ScanStatus};
use crate::setting::{
ScanSetting, ScanType, DEFAULT_HOSTS_CONCURRENCY, DEFAULT_PORTS_CONCURRENCY, DEFAULT_SRC_PORT,
};
use std::collections::HashMap;
use std::net::{IpAddr, SocketAddr};
use std::sync::mpsc::{channel, Receiver, Sender};
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};
#[derive(Clone, Debug)]
pub struct HostScanner {
pub if_index: u32,
pub if_name: String,
pub src_mac: [u8; 6],
pub dst_mac: [u8; 6],
pub src_ip: IpAddr,
pub src_port: u16,
pub targets: Vec<HostInfo>,
pub scan_type: ScanType,
pub hosts_concurrency: usize,
pub timeout: Duration,
pub wait_time: Duration,
pub send_rate: Duration,
pub scan_result: HostScanResult,
pub tx: Arc<Mutex<Sender<SocketAddr>>>,
pub rx: Arc<Mutex<Receiver<SocketAddr>>>,
}
impl HostScanner {
pub fn new(src_ip: IpAddr) -> Result<HostScanner, String> {
let mut if_index: u32 = 0;
let mut if_name: String = String::new();
let mut src_mac: pnet_datalink::MacAddr = pnet_datalink::MacAddr::zero();
for iface in pnet_datalink::interfaces() {
for ip in iface.ips {
if ip.ip() == src_ip {
if_index = iface.index;
if_name = iface.name;
src_mac = iface.mac.unwrap_or(pnet_datalink::MacAddr::zero());
break;
}
}
}
if if_index == 0 || if_name.is_empty() || src_mac == pnet_datalink::MacAddr::zero() {
return Err(String::from(
"Failed to create Scanner. Network Interface not found.",
));
}
let (tx, rx) = channel();
let host_scanner = HostScanner {
if_index: if_index,
if_name: if_name,
src_mac: src_mac.octets(),
dst_mac: pnet_datalink::MacAddr::zero().octets(),
src_ip: src_ip,
src_port: DEFAULT_SRC_PORT,
targets: vec![],
scan_type: ScanType::IcmpPingScan,
hosts_concurrency: DEFAULT_HOSTS_CONCURRENCY,
timeout: Duration::from_millis(30000),
wait_time: Duration::from_millis(200),
send_rate: Duration::from_millis(1),
scan_result: HostScanResult::new(),
tx: Arc::new(Mutex::new(tx)),
rx: Arc::new(Mutex::new(rx)),
};
Ok(host_scanner)
}
pub fn set_src_ip(&mut self, src_ip: IpAddr) {
self.src_ip = src_ip;
}
pub fn get_src_ip(&self) -> IpAddr {
self.src_ip.clone()
}
pub fn add_target(&mut self, dst: HostInfo) {
self.targets.push(dst);
}
pub fn set_targets(&mut self, dst: Vec<HostInfo>) {
self.targets = dst;
}
pub fn get_targets(&self) -> Vec<HostInfo> {
self.targets.clone()
}
pub fn set_scan_type(&mut self, scan_type: ScanType) {
self.scan_type = scan_type;
}
pub fn get_scan_type(&self) -> ScanType {
self.scan_type.clone()
}
pub fn set_timeout(&mut self, timeout: Duration) {
self.timeout = timeout;
}
pub fn get_timeout(&self) -> Duration {
self.timeout.clone()
}
pub fn set_wait_time(&mut self, wait_time: Duration) {
self.wait_time = wait_time;
}
pub fn get_wait_time(&self) -> Duration {
self.wait_time.clone()
}
pub fn set_send_rate(&mut self, send_rate: Duration) {
self.send_rate = send_rate;
}
pub fn get_send_rate(&self) -> Duration {
self.send_rate.clone()
}
pub fn set_hosts_concurrency(&mut self, concurrency: usize) {
self.hosts_concurrency = concurrency;
}
pub fn get_scan_result(&self) -> HostScanResult {
self.scan_result.clone()
}
pub fn get_progress_receiver(&self) -> Arc<Mutex<Receiver<SocketAddr>>> {
self.rx.clone()
}
pub async fn run_scan(&mut self) {
let mut ip_map: HashMap<IpAddr, String> = HashMap::new();
for dst in self.targets.clone() {
ip_map.insert(dst.ip_addr, dst.host_name);
}
let scan_setting: ScanSetting = ScanSetting {
if_index: self.if_index.clone(),
src_mac: pnet_datalink::MacAddr::from(self.src_mac),
dst_mac: pnet_datalink::MacAddr::from(self.dst_mac),
src_ip: self.src_ip.clone(),
src_port: self.src_port.clone(),
targets: self.targets.clone(),
ip_map: ip_map,
timeout: self.timeout.clone(),
wait_time: self.wait_time.clone(),
send_rate: self.timeout.clone(),
scan_type: self.scan_type.clone(),
hosts_concurrency: self.hosts_concurrency,
ports_concurrency: DEFAULT_PORTS_CONCURRENCY,
};
let start_time = Instant::now();
let mut result: HostScanResult = scan_hosts(scan_setting, &self.tx).await;
result.scan_time = Instant::now().duration_since(start_time);
if result.scan_time > self.timeout {
result.scan_status = ScanStatus::Timeout;
} else {
result.scan_status = ScanStatus::Done;
}
self.scan_result = result;
}
pub async fn scan(&mut self) -> HostScanResult {
self.run_scan().await;
self.scan_result.clone()
}
}
#[derive(Clone, Debug)]
pub struct PortScanner {
pub if_index: u32,
pub if_name: String,
pub src_mac: [u8; 6],
pub dst_mac: [u8; 6],
pub src_ip: IpAddr,
pub src_port: u16,
pub targets: Vec<HostInfo>,
pub scan_type: ScanType,
pub hosts_concurrency: usize,
pub ports_concurrency: usize,
pub timeout: Duration,
pub wait_time: Duration,
pub send_rate: Duration,
pub scan_result: PortScanResult,
pub tx: Arc<Mutex<Sender<SocketAddr>>>,
pub rx: Arc<Mutex<Receiver<SocketAddr>>>,
}
impl PortScanner {
pub fn new(src_ip: IpAddr) -> Result<PortScanner, String> {
let mut if_index: u32 = 0;
let mut if_name: String = String::new();
let mut src_mac: pnet_datalink::MacAddr = pnet_datalink::MacAddr::zero();
for iface in pnet_datalink::interfaces() {
for ip in iface.ips {
if ip.ip() == src_ip {
if_index = iface.index;
if_name = iface.name;
src_mac = iface.mac.unwrap_or(pnet_datalink::MacAddr::zero());
break;
}
}
}
if if_index == 0 || if_name.is_empty() || src_mac == pnet_datalink::MacAddr::zero() {
return Err(String::from(
"Failed to create Scanner. Network Interface not found.",
));
}
let (tx, rx) = channel();
let port_scanner = PortScanner {
if_index: if_index,
if_name: if_name,
src_mac: src_mac.octets(),
dst_mac: pnet_datalink::MacAddr::zero().octets(),
src_ip: src_ip,
src_port: DEFAULT_SRC_PORT,
targets: vec![],
scan_type: ScanType::TcpSynScan,
hosts_concurrency: DEFAULT_HOSTS_CONCURRENCY,
ports_concurrency: DEFAULT_PORTS_CONCURRENCY,
timeout: Duration::from_millis(30000),
wait_time: Duration::from_millis(200),
send_rate: Duration::from_millis(1),
scan_result: PortScanResult::new(),
tx: Arc::new(Mutex::new(tx)),
rx: Arc::new(Mutex::new(rx)),
};
Ok(port_scanner)
}
pub fn set_src_ip(&mut self, src_ip: IpAddr) {
self.src_ip = src_ip;
}
pub fn get_src_ip(&self) -> IpAddr {
self.src_ip.clone()
}
pub fn add_target(&mut self, dst: HostInfo) {
self.targets.push(dst);
}
pub fn set_targets(&mut self, dst: Vec<HostInfo>) {
self.targets = dst;
}
pub fn get_targets(&self) -> Vec<HostInfo> {
self.targets.clone()
}
pub fn set_scan_type(&mut self, scan_type: ScanType) {
self.scan_type = scan_type;
}
pub fn get_scan_type(&self) -> ScanType {
self.scan_type.clone()
}
pub fn set_timeout(&mut self, timeout: Duration) {
self.timeout = timeout;
}
pub fn get_timeout(&self) -> Duration {
self.timeout.clone()
}
pub fn set_wait_time(&mut self, wait_time: Duration) {
self.wait_time = wait_time;
}
pub fn get_wait_time(&self) -> Duration {
self.wait_time.clone()
}
pub fn set_send_rate(&mut self, send_rate: Duration) {
self.send_rate = send_rate;
}
pub fn get_send_rate(&self) -> Duration {
self.send_rate.clone()
}
pub fn set_hosts_concurrency(&mut self, concurrency: usize) {
self.hosts_concurrency = concurrency;
}
pub fn set_ports_concurrency(&mut self, concurrency: usize) {
self.ports_concurrency = concurrency;
}
pub fn get_scan_result(&self) -> PortScanResult {
self.scan_result.clone()
}
pub fn get_progress_receiver(&self) -> Arc<Mutex<Receiver<SocketAddr>>> {
self.rx.clone()
}
pub async fn run_scan(&mut self) {
let mut ip_map: HashMap<IpAddr, String> = HashMap::new();
for dst in self.targets.clone() {
ip_map.insert(dst.ip_addr, dst.host_name);
}
let scan_setting: ScanSetting = ScanSetting {
if_index: self.if_index.clone(),
src_mac: pnet_datalink::MacAddr::from(self.src_mac),
dst_mac: pnet_datalink::MacAddr::from(self.dst_mac),
src_ip: self.src_ip.clone(),
src_port: self.src_port.clone(),
targets: self.targets.clone(),
ip_map: ip_map,
timeout: self.timeout.clone(),
wait_time: self.wait_time.clone(),
send_rate: self.timeout.clone(),
scan_type: self.scan_type.clone(),
hosts_concurrency: self.hosts_concurrency,
ports_concurrency: self.ports_concurrency,
};
let start_time = Instant::now();
let mut result: PortScanResult = scan_ports(scan_setting, &self.tx).await;
result.scan_time = Instant::now().duration_since(start_time);
if result.scan_status != ScanStatus::Error {
if result.scan_time > self.timeout {
result.scan_status = ScanStatus::Timeout;
} else {
result.scan_status = ScanStatus::Done;
}
}
self.scan_result = result;
}
pub async fn scan(&mut self) -> PortScanResult {
self.run_scan().await;
self.scan_result.clone()
}
}