r_lanlib/scanners/
full_scanner.rs

1//! Provides Scanner implementation for Full scanning (ARP + SYN)
2
3use log::*;
4use std::{
5    sync::{Arc, Mutex, mpsc},
6    thread::JoinHandle,
7    time::Duration,
8};
9
10use crate::{
11    error::Result,
12    network::NetworkInterface,
13    packet::{Reader, Sender},
14    targets::{ips::IPTargets, ports::PortTargets},
15};
16
17use super::{
18    Device, ScanMessage, Scanner,
19    arp_scanner::{ARPScanner, ARPScannerArgs},
20    syn_scanner::{SYNScanner, SYNScannerArgs},
21};
22
23/// Data structure representing a Full scanner (ARP + SYN)
24pub struct FullScanner<'net> {
25    interface: &'net NetworkInterface,
26    packet_reader: Arc<Mutex<dyn Reader>>,
27    packet_sender: Arc<Mutex<dyn Sender>>,
28    targets: Arc<IPTargets>,
29    ports: Arc<PortTargets>,
30    vendor: bool,
31    host: bool,
32    idle_timeout: Duration,
33    notifier: mpsc::Sender<ScanMessage>,
34    source_port: u16,
35}
36
37/// Data structure holding parameters needed to create instance of FullScanner
38pub struct FullScannerArgs<'net> {
39    /// The network interface to use when scanning
40    pub interface: &'net NetworkInterface,
41    /// A packet Reader implementation (can use default provided in packet
42    /// crate)
43    pub packet_reader: Arc<Mutex<dyn Reader>>,
44    /// A packet Sender implementation (can use default provided in packet
45    /// crate)
46    pub packet_sender: Arc<Mutex<dyn Sender>>,
47    /// [`IPTargets`] to scan
48    pub targets: Arc<IPTargets>,
49    /// [`PortTargets`] to scan for each detected device
50    pub ports: Arc<PortTargets>,
51    /// An open source port to listen for incoming packets (can use network
52    /// packet to find open port)
53    pub source_port: u16,
54    /// Whether or not to include vendor look-ups for detected devices
55    pub include_vendor: bool,
56    /// Whether or not to include hostname look-ups for detected devices
57    pub include_host_names: bool,
58    /// The amount of time to wait for incoming packets after scanning all
59    /// targets
60    pub idle_timeout: Duration,
61    /// Channel to send messages regarding devices being scanned, and detected
62    /// devices
63    pub notifier: mpsc::Sender<ScanMessage>,
64}
65
66impl<'net> FullScanner<'net> {
67    /// Returns a new instance of FullScanner using provided info
68    pub fn new(args: FullScannerArgs<'net>) -> Self {
69        Self {
70            interface: args.interface,
71            packet_reader: args.packet_reader,
72            packet_sender: args.packet_sender,
73            targets: args.targets,
74            ports: args.ports,
75            vendor: args.include_vendor,
76            host: args.include_host_names,
77            idle_timeout: args.idle_timeout,
78            notifier: args.notifier,
79            source_port: args.source_port,
80        }
81    }
82}
83
84impl FullScanner<'_> {
85    fn get_syn_targets_from_arp_scan(&self) -> Vec<Device> {
86        let (tx, rx) = mpsc::channel::<ScanMessage>();
87
88        let mut syn_targets: Vec<Device> = Vec::new();
89
90        let arp = ARPScanner::new(ARPScannerArgs {
91            interface: self.interface,
92            packet_reader: Arc::clone(&self.packet_reader),
93            packet_sender: Arc::clone(&self.packet_sender),
94            targets: Arc::clone(&self.targets),
95            source_port: self.source_port,
96            include_vendor: self.vendor,
97            include_host_names: self.host,
98            idle_timeout: self.idle_timeout,
99            notifier: tx.clone(),
100        });
101
102        arp.scan();
103
104        loop {
105            if let Ok(msg) = rx.recv() {
106                match msg {
107                    ScanMessage::Done => {
108                        debug!("arp sending complete");
109                        break;
110                    }
111                    ScanMessage::ARPScanDevice(device) => {
112                        syn_targets.push(device.to_owned());
113                    }
114                    _ => {}
115                }
116            }
117        }
118
119        syn_targets
120    }
121}
122
123// Implements the Scanner trait for FullScanner
124impl Scanner for FullScanner<'_> {
125    fn scan(&self) -> JoinHandle<Result<()>> {
126        let syn_targets = self.get_syn_targets_from_arp_scan();
127        let syn = SYNScanner::new(SYNScannerArgs {
128            interface: self.interface,
129            packet_reader: Arc::clone(&self.packet_reader),
130            packet_sender: Arc::clone(&self.packet_sender),
131            targets: syn_targets,
132            ports: Arc::clone(&self.ports),
133            source_port: self.source_port,
134            idle_timeout: self.idle_timeout,
135            notifier: self.notifier.clone(),
136        });
137
138        syn.scan()
139    }
140}
141
142#[cfg(test)]
143#[path = "./full_scanner_tests.rs"]
144mod tests;