Skip to main content

r_lanlib/scanners/
full_scanner.rs

1//! Provides Scanner implementation for Full scanning (ARP + SYN)
2
3use derive_builder::Builder;
4use std::{
5    sync::{Arc, mpsc},
6    thread::JoinHandle,
7    time::Duration,
8};
9
10use crate::{
11    error::Result,
12    network::NetworkInterface,
13    packet::wire::Wire,
14    targets::{ips::IPTargets, ports::PortTargets},
15};
16
17use super::{
18    Device, ScanMessage, Scanner, arp_scanner::ARPScanner,
19    syn_scanner::SYNScanner,
20};
21
22/// Data structure representing a Full scanner (ARP + SYN)
23#[derive(Builder)]
24#[builder(setter(into))]
25pub struct FullScanner {
26    /// Network interface to use for scanning
27    interface: Arc<NetworkInterface>,
28    /// Wire for reading and sending packets on the wire
29    wire: Wire,
30    /// IP targets to scan for device discovery
31    targets: Arc<IPTargets>,
32    /// Port targets to scan on discovered devices
33    ports: Arc<PortTargets>,
34    /// Whether to include vendor lookups for discovered devices
35    vendor: bool,
36    /// Whether to include hostname lookups for discovered devices
37    host: bool,
38    /// Duration to wait for responses after scanning completes
39    idle_timeout: Duration,
40    /// Channel for sending scan results and status messages
41    notifier: mpsc::Sender<ScanMessage>,
42    /// Source port for packet listener and incoming packet identification
43    source_port: u16,
44}
45
46impl FullScanner {
47    /// Returns a builder for FullScanner
48    pub fn builder() -> FullScannerBuilder {
49        FullScannerBuilder::default()
50    }
51
52    fn get_syn_targets_from_arp_scan(&self) -> Result<Vec<Device>> {
53        let (tx, rx) = mpsc::channel::<ScanMessage>();
54
55        let mut syn_targets: Vec<Device> = Vec::new();
56
57        let arp = ARPScanner::builder()
58            .interface(Arc::clone(&self.interface))
59            .wire(self.wire.clone())
60            .targets(Arc::clone(&self.targets))
61            .source_port(self.source_port)
62            .include_vendor(self.vendor)
63            .include_host_names(self.host)
64            .idle_timeout(self.idle_timeout)
65            .notifier(tx.clone())
66            .build()?;
67
68        arp.scan()?;
69
70        loop {
71            if let Ok(msg) = rx.recv() {
72                match msg {
73                    ScanMessage::Done => {
74                        log::debug!("arp sending complete");
75                        break;
76                    }
77                    ScanMessage::ARPScanDevice(device) => {
78                        syn_targets.push(device.to_owned());
79                    }
80                    _ => {}
81                }
82            }
83        }
84
85        Ok(syn_targets)
86    }
87}
88
89// Implements the Scanner trait for FullScanner
90impl Scanner for FullScanner {
91    fn scan(&self) -> Result<JoinHandle<Result<()>>> {
92        let syn_targets = self.get_syn_targets_from_arp_scan()?;
93
94        let syn = SYNScanner::builder()
95            .interface(Arc::clone(&self.interface))
96            .wire(self.wire.clone())
97            .targets(syn_targets)
98            .ports(Arc::clone(&self.ports))
99            .source_port(self.source_port)
100            .idle_timeout(self.idle_timeout)
101            .notifier(self.notifier.clone())
102            .build()?;
103
104        syn.scan()
105    }
106}
107
108#[cfg(test)]
109#[path = "./full_scanner_tests.rs"]
110mod tests;