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