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    oui::traits::Oui,
14    targets::{ips::IPTargets, ports::PortTargets},
15    wire::{DEFAULT_PACKET_SEND_TIMING, Wire},
16};
17
18use super::{
19    Device, ScanMessage, Scanner, arp_scanner::ARPScanner,
20    syn_scanner::SYNScanner,
21};
22
23/// Data structure representing a Full scanner (ARP + SYN)
24#[derive(Builder)]
25#[builder(setter(into))]
26pub struct FullScanner {
27    /// Network interface to use for scanning
28    interface: Arc<NetworkInterface>,
29    /// Wire for reading and sending packets on the wire
30    wire: Wire,
31    /// IP targets to scan for device discovery
32    targets: Arc<IPTargets>,
33    /// Port targets to scan on discovered devices
34    ports: Arc<PortTargets>,
35    /// Whether to include vendor lookups for discovered devices
36    vendor: bool,
37    /// Whether to include hostname lookups for discovered devices
38    host: bool,
39    /// Duration to wait for responses after scanning completes
40    idle_timeout: Duration,
41    /// Throttles speed at which packets are sent. Higher throttles result
42    /// in more accurate scans
43    #[builder(default = DEFAULT_PACKET_SEND_TIMING)]
44    throttle: Duration,
45    /// Channel for sending scan results and status messages
46    notifier: mpsc::Sender<ScanMessage>,
47    /// Source port for packet listener and incoming packet identification
48    source_port: u16,
49    /// Used to lookup vendor info for mac addresses
50    #[builder(default)]
51    oui: Option<Arc<dyn Oui>>,
52}
53
54impl FullScanner {
55    /// Returns a builder for FullScanner
56    pub fn builder() -> FullScannerBuilder {
57        FullScannerBuilder::default()
58    }
59
60    fn get_syn_targets_from_arp_scan(&self) -> Result<Vec<Device>> {
61        let (tx, rx) = mpsc::channel::<ScanMessage>();
62
63        let mut syn_targets: Vec<Device> = Vec::new();
64
65        let mut arp_builder = ARPScanner::builder()
66            .interface(Arc::clone(&self.interface))
67            .wire(self.wire.clone())
68            .targets(Arc::clone(&self.targets))
69            .source_port(self.source_port)
70            .include_vendor(self.vendor)
71            .include_host_names(self.host)
72            .idle_timeout(self.idle_timeout)
73            .throttle(self.throttle)
74            .notifier(tx.clone());
75
76        if let Some(oui) = self.oui.as_ref() {
77            arp_builder = arp_builder.oui(Arc::clone(oui));
78        }
79
80        let arp = arp_builder.build()?;
81
82        arp.scan()?;
83
84        loop {
85            if let Ok(msg) = rx.recv() {
86                match msg {
87                    ScanMessage::Done => {
88                        log::debug!("arp sending complete");
89                        break;
90                    }
91                    ScanMessage::ARPScanDevice(device) => {
92                        syn_targets.push(device.to_owned());
93                    }
94                    _ => {}
95                }
96            }
97        }
98
99        Ok(syn_targets)
100    }
101}
102
103// Implements the Scanner trait for FullScanner
104impl Scanner for FullScanner {
105    fn scan(&self) -> Result<JoinHandle<Result<()>>> {
106        let syn_targets = self.get_syn_targets_from_arp_scan()?;
107
108        let syn = SYNScanner::builder()
109            .interface(Arc::clone(&self.interface))
110            .wire(self.wire.clone())
111            .targets(syn_targets)
112            .ports(Arc::clone(&self.ports))
113            .source_port(self.source_port)
114            .idle_timeout(self.idle_timeout)
115            .throttle(self.throttle)
116            .notifier(self.notifier.clone())
117            .build()?;
118
119        syn.scan()
120    }
121}
122
123#[cfg(test)]
124#[path = "./full_scanner_tests.rs"]
125mod tests;