Parallel execution and timeouts working. Receiver returning found

devices properly.
This commit is contained in:
Ricardo Zuasti
2026-01-15 11:19:33 -05:00
parent dda430556b
commit 5a7d504905
4 changed files with 65 additions and 57 deletions
+3 -3
View File
@@ -1,4 +1,4 @@
[env]
RUST_LOG="info"
OOTT_ARP_SENDER_TIMEOUT="180"
OOTT_ARP_RECEIVER_TIMEOUT="300"
RUST_LOG="debug"
OOTT_ARP_SENDER_TIMEOUT="30"
OOTT_ARP_SCAN_DURATION="60"
+27 -46
View File
@@ -10,7 +10,7 @@ use pnet::{
use tokio::time::{Duration, Instant, timeout};
const DEFAULT_SENDER_TIMEOUT: u64 = 60; // 1 minute to send all packets - good for a class C network
const DEFAULT_RECEIVER_TIMEOUT: u64 = 300; // 5 minutes to wait per round to receive responses
const DEFAULT_SCAN_DURATION: u64 = 300; // 5 minutes to wait per round to receive responses
pub async fn find(interface: &str) -> Vec<Device> {
debug!("Looking up devices via ARP using interface {}", interface);
@@ -57,55 +57,36 @@ pub async fn find(interface: &str) -> Vec<Device> {
let send_interface = network_interface.clone();
// Spawn sender thread
info!("Starting ARP sender");
let sender_start = Instant::now();
// Get timeouts
let sender_timeout =
config::parse_env("OOTT_ARP_SENDER_TIMEOUT").unwrap_or(DEFAULT_SENDER_TIMEOUT);
debug!("Sender timeout set to {} seconds", sender_timeout);
let sender_thread = timeout(
Duration::from_secs(sender_timeout),
send_packet(sender, send_interface, ipv4_net, mac),
info!("Sender timeout set to {} seconds", sender_timeout);
let scan_duration =
config::parse_env("OOTT_ARP_SCAN_DURATION").unwrap_or(DEFAULT_SCAN_DURATION);
let receiver_timeout = scan_duration * 2;
info!("Scan duration set to {} seconds", scan_duration);
info!("Receiver timeout set to {} seconds", receiver_timeout);
if sender_timeout >= scan_duration {
panic!("OOTT_ARP_SENDER_TIMEOUT needs to be smaller than OOTT_ARP_SCAN_DURATION");
}
let result = tokio::join!(
timeout(
Duration::from_secs(sender_timeout),
send_packet(sender, send_interface, ipv4_net, mac),
),
timeout(
Duration::from_secs(receiver_timeout),
listen_for_packets(receiver, ipv4_net, scan_duration),
)
);
// Spawn receiver thread
info!("Starting ARP receiver");
let receiver_start = Instant::now();
let receiver_timeout =
config::parse_env("OOTT_ARP_RECEIVER_TIMEOUT").unwrap_or(DEFAULT_RECEIVER_TIMEOUT);
debug!("Receiver timeout set to {} seconds", receiver_timeout);
let receiver_thread = timeout(
Duration::from_secs(receiver_timeout),
listen_for_packets(receiver, ipv4_net),
);
// Now we wait
// Joining sender thread - It should have a shorter timeout than the receiver thread
let sender_result = sender_thread.await;
match sender_result {
Ok(_) => info!("ARP sender done"),
Err(_) => warn!("ARP sender timed out"),
match result {
(Ok(_), Ok(_)) => info!("ARP sender and receiver done"),
(Err(_), _) => warn!("ARP sender timed out"),
(_, Err(_)) => info!("ARP receiver timed out"),
};
info!(
"ARP sender took {} secs",
(Instant::now() - sender_start).as_secs()
);
// Joining receiver thread
let receiver_result = receiver_thread.await;
match receiver_result {
Ok(_) => info!("ARP receiver done"),
Err(_) => warn!("ARP receiver timed out"),
};
info!(
"ARP receiver took {} secs",
(Instant::now() - receiver_start).as_secs()
);
let mut devices = Vec::new();
devices.push(Device {
mac_address: String::from("mac"),
ipv4_address: String::from("ip"),
});
devices
result.1.unwrap_or(Vec::new())
}
+32 -6
View File
@@ -1,3 +1,4 @@
use crate::device_finders::Device;
use log::{debug, info, warn};
use pnet::datalink::{DataLinkReceiver, DataLinkSender, NetworkInterface};
use pnet::ipnetwork::Ipv4Network;
@@ -5,7 +6,7 @@ use pnet::packet::arp::{ArpHardwareTypes, ArpOperations, ArpPacket, MutableArpPa
use pnet::packet::ethernet::{EtherTypes, EthernetPacket, MutableEthernetPacket};
use pnet::packet::{MutablePacket, Packet};
use pnet::util::MacAddr;
use tokio::time::{Duration, sleep, timeout};
use tokio::time::{Duration, Instant, sleep};
pub async fn send_packet(
mut tx: Box<dyn DataLinkSender>,
@@ -13,7 +14,9 @@ pub async fn send_packet(
sender_ip: Ipv4Network,
sender_macaddr: MacAddr,
) {
info!("Starting ARP sender loop");
info!("Starting ARP sender");
let sender_start = Instant::now();
for target_ip in sender_ip.iter() {
if target_ip == sender_ip.ip() {
continue;
@@ -51,11 +54,24 @@ pub async fn send_packet(
// Sleep 1 millisecond between IPs
sleep(Duration::from_millis(1)).await;
}
info!(
"ARP sender took {} secs",
(Instant::now() - sender_start).as_secs()
);
}
pub async fn listen_for_packets(mut rx: Box<dyn DataLinkReceiver>, ipv4_net: Ipv4Network) {
info!("Starting ARP receiver loop");
loop {
pub async fn listen_for_packets(
mut rx: Box<dyn DataLinkReceiver>,
ipv4_net: Ipv4Network,
run_for_secs: u64,
) -> Vec<Device> {
info!("Starting ARP receiver for {} secs", run_for_secs);
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 {
let arp_buffer = match rx.next() {
Ok(buffer) => buffer,
Err(_) => continue,
@@ -68,15 +84,25 @@ pub async fn listen_for_packets(mut rx: Box<dyn DataLinkReceiver>, ipv4_net: Ipv
if arp_packet.get_operation() == ArpOperations::Reply {
debug!("It is an ARP reply packet");
if arp_packet.get_target_proto_addr() == ipv4_net.ip() {
info!(
debug!(
"Found online device - IP addr={} - MAC addr={}",
arp_packet.get_sender_proto_addr(),
arp_packet.get_sender_hw_addr()
);
devices.push(Device {
mac_address: arp_packet.get_sender_hw_addr().to_string(),
ipv4_address: arp_packet.get_sender_proto_addr().to_string(),
});
}
}
}
// Sleep 1 millisecond between IPs
sleep(Duration::from_millis(1)).await;
}
info!(
"ARP receiver run for {} secs",
(Instant::now() - start_time).as_secs()
);
devices
}
+3 -2
View File
@@ -7,11 +7,12 @@ async fn main() {
env_logger::init();
info!("Starting up oott");
let devices = device_finders::arp::find("eno1").await;
let devices = device_finders::arp::find("wlp1s0").await;
info!("Done with ARP probes");
info!("Found {} online devices", devices.iter().count());
for device in devices.iter() {
debug!("Device found {}", device);
info!("Device found {}", device);
}
info!("Exiting");
}