Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Speed up netscanner #42

Merged
merged 11 commits into from
Oct 20, 2024
182 changes: 92 additions & 90 deletions src/components/discovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,16 +105,17 @@ impl Discovery {
}

fn set_cidr(&mut self, cidr_str: String, scan: bool) {
match &cidr_str.parse::<Ipv4Cidr>() {
match cidr_str.parse::<Ipv4Cidr>() {
Ok(ip_cidr) => {
self.cidr = Some(*ip_cidr);
self.cidr = Some(ip_cidr);
if scan {
self.scan();
}
}
Err(e) => {
let tx = self.action_tx.clone().unwrap();
tx.send(Action::CidrError).unwrap();
if let Some(tx) = &self.action_tx {
Chleba marked this conversation as resolved.
Show resolved Hide resolved
tx.send(Action::CidrError).unwrap();
}
}
}
}
Expand All @@ -125,71 +126,72 @@ impl Discovery {
}

fn send_arp(&mut self, target_ip: Ipv4Addr) {
let active_interface = self.active_interface.clone().unwrap();
if let Some(active_interface_mac) = active_interface.mac {
let ipv4 = active_interface.ips.iter().find(|f| f.is_ipv4()).unwrap();
let source_ip: Ipv4Addr = ipv4.ip().to_string().parse().unwrap();

let (mut sender, _) =
match pnet::datalink::channel(&active_interface, Default::default()) {
Ok(Channel::Ethernet(tx, rx)) => (tx, rx),
Ok(_) => {
let tx_action = self.action_tx.clone().unwrap();
tx_action
.send(Action::Error("Unknown or unsopported channel type".into()))
.unwrap();
return;
}
Err(e) => {
let tx_action = self.action_tx.clone().unwrap();
tx_action
.send(Action::Error(format!(
"Unable to create datalink channel: {e}"
)))
.unwrap();
return;
}
};

let mut ethernet_buffer = [0u8; 42];
let mut ethernet_packet = MutableEthernetPacket::new(&mut ethernet_buffer).unwrap();

ethernet_packet.set_destination(MacAddr::broadcast());
// ethernet_packet.set_source(active_interface.mac.unwrap());
ethernet_packet.set_source(active_interface_mac);
ethernet_packet.set_ethertype(EtherTypes::Arp);

let mut arp_buffer = [0u8; 28];
let mut arp_packet = MutableArpPacket::new(&mut arp_buffer).unwrap();

arp_packet.set_hardware_type(ArpHardwareTypes::Ethernet);
arp_packet.set_protocol_type(EtherTypes::Ipv4);
arp_packet.set_hw_addr_len(6);
arp_packet.set_proto_addr_len(4);
arp_packet.set_operation(ArpOperations::Request);
arp_packet.set_sender_hw_addr(active_interface_mac);
arp_packet.set_sender_proto_addr(source_ip);
arp_packet.set_target_hw_addr(MacAddr::zero());
arp_packet.set_target_proto_addr(target_ip);

ethernet_packet.set_payload(arp_packet.packet_mut());

sender
.send_to(ethernet_packet.packet(), None)
.unwrap()
.unwrap();
if let Some(active_interface) = &self.active_interface {
if let Some(active_interface_mac) = active_interface.mac {
let ipv4 = active_interface.ips.iter().find(|f| f.is_ipv4()).unwrap();
let source_ip: Ipv4Addr = ipv4.ip().to_string().parse().unwrap();

let (mut sender, _) =
match pnet::datalink::channel(active_interface, Default::default()) {
Ok(Channel::Ethernet(tx, rx)) => (tx, rx),
Ok(_) => {
if let Some(tx_action) = &self.action_tx {
tx_action
.send(Action::Error("Unknown or unsupported channel type".into()))
.unwrap();
}
return;
}
Err(e) => {
if let Some(tx_action) = &self.action_tx {
tx_action
.send(Action::Error(format!(
"Unable to create datalink channel: {e}"
)))
.unwrap();
}
return;
}
};

let mut ethernet_buffer = [0u8; 42];
let mut ethernet_packet = MutableEthernetPacket::new(&mut ethernet_buffer).unwrap();

ethernet_packet.set_destination(MacAddr::broadcast());
ethernet_packet.set_source(active_interface_mac);
ethernet_packet.set_ethertype(EtherTypes::Arp);

let mut arp_buffer = [0u8; 28];
let mut arp_packet = MutableArpPacket::new(&mut arp_buffer).unwrap();

arp_packet.set_hardware_type(ArpHardwareTypes::Ethernet);
arp_packet.set_protocol_type(EtherTypes::Ipv4);
arp_packet.set_hw_addr_len(6);
arp_packet.set_proto_addr_len(4);
arp_packet.set_operation(ArpOperations::Request);
arp_packet.set_sender_hw_addr(active_interface_mac);
arp_packet.set_sender_proto_addr(source_ip);
arp_packet.set_target_hw_addr(MacAddr::zero());
arp_packet.set_target_proto_addr(target_ip);

ethernet_packet.set_payload(arp_packet.packet_mut());

sender
.send_to(ethernet_packet.packet(), None)
.unwrap()
.unwrap();
}
}
}

fn scan(&mut self) {
self.reset_scan();

Chleba marked this conversation as resolved.
Show resolved Hide resolved
if let Some(cidr) = self.cidr {
self.is_scanning = true;
let tx = self.action_tx.clone().unwrap();
let tx = self.action_tx.as_ref().unwrap().clone();
self.task = tokio::spawn(async move {
let ips = get_ips4_from_cidr(cidr);
let tx = tx.clone();
let chunks: Vec<_> = ips.chunks(POOL_SIZE).collect();
for chunk in chunks {
let tasks: Vec<_> = chunk
Expand All @@ -204,7 +206,7 @@ impl Discovery {
.pinger(IpAddr::V4(ip), PingIdentifier(random()))
.await;
pinger.timeout(Duration::from_secs(2));

Chleba marked this conversation as resolved.
Show resolved Hide resolved
match pinger.ping(PingSequence(2), &payload).await {
Ok((IcmpPacket::V4(packet), dur)) => {
tx.send(Action::PingIp(packet.get_real_dest().to_string()))
Expand All @@ -222,7 +224,7 @@ impl Discovery {
task::spawn(closure())
})
.collect();

Chleba marked this conversation as resolved.
Show resolved Hide resolved
let _ = join_all(tasks).await;
}
});
Expand Down Expand Up @@ -250,32 +252,32 @@ impl Discovery {
}

fn process_ip(&mut self, ip: &str) {
let tx = self.action_tx.clone().unwrap();
let tx = self.action_tx.as_ref().unwrap();
let ipv4: Ipv4Addr = ip.parse().unwrap();
self.send_arp(ipv4);

if let Some(n) = self.scanned_ips.iter_mut().find(|item| item.ip == ip) {
let hip: IpAddr = ip.parse().unwrap();
let host = lookup_addr(&hip).unwrap_or(String::from(""));
let host = lookup_addr(&hip).unwrap_or_default();
n.hostname = host;
n.ip = ip.to_string();
} else {
let hip: IpAddr = ip.parse().unwrap();
let host = lookup_addr(&hip).unwrap_or(String::from(""));
let host = lookup_addr(&hip).unwrap_or_default();
self.scanned_ips.push(ScannedIp {
ip: ip.to_string(),
mac: String::from(""),
mac: String::new(),
hostname: host,
vendor: String::from(""),
vendor: String::new(),
});

self.scanned_ips.sort_by(|a, b| {
let a_ip: Ipv4Addr = a.ip.parse::<Ipv4Addr>().unwrap();
let b_ip: Ipv4Addr = b.ip.parse::<Ipv4Addr>().unwrap();
a_ip.partial_cmp(&b_ip).unwrap()
});
}

self.set_scrollbar_height();
}

Expand Down Expand Up @@ -336,11 +338,11 @@ impl Discovery {
self.scrollbar_state = self.scrollbar_state.position(index);
}

fn make_table(
scanned_ips: Vec<ScannedIp>,
fn make_table<'a>(
scanned_ips: &'a Vec<ScannedIp>,
cidr: Option<Ipv4Cidr>,
ip_num: i32,
) -> Table<'static> {
) -> Table<'a> {
let header = Row::new(vec!["ip", "mac", "hostname", "vendor"])
.style(Style::default().fg(Color::Yellow))
.top_margin(1)
Expand All @@ -350,20 +352,20 @@ impl Discovery {
Some(c) => count_ipv4_net_length(c.network_length() as u32),
None => 0,
};

for sip in scanned_ips {
let ip = &sip.ip;
rows.push(Row::new(vec![
Cell::from(Span::styled(
format!("{ip:<2}"),
Style::default().fg(Color::Blue),
)),
Cell::from(sip.mac.clone().green()),
Cell::from(sip.hostname.clone()),
Cell::from(sip.vendor.clone().yellow()),
Cell::from(sip.mac.as_str().green()),
Cell::from(sip.hostname.as_str()),
Cell::from(sip.vendor.as_str().yellow()),
]));
}

let table = Table::new(
rows,
[
Expand Down Expand Up @@ -651,15 +653,15 @@ impl Component for Discovery {
fn draw(&mut self, f: &mut Frame<'_>, area: Rect) -> Result<()> {
if self.active_tab == TabsEnum::Discovery {
let layout = get_vertical_layout(area);

// -- TABLE
let mut table_rect = layout.bottom;
table_rect.y += 1;
table_rect.height -= 1;

let table = Self::make_table(self.scanned_ips.clone(), self.cidr, self.ip_num);
f.render_stateful_widget(table, table_rect, &mut self.table_state.clone());

let table = Self::make_table(&self.scanned_ips, self.cidr, self.ip_num);
f.render_stateful_widget(table, table_rect, &mut self.table_state);
// -- SCROLLBAR
let scrollbar = Self::make_scrollbar();
let mut scroll_rect = table_rect;
Expand All @@ -673,14 +675,14 @@ impl Component for Discovery {
}),
&mut self.scrollbar_state,
);

// -- ERROR
if self.cidr_error {
let error_rect = Rect::new(table_rect.width - (19 + 41), table_rect.y + 1, 18, 3);
let block = self.make_error();
f.render_widget(block, error_rect);
}

// -- INPUT
let input_size: u16 = INPUT_SIZE as u16;
let input_rect = Rect::new(
Expand All @@ -689,15 +691,15 @@ impl Component for Discovery {
input_size,
3,
);

// -- INPUT_SIZE - 3 is offset for border + 1char for cursor
let scroll = self.input.visual_scroll(INPUT_SIZE - 3);
let mut block = self.make_input(scroll);
if self.is_scanning {
block = block.clone().add_modifier(Modifier::DIM);
block = block.add_modifier(Modifier::DIM);
}
f.render_widget(block, input_rect);

// -- cursor
match self.mode {
Mode::Input => {
Expand All @@ -710,15 +712,15 @@ impl Component for Discovery {
}
Mode::Normal => {}
}

// -- THROBBER
if self.is_scanning {
let throbber = self.make_spinner();
let throbber_rect = Rect::new(input_rect.x + 1, input_rect.y, 12, 1);
f.render_widget(throbber, throbber_rect);
}
}

Ok(())
}
}
17 changes: 8 additions & 9 deletions src/components/packetdump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ impl PacketDump {
let (_, mut receiver) = match pnet::datalink::channel(&interface, Default::default()) {
Ok(Channel::Ethernet(tx, rx)) => (tx, rx),
Ok(_) => {
tx.send(Action::Error("Unknown or unsopported channel type".into()))
tx.send(Action::Error("Unknown or unsupported channel type".into()))
.unwrap();
return;
}
Expand All @@ -424,14 +424,13 @@ impl PacketDump {
)))
.unwrap();
return;
} // Ok(_) => panic!("Unknown channel type"),
// Err(e) => panic!("Error happened {}", e),
}
};
// while !paused.load(Ordering::Relaxed) {

loop {
let mut buf: [u8; 1600] = [0u8; 1600];
let mut fake_ethernet_frame = MutableEthernetPacket::new(&mut buf[..]).unwrap();

match receiver.next() {
Ok(packet) => {
let payload_offset;
Expand Down Expand Up @@ -490,9 +489,9 @@ impl PacketDump {

fn start_loop(&mut self) {
if self.loop_thread.is_none() {
let tx = self.action_tx.clone().unwrap();
let interface = self.active_interface.clone().unwrap();
let paused = self.dump_paused.clone();
let tx = self.action_tx.take().unwrap();
Chleba marked this conversation as resolved.
Show resolved Hide resolved
let interface = self.active_interface.take().unwrap();
let paused = Arc::clone(&self.dump_paused);
let t_handle = thread::spawn(move || {
Self::t_logic(tx, interface, paused);
});
Expand All @@ -516,7 +515,7 @@ impl PacketDump {

pub fn get_arp_packages(&self) -> Vec<(DateTime<Local>, PacketsInfoTypesEnum)> {
let a = &self.arp_packets.get_vec().to_vec();
a.clone()
a.to_vec()
Chleba marked this conversation as resolved.
Show resolved Hide resolved
}

pub fn clone_array_by_packet_type(
Expand Down
Loading
Loading