From ca1674243eeb51c38d3b6c4a86016fdc838b0dc8 Mon Sep 17 00:00:00 2001 From: rzuasti Date: Fri, 23 Jan 2026 14:35:28 -0500 Subject: [PATCH] Using duration-string for configuration of timings. Much nicer. --- Cargo.lock | 10 ++++++ Cargo.toml | 1 + oott.toml | 6 ++-- sample_oott.toml | 6 ++-- src/device_finders/arp.rs | 34 +++++++++++++------ src/device_finders/arp/packet_send_receive.rs | 16 ++++++--- src/main.rs | 2 +- src/settings.rs | 7 ++-- 8 files changed, 56 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e371d73..e0ef2c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -405,6 +405,15 @@ dependencies = [ "const-random", ] +[[package]] +name = "duration-string" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edbd404ab304f4426de3e981a875a77129597ce04202c9b8b4502c6f1c246809" +dependencies = [ + "serde", +] + [[package]] name = "encoding_rs" version = "0.8.35" @@ -1283,6 +1292,7 @@ version = "0.1.0" dependencies = [ "chrono", "config", + "duration-string", "env_logger", "include_dir", "lazy_static", diff --git a/Cargo.toml b/Cargo.toml index ccc5269..87898e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,3 +17,4 @@ chrono = "0.4.43" pushover = "0.4.0" config = "0.15.19" lazy_static = "1.5.0" +duration-string = { version="0.5.3", features = ["serde"] } diff --git a/oott.toml b/oott.toml index 4dcd6d8..cf52aec 100644 --- a/oott.toml +++ b/oott.toml @@ -5,9 +5,9 @@ interface = "eno1" # Network interface to use for scans level = "info" # off, error, warn, info, debug, trace [timings] -wait_between_scans="30" -arp_sender_timeout="30" -arp_scan_duration="60" +wait_between_scans="30s" +arp_sender_timeout="30s" +arp_scan_duration="60s" [notifications] method="pushover" # For now just pushover diff --git a/sample_oott.toml b/sample_oott.toml index 12561d5..cd7e233 100644 --- a/sample_oott.toml +++ b/sample_oott.toml @@ -5,9 +5,9 @@ interface = "eno1" # Network interface to use for scans level = "info" # off, error, warn, info, debug, trace [timings] -wait_between_scans="900" # Wait time between scans (in seconds). This does not include the scan time -arp_sender_timeout="60" # If the ARP sender process takes longer than this (in seconds) it will be stopped (for a class C network - 254 IPs - it should take less than a minute) -arp_scan_duration="300" # How long to wait (in seconds) for response packets on each scan (300 to 600 seconds is a good timeframe for a class B or C network) +wait_between_scans="15m" # Wait time between scans. This does not include the scan time +arp_sender_timeout="1m" # If the ARP sender process takes longer than this it will be stopped (for a class C network - 254 IPs - it should take less than a minute) +arp_scan_duration="30s" # How long to wait for response packets on each scan (5m to 10m is a good timeframe for a class B or C network) [notifications] method="pushover" # For now just pushover, you can set this to "none" to avoid sending notifications (it will just log) diff --git a/src/device_finders/arp.rs b/src/device_finders/arp.rs index d963483..7d74d08 100644 --- a/src/device_finders/arp.rs +++ b/src/device_finders/arp.rs @@ -1,6 +1,7 @@ mod packet_send_receive; use crate::{device_finders::Device, settings::CONFIG}; +use duration_string::DurationString; use log::{debug, error, info, warn}; use packet_send_receive::{listen_for_packets, send_packet}; use pnet::{ @@ -81,34 +82,45 @@ pub async fn find(interface: String) -> Result, String> { let send_interface = network_interface.clone(); // Get timeouts - let sender_timeout = CONFIG.timings.arp_sender_timeout; - info!("Sender timeout set to {} seconds", sender_timeout); - let scan_duration = CONFIG.timings.arp_scan_duration; - let receiver_timeout = scan_duration * 2; - info!("Scan duration set to {} seconds", scan_duration); - info!("Receiver timeout set to {} seconds", receiver_timeout); + let sender_timeout: Duration = CONFIG.timings.arp_sender_timeout.into(); + info!( + "Sender timeout set to {}", + CONFIG.timings.arp_sender_timeout + ); + let scan_duration: Duration = CONFIG.timings.arp_scan_duration.into(); + let receiver_timeout: Duration = scan_duration * 2; + info!("Scan duration set to {}", CONFIG.timings.arp_scan_duration); + info!( + "Receiver timeout set to {}", + String::from(DurationString::from(receiver_timeout)) + ); if sender_timeout >= scan_duration { warn!( - "OOTT_ARP_SENDER_TIMEOUT ({sender_timeout}) needs to be smaller than OOTT_ARP_SCAN_DURATION ({scan_duration})." + "OOTT_ARP_SENDER_TIMEOUT ({}) needs to be smaller than OOTT_ARP_SCAN_DURATION ({}).", + CONFIG.timings.arp_sender_timeout, CONFIG.timings.arp_scan_duration ); - return Err(format!("OOTT_ARP_SENDER_TIMEOUT ({sender_timeout}) needs to be smaller than OOTT_ARP_SCAN_DURATION ({scan_duration}).").to_string()); + return Err(format!( + "OOTT_ARP_SENDER_TIMEOUT ({}) needs to be smaller than OOTT_ARP_SCAN_DURATION ({}).", + CONFIG.timings.arp_sender_timeout, CONFIG.timings.arp_scan_duration + ) + .to_string()); } let result = tokio::join!( timeout( - Duration::from_secs(sender_timeout), + sender_timeout, send_packet(sender, send_interface, ipv4_net, mac), ), timeout( - Duration::from_secs(receiver_timeout), + receiver_timeout, listen_for_packets(receiver, ipv4_net, scan_duration), ) ); match result { (Ok(_), Ok(_)) => info!("ARP sender and receiver done"), - (Err(_), _) => warn!("ARP sender timed out"), + (Err(_), _) => warn!("ARP sender timed out. Consider increasing its duration."), (_, Err(_)) => info!("ARP receiver timed out"), }; diff --git a/src/device_finders/arp/packet_send_receive.rs b/src/device_finders/arp/packet_send_receive.rs index 891df12..e8877e1 100644 --- a/src/device_finders/arp/packet_send_receive.rs +++ b/src/device_finders/arp/packet_send_receive.rs @@ -1,6 +1,7 @@ use crate::device_finders::Device; use crate::mac_vendor_finder; use chrono::Local; +use duration_string::DurationString; use log::{debug, info}; use pnet::datalink::{DataLinkReceiver, DataLinkSender, NetworkInterface}; use pnet::ipnetwork::Ipv4Network; @@ -65,15 +66,18 @@ pub async fn send_packet( pub async fn listen_for_packets( mut rx: Box, ipv4_net: Ipv4Network, - run_for_secs: u64, + run_for: Duration, ) -> Vec { - info!("Starting ARP receiver for {} secs", run_for_secs); + info!( + "Starting ARP receiver for {}", + String::from(DurationString::from(run_for)) + ); let start_time = Instant::now(); let mut devices = Vec::new(); // Run while still under the time window - while (Instant::now() - start_time).as_secs() <= run_for_secs { + while start_time.elapsed() <= run_for { let arp_buffer = match rx.next() { Ok(buffer) => buffer, Err(_) => continue, @@ -109,8 +113,10 @@ pub async fn listen_for_packets( sleep(Duration::from_millis(1)).await; } info!( - "ARP receiver ran for {} secs", - (Instant::now() - start_time).as_secs() + "ARP receiver ran for {}", + String::from(DurationString::from(Duration::from_secs( + start_time.elapsed().as_secs() + ))) ); devices diff --git a/src/main.rs b/src/main.rs index 3a759ce..17da636 100644 --- a/src/main.rs +++ b/src/main.rs @@ -78,6 +78,6 @@ async fn main() -> Result<(), String> { "Scan finished. Sleeping for {} seconds", CONFIG.timings.wait_between_scans ); - sleep(Duration::from_secs(CONFIG.timings.wait_between_scans)).await; + sleep(Duration::from(CONFIG.timings.wait_between_scans)).await; } } diff --git a/src/settings.rs b/src/settings.rs index 5f7b061..7f766ba 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -1,4 +1,5 @@ use config::{Config, ConfigError, File}; +use duration_string::DurationString; use lazy_static::lazy_static; use log::error; use serde::Deserialize; @@ -18,9 +19,9 @@ pub struct Log { #[derive(Debug, Deserialize, Clone)] pub struct Timings { - pub wait_between_scans: u64, - pub arp_sender_timeout: u64, - pub arp_scan_duration: u64, + pub wait_between_scans: DurationString, + pub arp_sender_timeout: DurationString, + pub arp_scan_duration: DurationString, } #[derive(Debug, Deserialize, Clone)]