1use std::net::IpAddr;
2use std::sync::Arc;
3
4use super::config::Ops;
5use super::validation::parse_limited_ipv4_subnet;
6use crate::error::Result;
7use crate::{
8 default_ipv4_subnet_string, default_ports, validate_ports, DiscoverEngine, Host, InspectEngine,
9 InspectResult, PortResult, PortScanner, SweepEngine, SweepEntry,
10};
11
12fn resolve_ports(ports: Option<Vec<u16>>) -> Result<Vec<u16>> {
22 match ports {
23 Some(ports) => {
24 validate_ports(&ports)?;
25 Ok(ports)
26 }
27 None => Ok(default_ports()),
28 }
29}
30
31impl Ops {
32 pub async fn discover_ipv4(
33 &self,
34 subnet: Option<String>,
35 resolve: bool,
36 ) -> Result<(String, Vec<Host>)> {
37 self.discover_ipv4_with_progress(subnet, resolve, None)
38 .await
39 }
40
41 pub async fn discover_ipv4_with_progress(
42 &self,
43 subnet: Option<String>,
44 resolve: bool,
45 progress: Option<Arc<dyn Fn(crate::discover::DiscoverProgress) + Send + Sync>>,
46 ) -> Result<(String, Vec<Host>)> {
47 let subnet_str = subnet.unwrap_or_else(default_ipv4_subnet_string);
48 let net = parse_limited_ipv4_subnet(&subnet_str)?;
49 let engine = DiscoverEngine::new_with_timeouts(
50 self.cfg.concurrency,
51 self.cfg.ping_timeout_ms,
52 self.cfg.dns_timeout_ms,
53 );
54 let hosts = engine
55 .scan_subnet_with_progress(net, resolve, progress)
56 .await?;
57 Ok((subnet_str, hosts))
58 }
59
60 pub async fn scan_ports(
61 &self,
62 host: &str,
63 ports: Option<Vec<u16>>,
64 ) -> Result<(IpAddr, Vec<PortResult>)> {
65 self.scan_ports_with_progress(host, ports, None).await
66 }
67
68 pub async fn scan_ports_with_progress(
69 &self,
70 host: &str,
71 ports: Option<Vec<u16>>,
72 progress: Option<Arc<dyn Fn(crate::scan::PortScanProgress) + Send + Sync>>,
73 ) -> Result<(IpAddr, Vec<PortResult>)> {
74 let ip = self.resolve_host_ip(host).await?;
75 let ports = resolve_ports(ports)?;
76 let scanner = PortScanner::new(self.cfg.concurrency);
77 let results = scanner
78 .scan_host_with_progress(ip, ports, self.cfg.scan_timeout_ms, progress)
79 .await?;
80 Ok((ip, results))
81 }
82
83 pub async fn scan_udp_ports_with_progress(
86 &self,
87 host: &str,
88 ports: Option<Vec<u16>>,
89 progress: Option<Arc<dyn Fn(crate::scan::PortScanProgress) + Send + Sync>>,
90 ) -> Result<(IpAddr, Vec<PortResult>)> {
91 let ip = self.resolve_host_ip(host).await?;
92 let ports = match ports {
93 Some(ports) => {
94 validate_ports(&ports)?;
95 ports
96 }
97 None => crate::DEFAULT_UDP_PORTS.to_vec(),
98 };
99 let scanner = crate::UdpScanner::new(self.cfg.concurrency);
100 let results = scanner
101 .scan_host_with_progress(ip, ports, self.cfg.scan_timeout_ms, progress)
102 .await?;
103 Ok((ip, results))
104 }
105
106 pub async fn scan_udp_ports(
107 &self,
108 host: &str,
109 ports: Option<Vec<u16>>,
110 ) -> Result<(IpAddr, Vec<PortResult>)> {
111 self.scan_udp_ports_with_progress(host, ports, None).await
112 }
113
114 pub async fn inspect_host(
115 &self,
116 host: String,
117 ports: Option<Vec<u16>>,
118 ) -> Result<InspectResult> {
119 let ports = resolve_ports(ports)?;
120 let engine = InspectEngine::new_with_timeouts(
121 self.cfg.concurrency,
122 self.cfg.ping_timeout_ms,
123 self.cfg.scan_timeout_ms,
124 self.cfg.dns_timeout_ms,
125 );
126 engine.inspect(host, ports).await
127 }
128
129 pub async fn sweep_ipv4(
130 &self,
131 subnet: Option<String>,
132 ports: Option<Vec<u16>>,
133 resolve_hostnames: bool,
134 ) -> Result<(String, Vec<SweepEntry>)> {
135 self.sweep_ipv4_with_progress(subnet, ports, resolve_hostnames, None)
136 .await
137 }
138
139 pub async fn sweep_ipv4_with_progress(
140 &self,
141 subnet: Option<String>,
142 ports: Option<Vec<u16>>,
143 resolve_hostnames: bool,
144 progress: Option<Arc<dyn Fn(crate::sweep::SweepProgress) + Send + Sync>>,
145 ) -> Result<(String, Vec<SweepEntry>)> {
146 let subnet_str = subnet.unwrap_or_else(default_ipv4_subnet_string);
147 let net = parse_limited_ipv4_subnet(&subnet_str)?;
148 let ports = resolve_ports(ports)?;
149 let engine = SweepEngine::new_with_timeouts(
150 self.cfg.concurrency,
151 self.cfg.ping_timeout_ms,
152 self.cfg.scan_timeout_ms,
153 self.cfg.dns_timeout_ms,
154 );
155 let results = engine
156 .sweep_with_progress(net, ports, resolve_hostnames, progress)
157 .await?;
158 Ok((subnet_str, results))
159 }
160}