From 77cbe3017d959b7d4cc921f4d441fe8c11ba8032 Mon Sep 17 00:00:00 2001 From: Giuliano Bellini s294739 Date: Sat, 30 Dec 2023 18:52:53 +0100 Subject: [PATCH 01/16] adding support for new link_types: null/loopback and ipv4/ipv6 --- src/gui/pages/overview_page.rs | 22 +- src/gui/types/runtime_data.rs | 4 + src/gui/types/sniffer.rs | 1 + src/networking/manage_packets.rs | 2 +- src/networking/types/info_traffic.rs | 4 + src/secondary_threads/parse_packets.rs | 304 ++++++++++++++----------- 6 files changed, 202 insertions(+), 135 deletions(-) diff --git a/src/gui/pages/overview_page.rs b/src/gui/pages/overview_page.rs index 5d35f675..7a4472ef 100644 --- a/src/gui/pages/overview_page.rs +++ b/src/gui/pages/overview_page.rs @@ -12,6 +12,7 @@ use iced::widget::{ use iced::widget::{horizontal_space, Rule}; use iced::Length::{Fill, FillPortion, Fixed}; use iced::{Alignment, Font, Length, Renderer}; +use pcap::Linktype; use crate::countries::country_utils::get_flag_tooltip; use crate::countries::flags_pictures::FLAGS_WIDTH_BIG; @@ -65,11 +66,13 @@ pub fn overview_page(sniffer: &Sniffer) -> Container { //no packets observed at all - body = body_no_packets(&sniffer.device, font, language, &sniffer.waiting); + body = + body_no_packets(&sniffer.device, font, language, &sniffer.waiting, link_type); } (observed, 0) => { //no packets have been filtered but some have been observed @@ -139,8 +142,10 @@ fn body_no_packets( font: Font, language: Language, waiting: &str, + link_type: Linktype, ) -> Column<'static, Message, Renderer> { - let adapter_name = device.name.clone(); + let mut adapter_name = device.name.clone(); + adapter_name.push_str(&format!(" ({})", link_type.0,)); let (icon_text, nothing_to_see_text) = if device.addresses.lock().unwrap().is_empty() { ( Icon::Warning.to_text().size(60), @@ -422,8 +427,10 @@ fn lazy_col_info( let filtered_bytes = sniffer.runtime_data.tot_sent_bytes + sniffer.runtime_data.tot_received_bytes; let all_bytes = sniffer.runtime_data.all_bytes; + let link_type = sniffer.runtime_data.link_type; - let col_device_filters = col_device_filters(language, font, &sniffer.filters, &sniffer.device); + let col_device_filters = + col_device_filters(language, font, &sniffer.filters, &sniffer.device, link_type); let col_data_representation = col_data_representation(language, font, sniffer.traffic_chart.chart_type); @@ -512,19 +519,22 @@ fn col_device_filters( font: Font, filters: &Filters, device: &MyDevice, + link_type: Linktype, ) -> Column<'static, Message, Renderer> { #[cfg(not(target_os = "windows"))] - let adapter_info = &device.name; + let mut adapter_info = device.name.to_owned(); #[cfg(target_os = "windows")] let adapter_name = &device.name; #[cfg(target_os = "windows")] - let adapter_info = device.desc.as_ref().unwrap_or(adapter_name); + let mut adapter_info = device.desc.as_ref().unwrap_or(adapter_name); + + adapter_info.push_str(&format!(" ({})", link_type.0,)); Column::new() .width(Length::FillPortion(1)) .push(TextType::highlighted_subtitle_with_desc( network_adapter_translation(language), - adapter_info, + &adapter_info, font, )) .push(vertical_space(15)) diff --git a/src/gui/types/runtime_data.rs b/src/gui/types/runtime_data.rs index 6390e48d..c377f23b 100644 --- a/src/gui/types/runtime_data.rs +++ b/src/gui/types/runtime_data.rs @@ -1,11 +1,14 @@ //! Module defining the `RunTimeData` struct, useful to to generate chart and to display statistics about network traffic //! +use pcap::Linktype; use std::collections::VecDeque; use crate::notifications::types::logged_notification::LoggedNotification; /// Struct containing useful data to display statistics about network traffic and the relative notifications pub struct RunTimeData { + /// Link type of the current capture (e.g., ethernet) + pub link_type: Linktype, /// Total number of bytes (filtered and not filtered) pub all_bytes: u128, /// Total number of packets (filtered and not filtered) @@ -38,6 +41,7 @@ impl RunTimeData { /// Constructs a new `ChartsData` element. pub fn new() -> Self { RunTimeData { + link_type: Linktype::ETHERNET, all_bytes: 0, all_packets: 0, tot_sent_bytes: 0, diff --git a/src/gui/types/sniffer.rs b/src/gui/types/sniffer.rs index 6300f232..adb6cd1e 100644 --- a/src/gui/types/sniffer.rs +++ b/src/gui/types/sniffer.rs @@ -303,6 +303,7 @@ impl Sniffer { self.runtime_data.tot_received_bytes = info_traffic_lock.tot_received_bytes; self.runtime_data.tot_sent_bytes = info_traffic_lock.tot_sent_bytes; self.runtime_data.dropped_packets = info_traffic_lock.dropped_packets; + self.runtime_data.link_type = info_traffic_lock.link_type; drop(info_traffic_lock); let emitted_notifications = notify_and_log( &mut self.runtime_data, diff --git a/src/networking/manage_packets.rs b/src/networking/manage_packets.rs index 694ae554..ff6f15da 100644 --- a/src/networking/manage_packets.rs +++ b/src/networking/manage_packets.rs @@ -80,7 +80,7 @@ fn analyze_link_header( *mac_address2 = mac_from_dec_to_hex(header.destination); true } - _ => false, + _ => true, } } diff --git a/src/networking/types/info_traffic.rs b/src/networking/types/info_traffic.rs index 8e3b0ac8..bdfdc3d6 100644 --- a/src/networking/types/info_traffic.rs +++ b/src/networking/types/info_traffic.rs @@ -1,6 +1,7 @@ //! Module defining the `ReportInfo` struct, useful to format the output report file and //! to keep track of statistics about the sniffed traffic. +use pcap::Linktype; use std::collections::{HashMap, HashSet}; use crate::networking::types::address_port_pair::AddressPortPair; @@ -13,6 +14,8 @@ use crate::AppProtocol; /// Struct to be shared between the threads in charge of parsing packets and update reports. pub struct InfoTraffic { + /// Link type of the current capture (e.g., ethernet) + pub link_type: Linktype, /// Total amount of filtered bytes received. pub tot_received_bytes: u128, /// Total amount of filtered bytes sent. @@ -47,6 +50,7 @@ impl InfoTraffic { /// Constructs a new `InfoTraffic` element. pub fn new() -> Self { InfoTraffic { + link_type: Linktype::ETHERNET, tot_received_bytes: 0, tot_sent_bytes: 0, tot_received_packets: 0, diff --git a/src/secondary_threads/parse_packets.rs b/src/secondary_threads/parse_packets.rs index 33ac999e..a7764770 100644 --- a/src/secondary_threads/parse_packets.rs +++ b/src/secondary_threads/parse_packets.rs @@ -4,8 +4,8 @@ use std::sync::{Arc, Mutex}; use std::thread; -use etherparse::PacketHeaders; -use pcap::{Active, Capture}; +use etherparse::{PacketHeaders, ReadError}; +use pcap::{Active, Capture, Linktype, Packet}; use crate::mmdb::types::mmdb_reader::MmdbReader; use crate::networking::manage_packets::{ @@ -32,6 +32,8 @@ pub fn parse_packets( asn_mmdb_reader: &Arc, ) { let capture_id = *current_capture_id.lock().unwrap(); + let mut is_first_packet = true; + let mut link_type = cap.get_datalink(); loop { match cap.next_packet() { @@ -45,152 +47,198 @@ pub fn parse_packets( if *current_capture_id.lock().unwrap() != capture_id { return; } - match PacketHeaders::from_ethernet_slice(&packet) { - Err(_) => { - continue; + if let Ok(headers) = match is_first_packet { + true => { + is_first_packet = false; + get_sniffable_headers(&packet, &mut link_type, info_traffic_mutex) } - Ok(headers) => { - let mut exchanged_bytes = 0; - let mut mac_addresses = (String::new(), String::new()); - let mut icmp_type = IcmpType::default(); - let mut packet_filters_fields = PacketFiltersFields::default(); - - let key_option = analyze_headers( - headers, - &mut mac_addresses, - &mut exchanged_bytes, - &mut icmp_type, - &mut packet_filters_fields, - ); - if key_option.is_none() { - continue; + false => match link_type { + Linktype::IPV4 | Linktype::IPV6 => PacketHeaders::from_ip_slice(&packet), + Linktype::NULL | Linktype::LOOP => { + PacketHeaders::from_ip_slice(&packet[4..]) } + _ => PacketHeaders::from_ethernet_slice(&packet), + }, + } { + let mut exchanged_bytes = 0; + let mut mac_addresses = (String::new(), String::new()); + let mut icmp_type = IcmpType::default(); + let mut packet_filters_fields = PacketFiltersFields::default(); - let key = key_option.unwrap(); - let application_protocol = get_app_protocol(key.port1, key.port2); - let mut new_info = InfoAddressPortPair::default(); - - let passed_filters = filters.matches(&packet_filters_fields); - if passed_filters { - new_info = modify_or_insert_in_map( - info_traffic_mutex, - &key, - device, - mac_addresses, - icmp_type, - exchanged_bytes, - application_protocol, - ); - } + let key_option = analyze_headers( + headers, + &mut mac_addresses, + &mut exchanged_bytes, + &mut icmp_type, + &mut packet_filters_fields, + ); + if key_option.is_none() { + continue; + } - let mut info_traffic = info_traffic_mutex - .lock() - .expect("Error acquiring mutex\n\r"); - //increment number of sniffed packets and bytes - info_traffic.all_packets += 1; - info_traffic.all_bytes += exchanged_bytes; - // update dropped packets number - if let Ok(stats) = cap.stats() { - info_traffic.dropped_packets = stats.dropped; - } + let key = key_option.unwrap(); + let application_protocol = get_app_protocol(key.port1, key.port2); + let mut new_info = InfoAddressPortPair::default(); + + let passed_filters = filters.matches(&packet_filters_fields); + if passed_filters { + new_info = modify_or_insert_in_map( + info_traffic_mutex, + &key, + device, + mac_addresses, + icmp_type, + exchanged_bytes, + application_protocol, + ); + } + + let mut info_traffic = info_traffic_mutex + .lock() + .expect("Error acquiring mutex\n\r"); + //increment number of sniffed packets and bytes + info_traffic.all_packets += 1; + info_traffic.all_bytes += exchanged_bytes; + // update dropped packets number + if let Ok(stats) = cap.stats() { + info_traffic.dropped_packets = stats.dropped; + } - if passed_filters { - info_traffic.add_packet(exchanged_bytes, new_info.traffic_direction); + if passed_filters { + info_traffic.add_packet(exchanged_bytes, new_info.traffic_direction); - // check the rDNS status of this address and act accordingly - let address_to_lookup = - get_address_to_lookup(&key, new_info.traffic_direction); - let r_dns_already_resolved = info_traffic - .addresses_resolved + // check the rDNS status of this address and act accordingly + let address_to_lookup = + get_address_to_lookup(&key, new_info.traffic_direction); + let r_dns_already_resolved = info_traffic + .addresses_resolved + .contains_key(&address_to_lookup); + let mut r_dns_waiting_resolution = false; + if !r_dns_already_resolved { + r_dns_waiting_resolution = info_traffic + .addresses_waiting_resolution .contains_key(&address_to_lookup); - let mut r_dns_waiting_resolution = false; - if !r_dns_already_resolved { - r_dns_waiting_resolution = info_traffic - .addresses_waiting_resolution - .contains_key(&address_to_lookup); - } + } - match (r_dns_waiting_resolution, r_dns_already_resolved) { - (false, false) => { - // rDNS not requested yet (first occurrence of this address to lookup) + match (r_dns_waiting_resolution, r_dns_already_resolved) { + (false, false) => { + // rDNS not requested yet (first occurrence of this address to lookup) - // Add this address to the map of addresses waiting for a resolution - // Useful to NOT perform again a rDNS lookup for this entry - info_traffic.addresses_waiting_resolution.insert( - address_to_lookup, - DataInfo::new_with_first_packet( - exchanged_bytes, + // Add this address to the map of addresses waiting for a resolution + // Useful to NOT perform again a rDNS lookup for this entry + info_traffic.addresses_waiting_resolution.insert( + address_to_lookup, + DataInfo::new_with_first_packet( + exchanged_bytes, + new_info.traffic_direction, + ), + ); + + // launch new thread to resolve host name + let key2 = key.clone(); + let info_traffic2 = info_traffic_mutex.clone(); + let device2 = device.clone(); + let country_db_reader_2 = country_mmdb_reader.clone(); + let asn_db_reader_2 = asn_mmdb_reader.clone(); + thread::Builder::new() + .name("thread_reverse_dns_lookup".to_string()) + .spawn(move || { + reverse_dns_lookup( + &info_traffic2, + &key2, new_info.traffic_direction, - ), - ); - - // launch new thread to resolve host name - let key2 = key.clone(); - let info_traffic2 = info_traffic_mutex.clone(); - let device2 = device.clone(); - let country_db_reader_2 = country_mmdb_reader.clone(); - let asn_db_reader_2 = asn_mmdb_reader.clone(); - thread::Builder::new() - .name("thread_reverse_dns_lookup".to_string()) - .spawn(move || { - reverse_dns_lookup( - &info_traffic2, - &key2, - new_info.traffic_direction, - &device2, - &country_db_reader_2, - &asn_db_reader_2, - ); - }) - .unwrap(); - } - (true, false) => { - // waiting for a previously requested rDNS resolution - // update the corresponding waiting address data - info_traffic - .addresses_waiting_resolution - .entry(address_to_lookup) - .and_modify(|data_info| { - data_info.add_packet( - exchanged_bytes, - new_info.traffic_direction, - ); - }); - } - (_, true) => { - // rDNS already resolved - // update the corresponding host's data info - let host = info_traffic - .addresses_resolved - .get(&address_to_lookup) - .unwrap() - .1 - .clone(); - info_traffic.hosts.entry(host).and_modify(|data_info_host| { - data_info_host.data_info.add_packet( + &device2, + &country_db_reader_2, + &asn_db_reader_2, + ); + }) + .unwrap(); + } + (true, false) => { + // waiting for a previously requested rDNS resolution + // update the corresponding waiting address data + info_traffic + .addresses_waiting_resolution + .entry(address_to_lookup) + .and_modify(|data_info| { + data_info.add_packet( exchanged_bytes, new_info.traffic_direction, ); }); - } } - - //increment the packet count for the sniffed app protocol - info_traffic - .app_protocols - .entry(application_protocol) - .and_modify(|data_info| { - data_info + (_, true) => { + // rDNS already resolved + // update the corresponding host's data info + let host = info_traffic + .addresses_resolved + .get(&address_to_lookup) + .unwrap() + .1 + .clone(); + info_traffic.hosts.entry(host).and_modify(|data_info_host| { + data_info_host + .data_info .add_packet(exchanged_bytes, new_info.traffic_direction); - }) - .or_insert(DataInfo::new_with_first_packet( - exchanged_bytes, - new_info.traffic_direction, - )); + }); + } } + + //increment the packet count for the sniffed app protocol + info_traffic + .app_protocols + .entry(application_protocol) + .and_modify(|data_info| { + data_info.add_packet(exchanged_bytes, new_info.traffic_direction); + }) + .or_insert(DataInfo::new_with_first_packet( + exchanged_bytes, + new_info.traffic_direction, + )); } } } } } } + +fn get_sniffable_headers<'a>( + packet: &'a Packet, + link_type: &mut Linktype, + info_traffic_mutex: &Arc>, +) -> Result, ReadError> { + let ethernet_result = PacketHeaders::from_ethernet_slice(&packet); + let ip_result = PacketHeaders::from_ip_slice(&packet); + let null_result = PacketHeaders::from_ip_slice(&packet[4..]); + + let is_ethernet_sniffable = are_headers_sniffable(ðernet_result); + let is_ip_sniffable = are_headers_sniffable(&ip_result); + let is_null_sniffable = are_headers_sniffable(&null_result); + + match (is_ethernet_sniffable, is_ip_sniffable, is_null_sniffable) { + (true, _, _) => { + *link_type = Linktype::ETHERNET; + info_traffic_mutex.lock().unwrap().link_type = Linktype::ETHERNET; + ethernet_result + } + (_, true, _) => { + *link_type = Linktype::IPV4; + info_traffic_mutex.lock().unwrap().link_type = Linktype::IPV4; + ip_result + } + (_, _, true) => { + *link_type = Linktype::NULL; + info_traffic_mutex.lock().unwrap().link_type = Linktype::NULL; + null_result + } + (false, false, false) => ethernet_result, + } +} + +fn are_headers_sniffable(headers_result: &Result) -> bool { + return if let Ok(headers) = headers_result { + headers.ip.is_some() && headers.transport.is_some() + } else { + false + }; +} From 4696a5ee79d531894543d7dcd872c99fe42b08f8 Mon Sep 17 00:00:00 2001 From: Giuliano Bellini s294739 Date: Sat, 30 Dec 2023 21:33:19 +0100 Subject: [PATCH 02/16] support parsing packets without ethernet header: mac addresses are now optional --- src/gui/pages/connection_details_page.rs | 11 +++++++-- src/networking/manage_packets.rs | 24 +++++++++---------- .../types/info_address_port_pair.rs | 4 ++-- src/secondary_threads/parse_packets.rs | 2 +- 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/gui/pages/connection_details_page.rs b/src/gui/pages/connection_details_page.rs index b4066b11..5b9bad3c 100644 --- a/src/gui/pages/connection_details_page.rs +++ b/src/gui/pages/connection_details_page.rs @@ -338,7 +338,7 @@ fn get_src_or_dest_col( caption: Row<'static, Message, Renderer>, ip: &String, port: Option, - mac: &str, + mac: &Option, font: Font, language: Language, timing_events: &TimingEvents, @@ -348,6 +348,13 @@ fn get_src_or_dest_col( } else { address_translation(language) }; + + let mac_str = if let Some(val) = mac { + &val + } else { + "-" + }; + Column::new() .spacing(4) .push( @@ -369,7 +376,7 @@ fn get_src_or_dest_col( ) .push(TextType::highlighted_subtitle_with_desc( mac_address_translation(language), - mac, + mac_str, font, )) } diff --git a/src/networking/manage_packets.rs b/src/networking/manage_packets.rs index ff6f15da..6efd7f77 100644 --- a/src/networking/manage_packets.rs +++ b/src/networking/manage_packets.rs @@ -28,14 +28,12 @@ use crate::{AppProtocol, InfoTraffic, IpVersion, Protocol}; /// Returns the relevant collected information. pub fn analyze_headers( headers: PacketHeaders, - mac_addresses: &mut (String, String), + mac_addresses: &mut (Option, Option), exchanged_bytes: &mut u128, icmp_type: &mut IcmpType, packet_filters_fields: &mut PacketFiltersFields, ) -> Option { - if !analyze_link_header(headers.link, &mut mac_addresses.0, &mut mac_addresses.1) { - return None; - } + analyze_link_header(headers.link, &mut mac_addresses.0, &mut mac_addresses.1); if !analyze_network_header( headers.ip, @@ -71,16 +69,18 @@ pub fn analyze_headers( /// Returns false if packet has to be skipped. fn analyze_link_header( link_header: Option, - mac_address1: &mut String, - mac_address2: &mut String, -) -> bool { + mac_address1: &mut Option, + mac_address2: &mut Option, +) { match link_header { Some(header) => { - *mac_address1 = mac_from_dec_to_hex(header.source); - *mac_address2 = mac_from_dec_to_hex(header.destination); - true + *mac_address1 = Some(mac_from_dec_to_hex(header.source)); + *mac_address2 = Some(mac_from_dec_to_hex(header.destination)); } - _ => true, + _ => { + *mac_address1 = None; + *mac_address2 = None; + }, } } @@ -167,7 +167,7 @@ pub fn modify_or_insert_in_map( info_traffic_mutex: &Arc>, key: &AddressPortPair, my_device: &MyDevice, - mac_addresses: (String, String), + mac_addresses: (Option, Option), icmp_type: IcmpType, exchanged_bytes: u128, application_protocol: AppProtocol, diff --git a/src/networking/types/info_address_port_pair.rs b/src/networking/types/info_address_port_pair.rs index 2ede47a8..9c16e517 100644 --- a/src/networking/types/info_address_port_pair.rs +++ b/src/networking/types/info_address_port_pair.rs @@ -17,9 +17,9 @@ use crate::AppProtocol; #[derive(Clone, Default)] pub struct InfoAddressPortPair { /// Source MAC address - pub mac_address1: String, + pub mac_address1: Option, /// Destination MAC address - pub mac_address2: String, + pub mac_address2: Option, /// Amount of bytes transmitted between the pair. pub transmitted_bytes: u128, /// Amount of packets transmitted between the pair. diff --git a/src/secondary_threads/parse_packets.rs b/src/secondary_threads/parse_packets.rs index a7764770..b09fae26 100644 --- a/src/secondary_threads/parse_packets.rs +++ b/src/secondary_threads/parse_packets.rs @@ -61,7 +61,7 @@ pub fn parse_packets( }, } { let mut exchanged_bytes = 0; - let mut mac_addresses = (String::new(), String::new()); + let mut mac_addresses = (None, None); let mut icmp_type = IcmpType::default(); let mut packet_filters_fields = PacketFiltersFields::default(); From f0c1d77791dd0487e71ed922e706a9af7fae117a Mon Sep 17 00:00:00 2001 From: Giuliano Bellini s294739 Date: Sat, 30 Dec 2023 22:23:59 +0100 Subject: [PATCH 03/16] print link_type_str and fix clippy lints --- src/gui/pages/connection_details_page.rs | 6 +- src/gui/pages/overview_page.rs | 11 +-- src/networking/manage_packets.rs | 17 ++--- src/secondary_threads/parse_packets.rs | 90 +++++++++++++----------- src/utils/formatted_strings.rs | 11 +++ 5 files changed, 75 insertions(+), 60 deletions(-) diff --git a/src/gui/pages/connection_details_page.rs b/src/gui/pages/connection_details_page.rs index 5b9bad3c..a3f4caf6 100644 --- a/src/gui/pages/connection_details_page.rs +++ b/src/gui/pages/connection_details_page.rs @@ -349,11 +349,7 @@ fn get_src_or_dest_col( address_translation(language) }; - let mac_str = if let Some(val) = mac { - &val - } else { - "-" - }; + let mac_str = if let Some(val) = mac { val } else { "-" }; Column::new() .spacing(4) diff --git a/src/gui/pages/overview_page.rs b/src/gui/pages/overview_page.rs index 7a4472ef..f65e33c9 100644 --- a/src/gui/pages/overview_page.rs +++ b/src/gui/pages/overview_page.rs @@ -43,7 +43,8 @@ use crate::translations::translations_2::{ only_top_30_hosts_translation, }; use crate::utils::formatted_strings::{ - get_active_filters_string, get_formatted_bytes_string_with_b, get_percentage_string, + get_active_filters_string, get_adapter_link_type_str, get_formatted_bytes_string_with_b, + get_percentage_string, }; use crate::utils::types::icon::Icon; use crate::{AppProtocol, ChartType, ConfigSettings, Language, RunningPage, StyleType}; @@ -522,19 +523,19 @@ fn col_device_filters( link_type: Linktype, ) -> Column<'static, Message, Renderer> { #[cfg(not(target_os = "windows"))] - let mut adapter_info = device.name.to_owned(); + let adapter_info = &device.name; #[cfg(target_os = "windows")] let adapter_name = &device.name; #[cfg(target_os = "windows")] - let mut adapter_info = device.desc.as_ref().unwrap_or(adapter_name); + let adapter_info = device.desc.as_ref().unwrap_or(adapter_name); - adapter_info.push_str(&format!(" ({})", link_type.0,)); + let adapter_link_type = get_adapter_link_type_str(adapter_info, link_type); Column::new() .width(Length::FillPortion(1)) .push(TextType::highlighted_subtitle_with_desc( network_adapter_translation(language), - &adapter_info, + &adapter_link_type, font, )) .push(vertical_space(15)) diff --git a/src/networking/manage_packets.rs b/src/networking/manage_packets.rs index 6efd7f77..171223b8 100644 --- a/src/networking/manage_packets.rs +++ b/src/networking/manage_packets.rs @@ -71,16 +71,13 @@ fn analyze_link_header( link_header: Option, mac_address1: &mut Option, mac_address2: &mut Option, -) { - match link_header { - Some(header) => { - *mac_address1 = Some(mac_from_dec_to_hex(header.source)); - *mac_address2 = Some(mac_from_dec_to_hex(header.destination)); - } - _ => { - *mac_address1 = None; - *mac_address2 = None; - }, +) { + if let Some(header) = link_header { + *mac_address1 = Some(mac_from_dec_to_hex(header.source)); + *mac_address2 = Some(mac_from_dec_to_hex(header.destination)); + } else { + *mac_address1 = None; + *mac_address2 = None; } } diff --git a/src/secondary_threads/parse_packets.rs b/src/secondary_threads/parse_packets.rs index b09fae26..a29c70fc 100644 --- a/src/secondary_threads/parse_packets.rs +++ b/src/secondary_threads/parse_packets.rs @@ -32,8 +32,11 @@ pub fn parse_packets( asn_mmdb_reader: &Arc, ) { let capture_id = *current_capture_id.lock().unwrap(); - let mut is_first_packet = true; + + // pcap seems to assign ethernet to all interfaces (at least on macOS)... let mut link_type = cap.get_datalink(); + // ...it'll be confirmed after having parsed the first packet! + let mut is_link_type_confirmed = false; loop { match cap.next_packet() { @@ -47,19 +50,12 @@ pub fn parse_packets( if *current_capture_id.lock().unwrap() != capture_id { return; } - if let Ok(headers) = match is_first_packet { - true => { - is_first_packet = false; - get_sniffable_headers(&packet, &mut link_type, info_traffic_mutex) - } - false => match link_type { - Linktype::IPV4 | Linktype::IPV6 => PacketHeaders::from_ip_slice(&packet), - Linktype::NULL | Linktype::LOOP => { - PacketHeaders::from_ip_slice(&packet[4..]) - } - _ => PacketHeaders::from_ethernet_slice(&packet), - }, - } { + if let Ok(headers) = get_sniffable_headers( + &packet, + &mut link_type, + info_traffic_mutex, + &mut is_link_type_confirmed, + ) { let mut exchanged_bytes = 0; let mut mac_addresses = (None, None); let mut icmp_type = IcmpType::default(); @@ -206,39 +202,53 @@ fn get_sniffable_headers<'a>( packet: &'a Packet, link_type: &mut Linktype, info_traffic_mutex: &Arc>, + is_link_type_confirmed: &mut bool, ) -> Result, ReadError> { - let ethernet_result = PacketHeaders::from_ethernet_slice(&packet); - let ip_result = PacketHeaders::from_ip_slice(&packet); - let null_result = PacketHeaders::from_ip_slice(&packet[4..]); - - let is_ethernet_sniffable = are_headers_sniffable(ðernet_result); - let is_ip_sniffable = are_headers_sniffable(&ip_result); - let is_null_sniffable = are_headers_sniffable(&null_result); - - match (is_ethernet_sniffable, is_ip_sniffable, is_null_sniffable) { - (true, _, _) => { - *link_type = Linktype::ETHERNET; - info_traffic_mutex.lock().unwrap().link_type = Linktype::ETHERNET; - ethernet_result - } - (_, true, _) => { - *link_type = Linktype::IPV4; - info_traffic_mutex.lock().unwrap().link_type = Linktype::IPV4; - ip_result - } - (_, _, true) => { - *link_type = Linktype::NULL; - info_traffic_mutex.lock().unwrap().link_type = Linktype::NULL; - null_result + match is_link_type_confirmed { + false => { + *is_link_type_confirmed = true; + + let ethernet_result = PacketHeaders::from_ethernet_slice(packet); + let ip_result = PacketHeaders::from_ip_slice(packet); + let null_result = PacketHeaders::from_ip_slice(&packet[4..]); + + let is_ethernet_sniffable = are_headers_sniffable(ðernet_result); + let is_ip_sniffable = are_headers_sniffable(&ip_result); + let is_null_sniffable = are_headers_sniffable(&null_result); + + match (is_ethernet_sniffable, is_ip_sniffable, is_null_sniffable) { + (true, _, _) => { + *link_type = Linktype::ETHERNET; + info_traffic_mutex.lock().unwrap().link_type = Linktype::ETHERNET; + ethernet_result + } + (_, true, _) => { + // it could be IPV4 as well as IPV6 but it should be the same + *link_type = Linktype::IPV4; + info_traffic_mutex.lock().unwrap().link_type = Linktype::IPV4; + ip_result + } + (_, _, true) => { + // it could be NULL as well as LOOP but it should be the same + *link_type = Linktype::NULL; + info_traffic_mutex.lock().unwrap().link_type = Linktype::NULL; + null_result + } + (false, false, false) => ethernet_result, + } } - (false, false, false) => ethernet_result, + true => match *link_type { + Linktype::IPV4 | Linktype::IPV6 => PacketHeaders::from_ip_slice(packet), + Linktype::NULL | Linktype::LOOP => PacketHeaders::from_ip_slice(&packet[4..]), + _ => PacketHeaders::from_ethernet_slice(packet), + }, } } fn are_headers_sniffable(headers_result: &Result) -> bool { - return if let Ok(headers) = headers_result { + if let Ok(headers) = headers_result { headers.ip.is_some() && headers.transport.is_some() } else { false - }; + } } diff --git a/src/utils/formatted_strings.rs b/src/utils/formatted_strings.rs index 954a25dd..1bb0632c 100644 --- a/src/utils/formatted_strings.rs +++ b/src/utils/formatted_strings.rs @@ -1,3 +1,4 @@ +use pcap::Linktype; use std::net::IpAddr; use crate::networking::types::filters::Filters; @@ -76,6 +77,16 @@ pub fn get_active_filters_string(filters: &Filters, language: Language) -> Strin filters_string } +pub fn get_adapter_link_type_str(adapter: &str, link_type: Linktype) -> String { + let link_type_str = match link_type { + Linktype::ETHERNET => "(Ethernet)", + Linktype::NULL | Linktype::LOOP => "(null/loopback)", + Linktype::IPV4 | Linktype::IPV6 => "(raw IP)", + _ => "", + }; + format!("{adapter} {link_type_str}") +} + /// Returns a String representing a quantity of bytes with its proper multiple (K, M, G, T) pub fn get_formatted_bytes_string(bytes: u128) -> String { let mut multiple_transmitted = String::new(); From f7673ef37459bd56870a8e8b38b49ab8a3075aca Mon Sep 17 00:00:00 2001 From: Giuliano Bellini s294739 Date: Sat, 30 Dec 2023 22:46:06 +0100 Subject: [PATCH 04/16] use TOFU only if at least one of the parsing strategies was successful --- src/chart/manage_chart_data.rs | 2 ++ src/secondary_threads/parse_packets.rs | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/chart/manage_chart_data.rs b/src/chart/manage_chart_data.rs index fe874efd..e97dc3ec 100644 --- a/src/chart/manage_chart_data.rs +++ b/src/chart/manage_chart_data.rs @@ -81,6 +81,7 @@ fn get_max(deque: &VecDeque<(u32, i64)>) -> i64 { #[cfg(test)] mod tests { + use pcap::Linktype; use std::collections::VecDeque; use crate::chart::manage_chart_data::{get_max, get_min, update_charts_data}; @@ -167,6 +168,7 @@ mod tests { style: StyleType::default(), }; let mut runtime_data = RunTimeData { + link_type: Linktype::ETHERNET, all_bytes: 0, all_packets: 0, tot_sent_bytes: tot_sent + 1111, diff --git a/src/secondary_threads/parse_packets.rs b/src/secondary_threads/parse_packets.rs index a29c70fc..019b731f 100644 --- a/src/secondary_threads/parse_packets.rs +++ b/src/secondary_threads/parse_packets.rs @@ -206,8 +206,6 @@ fn get_sniffable_headers<'a>( ) -> Result, ReadError> { match is_link_type_confirmed { false => { - *is_link_type_confirmed = true; - let ethernet_result = PacketHeaders::from_ethernet_slice(packet); let ip_result = PacketHeaders::from_ip_slice(packet); let null_result = PacketHeaders::from_ip_slice(&packet[4..]); @@ -218,17 +216,20 @@ fn get_sniffable_headers<'a>( match (is_ethernet_sniffable, is_ip_sniffable, is_null_sniffable) { (true, _, _) => { + *is_link_type_confirmed = true; *link_type = Linktype::ETHERNET; info_traffic_mutex.lock().unwrap().link_type = Linktype::ETHERNET; ethernet_result } (_, true, _) => { + *is_link_type_confirmed = true; // it could be IPV4 as well as IPV6 but it should be the same *link_type = Linktype::IPV4; info_traffic_mutex.lock().unwrap().link_type = Linktype::IPV4; ip_result } (_, _, true) => { + *is_link_type_confirmed = true; // it could be NULL as well as LOOP but it should be the same *link_type = Linktype::NULL; info_traffic_mutex.lock().unwrap().link_type = Linktype::NULL; From fa4ee555e017b1d8a25d8fbda473c4903f6358a6 Mon Sep 17 00:00:00 2001 From: Giuliano Bellini s294739 Date: Sun, 31 Dec 2023 00:17:28 +0100 Subject: [PATCH 05/16] removed useless link_type print when it's not confirmed yet --- src/gui/pages/overview_page.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/gui/pages/overview_page.rs b/src/gui/pages/overview_page.rs index f65e33c9..90c8883b 100644 --- a/src/gui/pages/overview_page.rs +++ b/src/gui/pages/overview_page.rs @@ -67,13 +67,11 @@ pub fn overview_page(sniffer: &Sniffer) -> Container { //no packets observed at all - body = - body_no_packets(&sniffer.device, font, language, &sniffer.waiting, link_type); + body = body_no_packets(&sniffer.device, font, language, &sniffer.waiting); } (observed, 0) => { //no packets have been filtered but some have been observed @@ -143,10 +141,8 @@ fn body_no_packets( font: Font, language: Language, waiting: &str, - link_type: Linktype, ) -> Column<'static, Message, Renderer> { - let mut adapter_name = device.name.clone(); - adapter_name.push_str(&format!(" ({})", link_type.0,)); + let adapter_name = device.name.clone(); let (icon_text, nothing_to_see_text) = if device.addresses.lock().unwrap().is_empty() { ( Icon::Warning.to_text().size(60), From 158ceb68672de2212a83dd523cba5a8410ddf549 Mon Sep 17 00:00:00 2001 From: Giuliano Bellini s294739 Date: Sun, 31 Dec 2023 10:43:54 +0100 Subject: [PATCH 06/16] Revert "removed useless link_type print when it's not confirmed yet" This reverts commit fa4ee555e017b1d8a25d8fbda473c4903f6358a6. --- src/gui/pages/overview_page.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/gui/pages/overview_page.rs b/src/gui/pages/overview_page.rs index 90c8883b..f65e33c9 100644 --- a/src/gui/pages/overview_page.rs +++ b/src/gui/pages/overview_page.rs @@ -67,11 +67,13 @@ pub fn overview_page(sniffer: &Sniffer) -> Container { //no packets observed at all - body = body_no_packets(&sniffer.device, font, language, &sniffer.waiting); + body = + body_no_packets(&sniffer.device, font, language, &sniffer.waiting, link_type); } (observed, 0) => { //no packets have been filtered but some have been observed @@ -141,8 +143,10 @@ fn body_no_packets( font: Font, language: Language, waiting: &str, + link_type: Linktype, ) -> Column<'static, Message, Renderer> { - let adapter_name = device.name.clone(); + let mut adapter_name = device.name.clone(); + adapter_name.push_str(&format!(" ({})", link_type.0,)); let (icon_text, nothing_to_see_text) = if device.addresses.lock().unwrap().is_empty() { ( Icon::Warning.to_text().size(60), From e1e388afe931f5554ef8c3365dd12dcb2bd3fe69 Mon Sep 17 00:00:00 2001 From: Giuliano Bellini s294739 Date: Sun, 31 Dec 2023 11:20:08 +0100 Subject: [PATCH 07/16] open Capture from pcap::Device instead of &str --- src/gui/types/sniffer.rs | 2 +- src/networking/manage_packets.rs | 2 +- src/networking/types/my_device.rs | 18 +++++++++++++++++- src/secondary_threads/parse_packets.rs | 1 + 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/gui/types/sniffer.rs b/src/gui/types/sniffer.rs index adb6cd1e..17c33820 100644 --- a/src/gui/types/sniffer.rs +++ b/src/gui/types/sniffer.rs @@ -293,6 +293,7 @@ impl Sniffer { fn refresh_data(&mut self) -> Command { let info_traffic_lock = self.info_traffic.lock().unwrap(); self.runtime_data.all_packets = info_traffic_lock.all_packets; + self.runtime_data.link_type = info_traffic_lock.link_type; if info_traffic_lock.tot_received_packets + info_traffic_lock.tot_sent_packets == 0 { drop(info_traffic_lock); return self.update(Message::Waiting); @@ -303,7 +304,6 @@ impl Sniffer { self.runtime_data.tot_received_bytes = info_traffic_lock.tot_received_bytes; self.runtime_data.tot_sent_bytes = info_traffic_lock.tot_sent_bytes; self.runtime_data.dropped_packets = info_traffic_lock.dropped_packets; - self.runtime_data.link_type = info_traffic_lock.link_type; drop(info_traffic_lock); let emitted_notifications = notify_and_log( &mut self.runtime_data, diff --git a/src/networking/manage_packets.rs b/src/networking/manage_packets.rs index 171223b8..8672c7dc 100644 --- a/src/networking/manage_packets.rs +++ b/src/networking/manage_packets.rs @@ -490,7 +490,7 @@ pub fn is_my_address(address_to_lookup: &String, my_interface_addresses: &Vec (Option, Option>) { - let cap_result = Capture::from_device(&*device.name) + let cap_result = Capture::from_device(device.to_pcap_device()) .expect("Capture initialization error\n\r") .promisc(true) .snaplen(256) //limit stored packets slice dimension (to keep more in the buffer) diff --git a/src/networking/types/my_device.rs b/src/networking/types/my_device.rs index f267a811..fad26d35 100644 --- a/src/networking/types/my_device.rs +++ b/src/networking/types/my_device.rs @@ -1,6 +1,6 @@ use std::sync::{Arc, Mutex}; -use pcap::Address; +use pcap::{Address, Device, DeviceFlags}; /// Represents the current inspected device. /// Used to keep in sync the device addresses in case of changes @@ -11,3 +11,19 @@ pub struct MyDevice { pub desc: Option, pub addresses: Arc>>, } + +impl MyDevice { + pub fn to_pcap_device(&self) -> Device { + for device in Device::list().unwrap_or_default() { + if device.name.eq(&self.name) { + return device; + } + } + Device::lookup().unwrap_or(None).unwrap_or(Device { + name: String::new(), + desc: None, + addresses: vec![], + flags: DeviceFlags::empty(), + }) + } +} diff --git a/src/secondary_threads/parse_packets.rs b/src/secondary_threads/parse_packets.rs index 019b731f..37e50da4 100644 --- a/src/secondary_threads/parse_packets.rs +++ b/src/secondary_threads/parse_packets.rs @@ -35,6 +35,7 @@ pub fn parse_packets( // pcap seems to assign ethernet to all interfaces (at least on macOS)... let mut link_type = cap.get_datalink(); + info_traffic_mutex.lock().unwrap().link_type = link_type; // ...it'll be confirmed after having parsed the first packet! let mut is_link_type_confirmed = false; From e853a409a300003f035eb75299928de2212ed1ae Mon Sep 17 00:00:00 2001 From: Giuliano Bellini s294739 Date: Sun, 31 Dec 2023 13:56:54 +0100 Subject: [PATCH 08/16] temporarily print link type infos of all the adapters --- src/main.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/main.rs b/src/main.rs index 1a62f5be..3d4e3f93 100644 --- a/src/main.rs +++ b/src/main.rs @@ -51,6 +51,31 @@ pub const SNIFFNET_LOWERCASE: &str = "sniffnet"; /// /// It initializes shared variables and loads configuration parameters pub fn main() -> iced::Result { + + for device in pcap::Device::list().expect("device lookup failed") { + println!("Found device! {:?}", device.name); + + let Ok(cap) = pcap::Capture::from_device(device) else { + println!(" Error creating capture"); + continue; + }; + let Ok(cap) = cap.immediate_mode(true).open() else { + println!(" Error opening capture"); + continue; + }; + + { + let l = cap.get_datalink(); + println!(" Main data link: {:?} {:?} {:?}", l, l.get_name(), l.get_description()) + } + + if let Ok(links) = cap.list_datalinks() { + for l in links { + println!(" {:?} {:?} {:?}", l, l.get_name(), l.get_description()); + } + } + } + parse_cli_args(); let configs1 = Arc::new(Mutex::new(Configs::load())); From 975ccc5ec651a9cb067e7c59d756a739516a9ffb Mon Sep 17 00:00:00 2001 From: Giuliano Bellini s294739 Date: Sun, 31 Dec 2023 15:22:48 +0100 Subject: [PATCH 09/16] don't use TOFU: trust link_type from pcap --- src/main.rs | 25 ------- src/secondary_threads/parse_packets.rs | 90 ++++++++++---------------- 2 files changed, 35 insertions(+), 80 deletions(-) diff --git a/src/main.rs b/src/main.rs index 3d4e3f93..1a62f5be 100644 --- a/src/main.rs +++ b/src/main.rs @@ -51,31 +51,6 @@ pub const SNIFFNET_LOWERCASE: &str = "sniffnet"; /// /// It initializes shared variables and loads configuration parameters pub fn main() -> iced::Result { - - for device in pcap::Device::list().expect("device lookup failed") { - println!("Found device! {:?}", device.name); - - let Ok(cap) = pcap::Capture::from_device(device) else { - println!(" Error creating capture"); - continue; - }; - let Ok(cap) = cap.immediate_mode(true).open() else { - println!(" Error opening capture"); - continue; - }; - - { - let l = cap.get_datalink(); - println!(" Main data link: {:?} {:?} {:?}", l, l.get_name(), l.get_description()) - } - - if let Ok(links) = cap.list_datalinks() { - for l in links { - println!(" {:?} {:?} {:?}", l, l.get_name(), l.get_description()); - } - } - } - parse_cli_args(); let configs1 = Arc::new(Mutex::new(Configs::load())); diff --git a/src/secondary_threads/parse_packets.rs b/src/secondary_threads/parse_packets.rs index 37e50da4..dd15f1be 100644 --- a/src/secondary_threads/parse_packets.rs +++ b/src/secondary_threads/parse_packets.rs @@ -1,6 +1,7 @@ //! Module containing functions executed by the thread in charge of parsing sniffed packets and //! inserting them in the shared map. +use std::io::ErrorKind; use std::sync::{Arc, Mutex}; use std::thread; @@ -33,11 +34,8 @@ pub fn parse_packets( ) { let capture_id = *current_capture_id.lock().unwrap(); - // pcap seems to assign ethernet to all interfaces (at least on macOS)... - let mut link_type = cap.get_datalink(); + let link_type = cap.get_datalink(); info_traffic_mutex.lock().unwrap().link_type = link_type; - // ...it'll be confirmed after having parsed the first packet! - let mut is_link_type_confirmed = false; loop { match cap.next_packet() { @@ -51,12 +49,7 @@ pub fn parse_packets( if *current_capture_id.lock().unwrap() != capture_id { return; } - if let Ok(headers) = get_sniffable_headers( - &packet, - &mut link_type, - info_traffic_mutex, - &mut is_link_type_confirmed, - ) { + if let Ok(headers) = get_sniffable_headers(&packet, link_type) { let mut exchanged_bytes = 0; let mut mac_addresses = (None, None); let mut icmp_type = IcmpType::default(); @@ -201,56 +194,43 @@ pub fn parse_packets( fn get_sniffable_headers<'a>( packet: &'a Packet, - link_type: &mut Linktype, - info_traffic_mutex: &Arc>, - is_link_type_confirmed: &mut bool, + link_type: Linktype, ) -> Result, ReadError> { - match is_link_type_confirmed { - false => { - let ethernet_result = PacketHeaders::from_ethernet_slice(packet); - let ip_result = PacketHeaders::from_ip_slice(packet); - let null_result = PacketHeaders::from_ip_slice(&packet[4..]); + match link_type { + Linktype(12) | Linktype::IPV4 | Linktype::IPV6 => PacketHeaders::from_ip_slice(packet), + Linktype::NULL | Linktype::LOOP => from_null_slice(packet), + _ => PacketHeaders::from_ethernet_slice(packet), + } +} - let is_ethernet_sniffable = are_headers_sniffable(ðernet_result); - let is_ip_sniffable = are_headers_sniffable(&ip_result); - let is_null_sniffable = are_headers_sniffable(&null_result); +fn from_null_slice(packet: &[u8]) -> Result { + if packet.len() < 4 { + return Err(ReadError::UnexpectedEndOfSlice(packet.len())); + } - match (is_ethernet_sniffable, is_ip_sniffable, is_null_sniffable) { - (true, _, _) => { - *is_link_type_confirmed = true; - *link_type = Linktype::ETHERNET; - info_traffic_mutex.lock().unwrap().link_type = Linktype::ETHERNET; - ethernet_result - } - (_, true, _) => { - *is_link_type_confirmed = true; - // it could be IPV4 as well as IPV6 but it should be the same - *link_type = Linktype::IPV4; - info_traffic_mutex.lock().unwrap().link_type = Linktype::IPV4; - ip_result - } - (_, _, true) => { - *is_link_type_confirmed = true; - // it could be NULL as well as LOOP but it should be the same - *link_type = Linktype::NULL; - info_traffic_mutex.lock().unwrap().link_type = Linktype::NULL; - null_result - } - (false, false, false) => ethernet_result, + let is_valid_af_inet = { + // based on https://wiki.wireshark.org/NullLoopback.md (2023-12-31) + fn matches(value: u32) -> bool { + match value { + // 2 = IPv4 on all platforms + // 24, 28, or 30 = IPv6 depending on platform + 2 | 24 | 28 | 30 => true, + _ => false, } } - true => match *link_type { - Linktype::IPV4 | Linktype::IPV6 => PacketHeaders::from_ip_slice(packet), - Linktype::NULL | Linktype::LOOP => PacketHeaders::from_ip_slice(&packet[4..]), - _ => PacketHeaders::from_ethernet_slice(packet), - }, - } -} - -fn are_headers_sniffable(headers_result: &Result) -> bool { - if let Ok(headers) = headers_result { - headers.ip.is_some() && headers.transport.is_some() + let h = &packet[..4]; + let b = [h[0], h[1], h[2], h[3]]; + // check both big endian and little endian representations + // as some OS'es use native endianess and others use big endian + matches(u32::from_le_bytes(b)) || matches(u32::from_be_bytes(b)) + }; + + if is_valid_af_inet { + PacketHeaders::from_ip_slice(&packet[4..]) } else { - false + Err(ReadError::IoError(std::io::Error::new( + ErrorKind::InvalidData, + "Invalid AF_INET / AF_INET6 value", + ))) } } From 228c509be7930bfe4ca4cd6cf1d1243005d34a3a Mon Sep 17 00:00:00 2001 From: Giuliano Bellini s294739 Date: Sun, 31 Dec 2023 16:40:19 +0100 Subject: [PATCH 10/16] created MyLinkType enum and fixing appearance (WIP) --- src/gui/pages/overview_page.rs | 36 +++++------ src/gui/types/runtime_data.rs | 8 +-- src/networking/types/info_traffic.rs | 6 +- src/networking/types/mod.rs | 1 + src/networking/types/my_link_type.rs | 89 ++++++++++++++++++++++++++ src/secondary_threads/parse_packets.rs | 3 +- src/translations/translations_3.rs | 8 +++ src/utils/formatted_strings.rs | 11 ---- 8 files changed, 124 insertions(+), 38 deletions(-) create mode 100644 src/networking/types/my_link_type.rs diff --git a/src/gui/pages/overview_page.rs b/src/gui/pages/overview_page.rs index f65e33c9..5520bcb8 100644 --- a/src/gui/pages/overview_page.rs +++ b/src/gui/pages/overview_page.rs @@ -12,7 +12,6 @@ use iced::widget::{ use iced::widget::{horizontal_space, Rule}; use iced::Length::{Fill, FillPortion, Fixed}; use iced::{Alignment, Font, Length, Renderer}; -use pcap::Linktype; use crate::countries::country_utils::get_flag_tooltip; use crate::countries::flags_pictures::FLAGS_WIDTH_BIG; @@ -29,6 +28,7 @@ use crate::networking::types::data_info::DataInfo; use crate::networking::types::filters::Filters; use crate::networking::types::host::Host; use crate::networking::types::my_device::MyDevice; +use crate::networking::types::my_link_type::MyLinkType; use crate::networking::types::search_parameters::SearchParameters; use crate::report::get_report_entries::{get_app_entries, get_host_entries}; use crate::translations::translations::{ @@ -43,8 +43,7 @@ use crate::translations::translations_2::{ only_top_30_hosts_translation, }; use crate::utils::formatted_strings::{ - get_active_filters_string, get_adapter_link_type_str, get_formatted_bytes_string_with_b, - get_percentage_string, + get_active_filters_string, get_formatted_bytes_string_with_b, get_percentage_string, }; use crate::utils::types::icon::Icon; use crate::{AppProtocol, ChartType, ConfigSettings, Language, RunningPage, StyleType}; @@ -143,10 +142,10 @@ fn body_no_packets( font: Font, language: Language, waiting: &str, - link_type: Linktype, + link_type: MyLinkType, ) -> Column<'static, Message, Renderer> { let mut adapter_name = device.name.clone(); - adapter_name.push_str(&format!(" ({})", link_type.0,)); + adapter_name.push_str(&format!("\n{}", link_type.full_print_on_one_line(language))); let (icon_text, nothing_to_see_text) = if device.addresses.lock().unwrap().is_empty() { ( Icon::Warning.to_text().size(60), @@ -430,8 +429,7 @@ fn lazy_col_info( let all_bytes = sniffer.runtime_data.all_bytes; let link_type = sniffer.runtime_data.link_type; - let col_device_filters = - col_device_filters(language, font, &sniffer.filters, &sniffer.device, link_type); + let col_device = col_device(language, font, &sniffer.device, link_type); let col_data_representation = col_data_representation(language, font, sniffer.traffic_chart.chart_type); @@ -444,6 +442,7 @@ fn lazy_col_info( all_bytes, filtered_bytes, font, + &sniffer.filters, ); let content = Column::new() @@ -453,14 +452,14 @@ fn lazy_col_info( Row::new() .height(Length::Fixed(120.0)) .push( - Scrollable::new(col_device_filters) - .width(Length::Fill) - .direction(Direction::Vertical(ScrollbarType::properties())), + Scrollable::new(col_device) + .width(Length::FillPortion(1)) + .direction(Direction::Horizontal(ScrollbarType::properties())), ) .push(Rule::vertical(25)) .push(col_data_representation), ) - .push(Rule::horizontal(25)) + .push(Rule::horizontal(15)) .push( Scrollable::new(col_bytes_packets) .width(Length::Fill) @@ -515,12 +514,11 @@ fn container_chart(sniffer: &Sniffer, font: Font) -> Container Column<'static, Message, Renderer> { #[cfg(not(target_os = "windows"))] let adapter_info = &device.name; @@ -529,17 +527,15 @@ fn col_device_filters( #[cfg(target_os = "windows")] let adapter_info = device.desc.as_ref().unwrap_or(adapter_name); - let adapter_link_type = get_adapter_link_type_str(adapter_info, link_type); - Column::new() + .spacing(15) .width(Length::FillPortion(1)) .push(TextType::highlighted_subtitle_with_desc( network_adapter_translation(language), - &adapter_link_type, + &adapter_info, font, )) - .push(vertical_space(15)) - .push(get_active_filters_col(filters, language, font, false)) + .push(link_type.link_type_col(language, font)) } fn col_data_representation( @@ -584,6 +580,7 @@ fn col_bytes_packets( all_bytes: u128, filtered_bytes: u128, font: Font, + filters: &Filters, ) -> Column<'static, Message, Renderer> { let dropped_val = if dropped > 0 { format!( @@ -606,6 +603,7 @@ fn col_bytes_packets( Column::new() .spacing(15) + .push(get_active_filters_col(filters, language, font, false)) .push(TextType::highlighted_subtitle_with_desc( filtered_bytes_translation(language), &bytes_value, diff --git a/src/gui/types/runtime_data.rs b/src/gui/types/runtime_data.rs index c377f23b..1de478db 100644 --- a/src/gui/types/runtime_data.rs +++ b/src/gui/types/runtime_data.rs @@ -1,6 +1,6 @@ //! Module defining the `RunTimeData` struct, useful to to generate chart and to display statistics about network traffic -//! -use pcap::Linktype; + +use crate::networking::types::my_link_type::MyLinkType; use std::collections::VecDeque; use crate::notifications::types::logged_notification::LoggedNotification; @@ -8,7 +8,7 @@ use crate::notifications::types::logged_notification::LoggedNotification; /// Struct containing useful data to display statistics about network traffic and the relative notifications pub struct RunTimeData { /// Link type of the current capture (e.g., ethernet) - pub link_type: Linktype, + pub link_type: MyLinkType, /// Total number of bytes (filtered and not filtered) pub all_bytes: u128, /// Total number of packets (filtered and not filtered) @@ -41,7 +41,7 @@ impl RunTimeData { /// Constructs a new `ChartsData` element. pub fn new() -> Self { RunTimeData { - link_type: Linktype::ETHERNET, + link_type: MyLinkType::NotYetAssigned, all_bytes: 0, all_packets: 0, tot_sent_bytes: 0, diff --git a/src/networking/types/info_traffic.rs b/src/networking/types/info_traffic.rs index bdfdc3d6..3431ea97 100644 --- a/src/networking/types/info_traffic.rs +++ b/src/networking/types/info_traffic.rs @@ -1,7 +1,6 @@ //! Module defining the `ReportInfo` struct, useful to format the output report file and //! to keep track of statistics about the sniffed traffic. -use pcap::Linktype; use std::collections::{HashMap, HashSet}; use crate::networking::types::address_port_pair::AddressPortPair; @@ -9,13 +8,14 @@ use crate::networking::types::data_info::DataInfo; use crate::networking::types::data_info_host::DataInfoHost; use crate::networking::types::host::Host; use crate::networking::types::info_address_port_pair::InfoAddressPortPair; +use crate::networking::types::my_link_type::MyLinkType; use crate::networking::types::traffic_direction::TrafficDirection; use crate::AppProtocol; /// Struct to be shared between the threads in charge of parsing packets and update reports. pub struct InfoTraffic { /// Link type of the current capture (e.g., ethernet) - pub link_type: Linktype, + pub link_type: MyLinkType, /// Total amount of filtered bytes received. pub tot_received_bytes: u128, /// Total amount of filtered bytes sent. @@ -50,7 +50,7 @@ impl InfoTraffic { /// Constructs a new `InfoTraffic` element. pub fn new() -> Self { InfoTraffic { - link_type: Linktype::ETHERNET, + link_type: MyLinkType::NotYetAssigned, tot_received_bytes: 0, tot_sent_bytes: 0, tot_received_packets: 0, diff --git a/src/networking/types/mod.rs b/src/networking/types/mod.rs index 2134f328..8bc652c1 100644 --- a/src/networking/types/mod.rs +++ b/src/networking/types/mod.rs @@ -12,6 +12,7 @@ pub mod info_traffic; pub mod ip_collection; pub mod ip_version; pub mod my_device; +pub mod my_link_type; pub mod packet_filters_fields; pub mod port_collection; pub mod protocol; diff --git a/src/networking/types/my_link_type.rs b/src/networking/types/my_link_type.rs new file mode 100644 index 00000000..5341c8e0 --- /dev/null +++ b/src/networking/types/my_link_type.rs @@ -0,0 +1,89 @@ +use crate::gui::styles::text::TextType; +use crate::gui::types::message::Message; +use crate::translations::translations_3::link_type_translation; +use crate::{Language, StyleType}; +use iced::widget::Column; +use iced::{Font, Renderer}; +use pcap::Linktype; + +#[derive(Copy, Clone)] +pub enum MyLinkType { + Supported(Linktype), + Unsupported(Linktype), + NotYetAssigned, +} + +impl MyLinkType { + pub fn is_supported(&self) -> bool { + match self { + MyLinkType::Supported(_) => true, + MyLinkType::Unsupported(_) | MyLinkType::NotYetAssigned => false, + } + } + + pub fn from_pcap_link_type(link_type: Linktype) -> Self { + match link_type { + Linktype::NULL + | Linktype::ETHERNET + | Linktype(12) + | Linktype::LOOP + | Linktype::IPV4 + | Linktype::IPV6 => Self::Supported(link_type), + _ => Self::Unsupported(link_type), + } + } + + pub fn full_print_on_one_line(&self, language: Language) -> String { + match self { + MyLinkType::Supported(l) => { + format!( + "{}: {} ({})", + link_type_translation(language), + l.get_name().unwrap_or(l.0.to_string()), + l.get_description().unwrap_or(String::new()) + ) + } + MyLinkType::Unsupported(l) => { + format!( + "{}: {} (NOT SUPPORTED)", + link_type_translation(language), + l.get_name().unwrap_or(l.0.to_string()), + ) + } + MyLinkType::NotYetAssigned => String::new(), + } + } + + pub fn link_type_col( + &self, + language: Language, + font: Font, + ) -> Column<'static, Message, Renderer> { + match self { + MyLinkType::Supported(l) => { + let link_info = format!( + "{} ({})", + l.get_name().unwrap_or(l.0.to_string()), + l.get_description().unwrap_or(String::new()) + ); + TextType::highlighted_subtitle_with_desc( + link_type_translation(language), + &link_info, + font, + ) + } + MyLinkType::Unsupported(l) => { + let link_info = format!( + "{} (NOT SUPPORTED)", + l.get_name().unwrap_or(l.0.to_string()), + ); + TextType::highlighted_subtitle_with_desc( + link_type_translation(language), + &link_info, + font, + ) + } + MyLinkType::NotYetAssigned => Column::new().height(0), + } + } +} diff --git a/src/secondary_threads/parse_packets.rs b/src/secondary_threads/parse_packets.rs index dd15f1be..2afd3cda 100644 --- a/src/secondary_threads/parse_packets.rs +++ b/src/secondary_threads/parse_packets.rs @@ -18,6 +18,7 @@ use crate::networking::types::filters::Filters; use crate::networking::types::icmp_type::IcmpType; use crate::networking::types::info_address_port_pair::InfoAddressPortPair; use crate::networking::types::my_device::MyDevice; +use crate::networking::types::my_link_type::MyLinkType; use crate::networking::types::packet_filters_fields::PacketFiltersFields; use crate::InfoTraffic; @@ -35,7 +36,7 @@ pub fn parse_packets( let capture_id = *current_capture_id.lock().unwrap(); let link_type = cap.get_datalink(); - info_traffic_mutex.lock().unwrap().link_type = link_type; + info_traffic_mutex.lock().unwrap().link_type = MyLinkType::from_pcap_link_type(link_type); loop { match cap.next_packet() { diff --git a/src/translations/translations_3.rs b/src/translations/translations_3.rs index 77d6041e..76d8d3bd 100644 --- a/src/translations/translations_3.rs +++ b/src/translations/translations_3.rs @@ -81,3 +81,11 @@ pub fn messages_translation(language: Language) -> &'static str { _ => "Messages", } } + +pub fn link_type_translation(language: Language) -> &'static str { + match language { + Language::EN => "Link type", + Language::IT => "Tipo di collegamento", + _ => "Link type", + } +} diff --git a/src/utils/formatted_strings.rs b/src/utils/formatted_strings.rs index 1bb0632c..954a25dd 100644 --- a/src/utils/formatted_strings.rs +++ b/src/utils/formatted_strings.rs @@ -1,4 +1,3 @@ -use pcap::Linktype; use std::net::IpAddr; use crate::networking::types::filters::Filters; @@ -77,16 +76,6 @@ pub fn get_active_filters_string(filters: &Filters, language: Language) -> Strin filters_string } -pub fn get_adapter_link_type_str(adapter: &str, link_type: Linktype) -> String { - let link_type_str = match link_type { - Linktype::ETHERNET => "(Ethernet)", - Linktype::NULL | Linktype::LOOP => "(null/loopback)", - Linktype::IPV4 | Linktype::IPV6 => "(raw IP)", - _ => "", - }; - format!("{adapter} {link_type_str}") -} - /// Returns a String representing a quantity of bytes with its proper multiple (K, M, G, T) pub fn get_formatted_bytes_string(bytes: u128) -> String { let mut multiple_transmitted = String::new(); From d6e8872628ace0017e1723c46bfa0afd0e0bed77 Mon Sep 17 00:00:00 2001 From: Giuliano Bellini s294739 Date: Mon, 1 Jan 2024 00:30:35 +0100 Subject: [PATCH 11/16] changed MyLinkType logic --- src/chart/manage_chart_data.rs | 4 +-- src/gui/pages/overview_page.rs | 15 ++++---- src/gui/types/sniffer.rs | 8 +++-- src/networking/types/info_traffic.rs | 4 --- src/networking/types/my_link_type.rs | 48 +++++++++++++++++--------- src/secondary_threads/parse_packets.rs | 17 ++++----- 6 files changed, 54 insertions(+), 42 deletions(-) diff --git a/src/chart/manage_chart_data.rs b/src/chart/manage_chart_data.rs index e97dc3ec..d8f35691 100644 --- a/src/chart/manage_chart_data.rs +++ b/src/chart/manage_chart_data.rs @@ -81,10 +81,10 @@ fn get_max(deque: &VecDeque<(u32, i64)>) -> i64 { #[cfg(test)] mod tests { - use pcap::Linktype; use std::collections::VecDeque; use crate::chart::manage_chart_data::{get_max, get_min, update_charts_data}; + use crate::networking::types::my_link_type::MyLinkType; use crate::{ChartType, Language, RunTimeData, StyleType, TrafficChart}; #[test] @@ -168,7 +168,7 @@ mod tests { style: StyleType::default(), }; let mut runtime_data = RunTimeData { - link_type: Linktype::ETHERNET, + link_type: MyLinkType::NotYetAssigned, all_bytes: 0, all_packets: 0, tot_sent_bytes: tot_sent + 1111, diff --git a/src/gui/pages/overview_page.rs b/src/gui/pages/overview_page.rs index 5520bcb8..574212ea 100644 --- a/src/gui/pages/overview_page.rs +++ b/src/gui/pages/overview_page.rs @@ -457,7 +457,7 @@ fn lazy_col_info( .direction(Direction::Horizontal(ScrollbarType::properties())), ) .push(Rule::vertical(25)) - .push(col_data_representation), + .push(col_data_representation.width(Length::FillPortion(1))), ) .push(Rule::horizontal(15)) .push( @@ -523,16 +523,13 @@ fn col_device( #[cfg(not(target_os = "windows"))] let adapter_info = &device.name; #[cfg(target_os = "windows")] - let adapter_name = &device.name; - #[cfg(target_os = "windows")] - let adapter_info = device.desc.as_ref().unwrap_or(adapter_name); + let adapter_info = device.desc.as_ref().unwrap_or(&device.name); Column::new() - .spacing(15) - .width(Length::FillPortion(1)) + .spacing(10) .push(TextType::highlighted_subtitle_with_desc( network_adapter_translation(language), - &adapter_info, + adapter_info, font, )) .push(link_type.link_type_col(language, font)) @@ -543,7 +540,7 @@ fn col_data_representation( font: Font, chart_type: ChartType, ) -> Column<'static, Message, Renderer> { - let mut ret_val = Column::new().spacing(5).width(Length::FillPortion(1)).push( + let mut ret_val = Column::new().spacing(5).push( Text::new(format!("{}:", data_representation_translation(language))) .style(TextType::Subtitle) .font(font), @@ -602,7 +599,7 @@ fn col_bytes_packets( }; Column::new() - .spacing(15) + .spacing(10) .push(get_active_filters_col(filters, language, font, false)) .push(TextType::highlighted_subtitle_with_desc( filtered_bytes_translation(language), diff --git a/src/gui/types/sniffer.rs b/src/gui/types/sniffer.rs index 17c33820..8e944377 100644 --- a/src/gui/types/sniffer.rs +++ b/src/gui/types/sniffer.rs @@ -24,6 +24,7 @@ use crate::networking::types::filters::Filters; use crate::networking::types::host::Host; use crate::networking::types::ip_collection::AddressCollection; use crate::networking::types::my_device::MyDevice; +use crate::networking::types::my_link_type::MyLinkType; use crate::networking::types::port_collection::PortCollection; use crate::networking::types::search_parameters::SearchParameters; use crate::notifications::notify_and_log::notify_and_log; @@ -293,7 +294,6 @@ impl Sniffer { fn refresh_data(&mut self) -> Command { let info_traffic_lock = self.info_traffic.lock().unwrap(); self.runtime_data.all_packets = info_traffic_lock.all_packets; - self.runtime_data.link_type = info_traffic_lock.link_type; if info_traffic_lock.tot_received_packets + info_traffic_lock.tot_sent_packets == 0 { drop(info_traffic_lock); return self.update(Message::Waiting); @@ -352,7 +352,7 @@ impl Sniffer { let current_device_name = &*self.device.name.clone(); self.set_adapter(current_device_name); let device = self.device.clone(); - let (pcap_error, cap) = get_capture_result(&device); + let (pcap_error, cap_result) = get_capture_result(&device); self.pcap_error = pcap_error.clone(); let info_traffic_mutex = self.info_traffic.clone(); *info_traffic_mutex.lock().unwrap() = InfoTraffic::new(); @@ -365,17 +365,19 @@ impl Sniffer { if pcap_error.is_none() { // no pcap error + let cap = cap_result.unwrap(); let current_capture_id = self.current_capture_id.clone(); let filters = self.filters.clone(); let country_mmdb_reader = self.country_mmdb_reader.clone(); let asn_mmdb_reader = self.asn_mmdb_reader.clone(); + self.runtime_data.link_type = MyLinkType::from_pcap_link_type(cap.get_datalink()); thread::Builder::new() .name("thread_parse_packets".to_string()) .spawn(move || { parse_packets( ¤t_capture_id, &device, - cap.unwrap(), + cap, &filters, &info_traffic_mutex, &country_mmdb_reader, diff --git a/src/networking/types/info_traffic.rs b/src/networking/types/info_traffic.rs index 3431ea97..8e3b0ac8 100644 --- a/src/networking/types/info_traffic.rs +++ b/src/networking/types/info_traffic.rs @@ -8,14 +8,11 @@ use crate::networking::types::data_info::DataInfo; use crate::networking::types::data_info_host::DataInfoHost; use crate::networking::types::host::Host; use crate::networking::types::info_address_port_pair::InfoAddressPortPair; -use crate::networking::types::my_link_type::MyLinkType; use crate::networking::types::traffic_direction::TrafficDirection; use crate::AppProtocol; /// Struct to be shared between the threads in charge of parsing packets and update reports. pub struct InfoTraffic { - /// Link type of the current capture (e.g., ethernet) - pub link_type: MyLinkType, /// Total amount of filtered bytes received. pub tot_received_bytes: u128, /// Total amount of filtered bytes sent. @@ -50,7 +47,6 @@ impl InfoTraffic { /// Constructs a new `InfoTraffic` element. pub fn new() -> Self { InfoTraffic { - link_type: MyLinkType::NotYetAssigned, tot_received_bytes: 0, tot_sent_bytes: 0, tot_received_packets: 0, diff --git a/src/networking/types/my_link_type.rs b/src/networking/types/my_link_type.rs index 5341c8e0..44367a39 100644 --- a/src/networking/types/my_link_type.rs +++ b/src/networking/types/my_link_type.rs @@ -6,36 +6,47 @@ use iced::widget::Column; use iced::{Font, Renderer}; use pcap::Linktype; +/// Currently supported link types #[derive(Copy, Clone)] pub enum MyLinkType { - Supported(Linktype), + Null(Linktype), + Ethernet(Linktype), + RawIp(Linktype), + Loop(Linktype), + IPv4(Linktype), + IPv6(Linktype), Unsupported(Linktype), NotYetAssigned, } impl MyLinkType { - pub fn is_supported(&self) -> bool { - match self { - MyLinkType::Supported(_) => true, - MyLinkType::Unsupported(_) | MyLinkType::NotYetAssigned => false, - } + pub fn is_supported(self) -> bool { + !matches!( + self, + MyLinkType::Unsupported(_) | MyLinkType::NotYetAssigned + ) } pub fn from_pcap_link_type(link_type: Linktype) -> Self { match link_type { - Linktype::NULL - | Linktype::ETHERNET - | Linktype(12) - | Linktype::LOOP - | Linktype::IPV4 - | Linktype::IPV6 => Self::Supported(link_type), + Linktype::NULL => Self::Null(link_type), + Linktype::ETHERNET => Self::Ethernet(link_type), + Linktype(12) => Self::RawIp(link_type), + Linktype::LOOP => Self::Loop(link_type), + Linktype::IPV4 => Self::IPv4(link_type), + Linktype::IPV6 => Self::IPv6(link_type), _ => Self::Unsupported(link_type), } } - pub fn full_print_on_one_line(&self, language: Language) -> String { + pub fn full_print_on_one_line(self, language: Language) -> String { match self { - MyLinkType::Supported(l) => { + Self::Null(l) + | Self::Ethernet(l) + | Self::RawIp(l) + | Self::Loop(l) + | Self::IPv4(l) + | Self::IPv6(l) => { format!( "{}: {} ({})", link_type_translation(language), @@ -55,12 +66,17 @@ impl MyLinkType { } pub fn link_type_col( - &self, + self, language: Language, font: Font, ) -> Column<'static, Message, Renderer> { match self { - MyLinkType::Supported(l) => { + Self::Null(l) + | Self::Ethernet(l) + | Self::RawIp(l) + | Self::Loop(l) + | Self::IPv4(l) + | Self::IPv6(l) => { let link_info = format!( "{} ({})", l.get_name().unwrap_or(l.0.to_string()), diff --git a/src/secondary_threads/parse_packets.rs b/src/secondary_threads/parse_packets.rs index 2afd3cda..e75ae433 100644 --- a/src/secondary_threads/parse_packets.rs +++ b/src/secondary_threads/parse_packets.rs @@ -6,7 +6,7 @@ use std::sync::{Arc, Mutex}; use std::thread; use etherparse::{PacketHeaders, ReadError}; -use pcap::{Active, Capture, Linktype, Packet}; +use pcap::{Active, Capture, Packet}; use crate::mmdb::types::mmdb_reader::MmdbReader; use crate::networking::manage_packets::{ @@ -35,8 +35,7 @@ pub fn parse_packets( ) { let capture_id = *current_capture_id.lock().unwrap(); - let link_type = cap.get_datalink(); - info_traffic_mutex.lock().unwrap().link_type = MyLinkType::from_pcap_link_type(link_type); + let my_link_type = MyLinkType::from_pcap_link_type(cap.get_datalink()); loop { match cap.next_packet() { @@ -50,7 +49,7 @@ pub fn parse_packets( if *current_capture_id.lock().unwrap() != capture_id { return; } - if let Ok(headers) = get_sniffable_headers(&packet, link_type) { + if let Ok(headers) = get_sniffable_headers(&packet, my_link_type) { let mut exchanged_bytes = 0; let mut mac_addresses = (None, None); let mut icmp_type = IcmpType::default(); @@ -195,11 +194,13 @@ pub fn parse_packets( fn get_sniffable_headers<'a>( packet: &'a Packet, - link_type: Linktype, + my_link_type: MyLinkType, ) -> Result, ReadError> { - match link_type { - Linktype(12) | Linktype::IPV4 | Linktype::IPV6 => PacketHeaders::from_ip_slice(packet), - Linktype::NULL | Linktype::LOOP => from_null_slice(packet), + match my_link_type { + MyLinkType::RawIp(_) | MyLinkType::IPv4(_) | MyLinkType::IPv6(_) => { + PacketHeaders::from_ip_slice(packet) + } + MyLinkType::Null(_) | MyLinkType::Loop(_) => from_null_slice(packet), _ => PacketHeaders::from_ethernet_slice(packet), } } From 61456f1e5e7c4f824d5a9dcd2512edb47161f642 Mon Sep 17 00:00:00 2001 From: Giuliano Bellini s294739 Date: Mon, 1 Jan 2024 11:14:09 +0100 Subject: [PATCH 12/16] print informative warning when a device with unsupported link type is chosen --- src/gui/pages/overview_page.rs | 41 ++++++++------- src/networking/types/my_link_type.rs | 33 +++---------- src/translations/translations.rs | 74 ++++++++++++++-------------- src/translations/translations_3.rs | 20 +++++++- 4 files changed, 84 insertions(+), 84 deletions(-) diff --git a/src/gui/pages/overview_page.rs b/src/gui/pages/overview_page.rs index 574212ea..d87ffe55 100644 --- a/src/gui/pages/overview_page.rs +++ b/src/gui/pages/overview_page.rs @@ -42,6 +42,7 @@ use crate::translations::translations_2::{ data_representation_translation, dropped_packets_translation, host_translation, only_top_30_hosts_translation, }; +use crate::translations::translations_3::unsupported_link_type_translation; use crate::utils::formatted_strings::{ get_active_filters_string, get_formatted_bytes_string_with_b, get_percentage_string, }; @@ -144,19 +145,26 @@ fn body_no_packets( waiting: &str, link_type: MyLinkType, ) -> Column<'static, Message, Renderer> { - let mut adapter_name = device.name.clone(); - adapter_name.push_str(&format!("\n{}", link_type.full_print_on_one_line(language))); - let (icon_text, nothing_to_see_text) = if device.addresses.lock().unwrap().is_empty() { + let mut adapter_info = device.name.clone(); + adapter_info.push_str(&format!("\n{}", link_type.full_print_on_one_line(language))); + let (icon_text, nothing_to_see_text) = if !link_type.is_supported() { ( Icon::Warning.to_text().size(60), - no_addresses_translation(language, &adapter_name) + unsupported_link_type_translation(language, &adapter_info) + .horizontal_alignment(Horizontal::Center) + .font(font), + ) + } else if device.addresses.lock().unwrap().is_empty() { + ( + Icon::Warning.to_text().size(60), + no_addresses_translation(language, &adapter_info) .horizontal_alignment(Horizontal::Center) .font(font), ) } else { ( Icon::get_hourglass(waiting.len()).size(60), - waiting_translation(language, &adapter_name) + waiting_translation(language, &adapter_info) .horizontal_alignment(Horizontal::Center) .font(font), ) @@ -424,9 +432,6 @@ fn lazy_col_info( style, language, .. } = sniffer.configs.lock().unwrap().settings; let font = style.get_extension().font; - let filtered_bytes = - sniffer.runtime_data.tot_sent_bytes + sniffer.runtime_data.tot_received_bytes; - let all_bytes = sniffer.runtime_data.all_bytes; let link_type = sniffer.runtime_data.link_type; let col_device = col_device(language, font, &sniffer.device, link_type); @@ -434,16 +439,7 @@ fn lazy_col_info( let col_data_representation = col_data_representation(language, font, sniffer.traffic_chart.chart_type); - let col_bytes_packets = col_bytes_packets( - language, - dropped, - total, - filtered, - all_bytes, - filtered_bytes, - font, - &sniffer.filters, - ); + let col_bytes_packets = col_bytes_packets(language, dropped, total, filtered, font, sniffer); let content = Column::new() .align_items(Alignment::Center) @@ -574,11 +570,14 @@ fn col_bytes_packets( dropped: u32, total: u128, filtered: u128, - all_bytes: u128, - filtered_bytes: u128, font: Font, - filters: &Filters, + sniffer: &Sniffer, ) -> Column<'static, Message, Renderer> { + let filtered_bytes = + sniffer.runtime_data.tot_sent_bytes + sniffer.runtime_data.tot_received_bytes; + let all_bytes = sniffer.runtime_data.all_bytes; + let filters = &sniffer.filters; + let dropped_val = if dropped > 0 { format!( "{} {}", diff --git a/src/networking/types/my_link_type.rs b/src/networking/types/my_link_type.rs index 44367a39..9e1e667c 100644 --- a/src/networking/types/my_link_type.rs +++ b/src/networking/types/my_link_type.rs @@ -21,10 +21,7 @@ pub enum MyLinkType { impl MyLinkType { pub fn is_supported(self) -> bool { - !matches!( - self, - MyLinkType::Unsupported(_) | MyLinkType::NotYetAssigned - ) + !matches!(self, Self::Unsupported(_) | Self::NotYetAssigned) } pub fn from_pcap_link_type(link_type: Linktype) -> Self { @@ -46,7 +43,8 @@ impl MyLinkType { | Self::RawIp(l) | Self::Loop(l) | Self::IPv4(l) - | Self::IPv6(l) => { + | Self::IPv6(l) + | Self::Unsupported(l) => { format!( "{}: {} ({})", link_type_translation(language), @@ -54,14 +52,7 @@ impl MyLinkType { l.get_description().unwrap_or(String::new()) ) } - MyLinkType::Unsupported(l) => { - format!( - "{}: {} (NOT SUPPORTED)", - link_type_translation(language), - l.get_name().unwrap_or(l.0.to_string()), - ) - } - MyLinkType::NotYetAssigned => String::new(), + Self::NotYetAssigned => String::new(), } } @@ -76,7 +67,8 @@ impl MyLinkType { | Self::RawIp(l) | Self::Loop(l) | Self::IPv4(l) - | Self::IPv6(l) => { + | Self::IPv6(l) + | Self::Unsupported(l) => { let link_info = format!( "{} ({})", l.get_name().unwrap_or(l.0.to_string()), @@ -88,18 +80,7 @@ impl MyLinkType { font, ) } - MyLinkType::Unsupported(l) => { - let link_info = format!( - "{} (NOT SUPPORTED)", - l.get_name().unwrap_or(l.0.to_string()), - ); - TextType::highlighted_subtitle_with_desc( - link_type_translation(language), - &link_info, - font, - ) - } - MyLinkType::NotYetAssigned => Column::new().height(0), + Self::NotYetAssigned => Column::new().height(0), } } } diff --git a/src/translations/translations.rs b/src/translations/translations.rs index 31d0a3ba..361047d2 100644 --- a/src/translations/translations.rs +++ b/src/translations/translations.rs @@ -451,63 +451,64 @@ pub fn no_addresses_translation( language: Language, adapter: &str, ) -> Text<'static, Renderer> { + let network_adapter_translation = network_adapter_translation(language); Text::new(match language { Language::EN => format!("No traffic can be observed because the adapter you selected has no active addresses...\n\n\ - Network adapter: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ If you are sure you are connected to the internet, try choosing a different adapter."), Language::IT => format!("Non è osservabile alcun traffico perché l'adattatore di rete selezionato non ha indirizzi attivi...\n\n\ - Adattatore di rete: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ Se sei sicuro di essere connesso ad internet, prova a scegliere un adattatore diverso."), Language::FR => format!("Aucun trafic ne peut être observé, car la carte réseau que vous avez saisie n'a pas d'adresse...\n\n\ - Carte réseau : {adapter}\n\n\ + {network_adapter_translation} : {adapter}\n\n\ Si vous êtes sûr d'être connecté à internet, essayez une autre carte."), Language::ES => format!("No se puede observar ningún tráfico porque el adaptador seleccionado no tiene direcciones activas...\n\n\ - Adaptador de red : {adapter}\n\n\ + {network_adapter_translation} : {adapter}\n\n\ Si estás seguro de que estás conectado a Internet, prueba a elegir otro adaptador."), Language::PL => format!("Nie można zaobserwować żadnego ruchu, ponieważ wybrany adapter nie ma aktywnych adresów...\n\n\ - Adapter sieciowy: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ Jeśli jesteś pewien, że jesteś podłączony do internetu, spróbuj wybrać inny adapter."), Language::DE => format!("Es kann kein Netzwerkverkehr beobachtet werden, weil der Adapter keine aktiven Adressen hat...\n\n\ - Netzwerkadapter: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ Wenn du dir sicher bist, dass du mit dem Internet verbunden bist, probier einen anderen Adapter auszuwählen."), Language::UK => format!("Не зафіксовано жодного мережевого трафіку тому що вибраний адаптер немає активних адрес... \n\n\ - Мережквий адаптер: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ Якщо Ти впевнений, що підключений до інтернету, спробуй вибрати інший адаптер."), Language::ZH => format!("您选择的网络适配器当前无活动网络...\n\n\ - 网络适配器: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ 如果您确信您已成功连接互联网, 请尝试选择其他网络适配器."), Language::RO => format!("Niciun trafic nu poate fi observat deoarece adaptorul selectat nu are adrese active...\n\n\ - Adaptor de rețea: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ Dacă sunteți sigur că sunteți conectat la internet, încercați să alegeți un alt adaptor."), Language::KO => format!("선택한 어댑터에 유효한 주소가 없기 때문에 트래픽을 확인할 수 없습니다...\n\n\ - 네트워크 어뎁터: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ 인터넷이 연결되어있다면 다른 어댑터로 시도해보세요."), Language::TR => format!("Seçtiğiniz adaptör aktif bir adrese sahip olmadığı için hiç bir trafik izlenemez...\n\n\ - Ağ adaptörü: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ Eğer gerçekten internete bağlı olduğunuza eminseniz, başka bir adaptör seçmeyi deneyiniz."), Language::RU => format!("Наблюдение за трафиком не возможно, потому что Вы выбрали интерфейс без активного адреса...\n\n\ - Сетевой интерфейс: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ Если Вы уверены, что подключены к Интернету, попробуйте выбрать другой интерфейс."), Language::PT => format!("Não é possível observar tráfego porque o adaptador que selecionou não tem endereços ativos...\n\n\ - Adaptador de rede: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ Se tiver a certeza que está ligado à internet, tente escolher um adaptador diferente."), Language::EL => format!("Δεν μπορεί να ανιχνευθεί κίνηση επειδή ο προσαρμογέας που επέλεξες δεν έχει ενεργές διευθύνσεις...\n\n\ - Προσαρμογέας δικτύου: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ Αν είσαι σίγουρος ότι είσαι συνδεδεμένος στο διαδίκτυο, δοκίμασε αν επιλέξεις έναν διαφορετικό προσαρμογέα."), // Language::FA => format!("هیچ آمد و شدی قابل مشاهده نیست چون مبدلی که انتخاب کرده اید هیچ نشانی فعالی ندارد...\n\n\ // مبدل شبکه: {adapter}\n\n\ // اگر مطمئن هستید به اینترنت وصل هستید، سعی کنید مبدل متفاوتی را انتخاب کنید."), Language::SV => format!("Det går inte att observa någon trafik eftersom den valda adaptern inte har några aktiva adresser ...\n\n\ - Nätverksadapter: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ Om du är säker att du är ansluten till internet, testa att välja en annan adapter."), Language::FI => format!("Liikennettä ei voitu havainnoida, koska valitulla sovittimella ei ole aktiivista osoitetta...\n\n\ - Verkkosovitin: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ Jos olet varma että sinulla on internet-yhteys, kokeile valita toinen verkkosovitin."), Language::JA => format!("選択されたアダプターが有効なアドレスを持っていないため、トラフィックを観測できていません...\n\n\ - ネットワーク アダプター: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ インターネットに接続しているか確認し、別のネットワーク アダプターを試してください。"), Language::UZ => format!("Trafik kuzatilmaydi, chunki siz tanlagan adapterda faol manzillar yo'q...\n\n\ - Tarmoq adapteri: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ Internetga ulanganingizga ishonchingiz komil bo'lsa, boshqa adapterni tanlashga harakat qiling"), }) } @@ -516,64 +517,65 @@ pub fn waiting_translation( language: Language, adapter: &str, ) -> Text<'static, Renderer> { + let network_adapter_translation = network_adapter_translation(language); Text::new(match language { Language::EN => format!("No traffic has been observed yet. Waiting for network packets...\n\n\ - Network adapter: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ Are you sure you are connected to the internet and you have selected the correct adapter?"), Language::IT => format!("Nessun tipo di traffico è stato osservato finora. Attendo pacchetti di rete...\n\n\ - Adattatore di rete: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ Sei sicuro di esser connesso ad internet e di aver selezionato l'adattatore corretto?"), Language::FR => format!("Aucun trafic n'a été capturé pour le moment. En attente de paquets...\n\n\ - Carte réseau : {adapter}\n\n\ + {network_adapter_translation} : {adapter}\n\n\ Êtes-vous sûr d'être connecté à internet et d'avoir selectionné la bonne carte réseau ?"), Language::ES => format!("Aún no se ha captado tráfico. Esperando paquetes...\n\n\ - Adaptador de red : {adapter}\n\n\ + {network_adapter_translation} : {adapter}\n\n\ ¿Está seguro de que está conectado a Internet y ha seleccionado la tarjeta de red correcta?"), Language::PL => format!("Nie zaobserowano żadnego ruchu sieciowego. Oczekiwanie na pakiety...\n\n\ - Adapter sieciowy: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ Czy na pewno jesteś podłączony do internetu i wybrałeś właściwy adapter?"), Language::DE => format!("Noch kein Netzwerkverkehr beobachtet. Warte auf Pakete...\n\n\ - Netzwerkadapter: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ Bist du sicher, dass du mit dem Internet verbunden bist und den richtigen Adapter ausgewählt hast?"), Language::UK => format!("Не зафіксовано жодного мережевого трафіку. Очікування на пакети...\n\n\ - Мережквий адаптер: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ Чи Ти дійсно підключений до інтернету і вибрав відповідний мережевий адаптер?"), Language::ZH => format!("暂无流量数据. 等待网络活动中......\n\n\ - 网络适配器: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ 您确信您已成功连接到互联网, 并选择了当前正在使用的的网络适配器吗?"), Language::RO => format!("Nu a fost observat încă trafic. Se așteaptă pachetele de rețea...\n\n\ - Adaptor de rețea: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ Ești sigur că ești conectat la internet și ai selectat adaptorul corect?"), Language::KO => format!("아직 트래픽이 관찰되지 않았습니다. 네트워크 패킷 대기 중...\n\n\ - 네트워크 어뎁터: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ 인터넷에 연결되어 있고 올바른 어댑터를 선택하셨습니까?"), Language::TR => format!("Henüz bir trafik algılanamadı. Ağ paketleri için bekleniyor...\n\n\ - Ağ adaptörü: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ İnternete bağlı olduğunuza ve doğru adaptörü seçtiğinize emin misiniz?"), Language::RU => format!("Трафик не обнаружен. Ожидаем сетевые пакеты...\n\n\ - Сетевой интерфейс: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ Вы уверены, что подключены к Интернету и выбрали правильный интерфейс?"), Language::PT => format!("Ainda não foi observado tráfego. Aguardando por pacotes...\n\n\ - Adaptador de rede: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ Tem a certeza de que está ligado à internet e selecionou o adaptador correto?"), Language::EL => format!("Δεν έχει παρατηρηθεί κίνηση μέχρι στιγμής. Ανέμενε για πακέτα δικτύου...\n\n\ - Προσαρμογέας δικτύου: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ Είσαι σίγουρος ότι είσαι συνδεδεμένος στο διαδίκτυο και ότι έχεις επιλέξει τον σωστό προσαρμογέα;"), // Language::FA => format!("هنوز هیچ آمد و شدی مشاهده نشده است. در حال انتظار برای بسته های شبکه...\n\n // مبدل شبکه: {adapter}\n\n // آیا مطمئن هستید به اینترنت وصل هستید و مبدل درست را انتخاب کرده اید؟"), Language::SV => format!("Ingen trafik har observerats ännu. Väntar på paket ...\n\n\ - Nätverksadapter: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ Är du säker på att du är ansluten till internet och att du har valt rätt adapter?"), Language::FI => format!("Ei vielä havaittua liikennettä. Odotetaan verkkopaketteja...\n\n\ - Verkkosovitin: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ Onhan sinulla varmasti internet-yhteys ja olet valinnut oikean verkkosovittimen."), Language::JA => format!("トラフィックがまだ観測できていません。ネットワーク パケットを待っています...\n\n\ - ネットワーク アダプター: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ インターネットに接続していて、正しいアダプターを選択していますか?"), Language::UZ => format!( "Hali hech qanday trafik aniqlanmadi. Tarmoq paketlari kutilmoqda...\n\n\ - Tarmoq adapteri: {adapter}\n\n\ + {network_adapter_translation}: {adapter}\n\n\ Internetga ulanganingizga va to'g'ri adapterni tanlaganingizga ishonchingiz komilmi?"), }) } diff --git a/src/translations/translations_3.rs b/src/translations/translations_3.rs index 76d8d3bd..0c726cdd 100644 --- a/src/translations/translations_3.rs +++ b/src/translations/translations_3.rs @@ -1,6 +1,9 @@ #![allow(clippy::match_same_arms)] -use crate::Language; +use crate::translations::translations::network_adapter_translation; +use crate::{Language, StyleType}; +use iced::widget::Text; +use iced::Renderer; // This is referred to settings (General settings) pub fn general_translation(language: Language) -> &'static str { @@ -89,3 +92,18 @@ pub fn link_type_translation(language: Language) -> &'static str { _ => "Link type", } } + +pub fn unsupported_link_type_translation( + language: Language, + adapter: &str, +) -> Text<'static, Renderer> { + let mut string = match language { + Language::EN => "The link type associated to this adapter is not supported by Sniffnet yet...", + Language::IT => "Il tipo di collegamento associato a questo adattatore di rete non è ancora supportato da Sniffnet...", + _ => "The link type associated to this adapter is not supported by Sniffnet yet...", + }.to_string(); + + let network_adapter_translation = network_adapter_translation(language); + string.push_str(&format!("\n\n{network_adapter_translation}: {adapter}")); + Text::new(string) +} From 28e21e9d73824acacb06c457db1cfa5897758a7e Mon Sep 17 00:00:00 2001 From: Giuliano Bellini s294739 Date: Mon, 1 Jan 2024 15:32:25 +0100 Subject: [PATCH 13/16] fixed loopback traffic handling --- src/countries/country_utils.rs | 47 +++++++++++++------- src/gui/pages/connection_details_page.rs | 28 +++++------- src/gui/pages/notifications_page.rs | 8 ++-- src/gui/pages/overview_page.rs | 3 +- src/networking/manage_packets.rs | 55 +++++++++++++++++++----- src/networking/types/data_info_host.rs | 2 + src/report/get_report_entries.rs | 3 +- 7 files changed, 94 insertions(+), 52 deletions(-) diff --git a/src/countries/country_utils.rs b/src/countries/country_utils.rs index 87e359f6..49e8990c 100644 --- a/src/countries/country_utils.rs +++ b/src/countries/country_utils.rs @@ -21,6 +21,7 @@ use crate::countries::types::country::Country; use crate::gui::styles::container::ContainerType; use crate::gui::styles::svg::SvgType; use crate::gui::types::message::Message; +use crate::networking::types::data_info_host::DataInfoHost; use crate::networking::types::traffic_type::TrafficType; use crate::translations::translations_2::{ local_translation, unknown_translation, your_network_adapter_translation, @@ -31,6 +32,7 @@ fn get_flag_from_country( country: Country, width: f32, is_local: bool, + is_loopback: bool, traffic_type: TrafficType, language: Language, ) -> (Svg>, String) { @@ -284,7 +286,11 @@ fn get_flag_from_country( Country::ZM => ZM, Country::ZW => ZW, Country::ZZ => { - if is_local { + if is_loopback { + tooltip = your_network_adapter_translation(language); + svg_style = SvgType::AdaptColor; + COMPUTER + } else if is_local { tooltip = local_translation(language); svg_style = SvgType::AdaptColor; HOME @@ -313,13 +319,21 @@ fn get_flag_from_country( pub fn get_flag_tooltip( country: Country, width: f32, - is_local: bool, - traffic_type: TrafficType, + host_info: &DataInfoHost, language: Language, font: Font, ) -> Tooltip<'static, Message, Renderer> { - let (content, tooltip) = - get_flag_from_country(country, width, is_local, traffic_type, language); + let is_local = host_info.is_local; + let is_loopback = host_info.is_loopback; + let traffic_type = host_info.traffic_type; + let (content, tooltip) = get_flag_from_country( + country, + width, + is_local, + is_loopback, + traffic_type, + language, + ); let mut tooltip = Tooltip::new(content, tooltip, Position::FollowCursor) .font(font) @@ -335,27 +349,30 @@ pub fn get_flag_tooltip( pub fn get_computer_tooltip( is_my_address: bool, + is_local: bool, traffic_type: TrafficType, language: Language, font: Font, ) -> Tooltip<'static, Message, Renderer> { let content = Svg::new(Handle::from_memory(Vec::from( - match (is_my_address, traffic_type) { - (true, _) => COMPUTER, - (false, TrafficType::Multicast) => MULTICAST, - (false, TrafficType::Broadcast) => BROADCAST, - (false, TrafficType::Unicast) => UNKNOWN, + match (is_my_address, is_local, traffic_type) { + (true, _, _) => COMPUTER, + (false, true, _) => HOME, + (false, false, TrafficType::Multicast) => MULTICAST, + (false, false, TrafficType::Broadcast) => BROADCAST, + (false, false, TrafficType::Unicast) => UNKNOWN, }, ))) .style(SvgType::AdaptColor) .width(Length::Fixed(FLAGS_WIDTH_BIG)) .height(Length::Fixed(FLAGS_WIDTH_BIG * 0.75)); - let tooltip = match (is_my_address, traffic_type) { - (true, _) => your_network_adapter_translation(language), - (false, TrafficType::Multicast) => "Multicast".to_string(), - (false, TrafficType::Broadcast) => "Broadcast".to_string(), - (false, TrafficType::Unicast) => unknown_translation(language), + let tooltip = match (is_my_address, is_local, traffic_type) { + (true, _, _) => your_network_adapter_translation(language), + (false, true, _) => local_translation(language), + (false, false, TrafficType::Multicast) => "Multicast".to_string(), + (false, false, TrafficType::Broadcast) => "Broadcast".to_string(), + (false, false, TrafficType::Unicast) => unknown_translation(language), }; Tooltip::new(content, tooltip, Position::FollowCursor) diff --git a/src/gui/pages/connection_details_page.rs b/src/gui/pages/connection_details_page.rs index a3f4caf6..0d9d9e7e 100644 --- a/src/gui/pages/connection_details_page.rs +++ b/src/gui/pages/connection_details_page.rs @@ -18,7 +18,9 @@ use crate::gui::styles::text::TextType; use crate::gui::styles::types::gradient_type::GradientType; use crate::gui::types::message::Message; use crate::gui::types::timing_events::TimingEvents; -use crate::networking::manage_packets::{get_address_to_lookup, get_traffic_type, is_my_address}; +use crate::networking::manage_packets::{ + get_address_to_lookup, get_traffic_type, is_local_connection, is_my_address, +}; use crate::networking::types::address_port_pair::AddressPortPair; use crate::networking::types::host::Host; use crate::networking::types::icmp_type::IcmpType; @@ -105,14 +107,7 @@ fn page_content( if let Some((r_dns, host)) = host_option { host_info_col = get_host_info_col(&r_dns, &host, font, language); let host_info = host_info_option.unwrap_or_default(); - let flag = get_flag_tooltip( - host.country, - FLAGS_WIDTH_BIG, - host_info.is_local, - host_info.traffic_type, - language, - font, - ); + let flag = get_flag_tooltip(host.country, FLAGS_WIDTH_BIG, &host_info, language, font); let computer = get_local_tooltip(sniffer, &address_to_lookup, key); if address_to_lookup.eq(&key.address1) { source_caption = source_caption.push(flag); @@ -310,16 +305,15 @@ fn get_local_tooltip( style, language, .. } = sniffer.configs.lock().unwrap().settings; + let local_address = if address_to_lookup.eq(&key.address1) { + &key.address2 + } else { + &key.address1 + }; let my_interface_addresses = &*sniffer.device.addresses.lock().unwrap(); get_computer_tooltip( - is_my_address( - if address_to_lookup.eq(&key.address1) { - &key.address2 - } else { - &key.address1 - }, - my_interface_addresses, - ), + is_my_address(local_address, my_interface_addresses), + is_local_connection(local_address, my_interface_addresses), get_traffic_type( if address_to_lookup.eq(&key.address1) { &key.address2 diff --git a/src/gui/pages/notifications_page.rs b/src/gui/pages/notifications_page.rs index 0a6ec414..41340237 100644 --- a/src/gui/pages/notifications_page.rs +++ b/src/gui/pages/notifications_page.rs @@ -312,11 +312,10 @@ fn favorite_notification_log( language: Language, font: Font, ) -> Container<'static, Message, Renderer> { - let domain = logged_notification.host.domain; let country = logged_notification.host.country; - let asn = logged_notification.host.asn; + let asn = &logged_notification.host.asn; - let mut domain_asn_str = domain; + let mut domain_asn_str = logged_notification.host.domain.clone(); if !asn.name.is_empty() { domain_asn_str.push_str(&format!(" - {}", asn.name)); } @@ -327,8 +326,7 @@ fn favorite_notification_log( .push(get_flag_tooltip( country, FLAGS_WIDTH_BIG, - logged_notification.data_info_host.is_local, - logged_notification.data_info_host.traffic_type, + &logged_notification.data_info_host, language, font, )) diff --git a/src/gui/pages/overview_page.rs b/src/gui/pages/overview_page.rs index d87ffe55..3471aef8 100644 --- a/src/gui/pages/overview_page.rs +++ b/src/gui/pages/overview_page.rs @@ -308,8 +308,7 @@ fn col_host(width: f32, sniffer: &Sniffer) -> Column<'static, Message, Renderer< .push(get_flag_tooltip( host.country, FLAGS_WIDTH_BIG, - data_info_host.is_local, - data_info_host.traffic_type, + data_info_host, language, font, )) diff --git a/src/networking/manage_packets.rs b/src/networking/manage_packets.rs index 8672c7dc..2aa95846 100644 --- a/src/networking/manage_packets.rs +++ b/src/networking/manage_packets.rs @@ -1,5 +1,6 @@ use std::collections::HashMap; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; +use std::str::FromStr; use std::sync::{Arc, Mutex}; use chrono::Local; @@ -189,8 +190,13 @@ pub fn modify_or_insert_in_map( // determine traffic direction let source_ip = &key.address1; let destination_ip = &key.address2; - traffic_direction = - get_traffic_direction(source_ip, destination_ip, &my_interface_addresses); + traffic_direction = get_traffic_direction( + source_ip, + destination_ip, + key.port1, + key.port2, + &my_interface_addresses, + ); }; let mut info_traffic = info_traffic_mutex @@ -261,6 +267,7 @@ pub fn reverse_dns_lookup( &my_interface_addresses, traffic_direction, ); + let is_loopback = is_loopback(&address_to_lookup); let is_local = is_local_connection(&address_to_lookup, &my_interface_addresses); let country = get_country(&address_to_lookup, country_db_reader); let asn = get_asn(&address_to_lookup, asn_db_reader); @@ -298,6 +305,7 @@ pub fn reverse_dns_lookup( .or_insert(DataInfoHost { data_info: other_data, is_favorite: false, + is_loopback, is_local, traffic_type, }); @@ -313,6 +321,8 @@ pub fn reverse_dns_lookup( fn get_traffic_direction( source_ip: &String, destination_ip: &String, + source_port: Option, + dest_port: Option, my_interface_addresses: &[Address], ) -> TrafficDirection { let my_interface_addresses_string: Vec = my_interface_addresses @@ -320,6 +330,17 @@ fn get_traffic_direction( .map(|address| address.addr.to_string()) .collect(); + // first let's handle TCP and UDP loopback + if is_loopback(source_ip) && is_loopback(destination_ip) { + if let (Some(sport), Some(dport)) = (source_port, dest_port) { + return if sport > dport { + TrafficDirection::Outgoing + } else { + TrafficDirection::Incoming + }; + } + } + if my_interface_addresses_string.contains(source_ip) { // source is local TrafficDirection::Outgoing @@ -407,8 +428,14 @@ fn is_broadcast_address(address: &str, my_interface_addresses: &[Address]) -> bo false } +fn is_loopback(address_to_lookup: &str) -> bool { + IpAddr::from_str(address_to_lookup) + .unwrap_or(IpAddr::V4(Ipv4Addr::UNSPECIFIED)) + .is_loopback() +} + /// Determines if the connection is local -fn is_local_connection(address_to_lookup: &str, my_interface_addresses: &Vec
) -> bool { +pub fn is_local_connection(address_to_lookup: &str, my_interface_addresses: &Vec
) -> bool { let mut ret_val = false; let address_to_lookup_type = if address_to_lookup.contains(':') { @@ -475,17 +502,13 @@ fn is_local_connection(address_to_lookup: &str, my_interface_addresses: &Vec) -> bool { - let mut ret_val = false; - +pub fn is_my_address(local_address: &String, my_interface_addresses: &Vec
) -> bool { for address in my_interface_addresses { - if address.addr.to_string().eq(address_to_lookup) { - ret_val = true; - break; + if address.addr.to_string().eq(local_address) { + return true; } } - - ret_val + is_loopback(local_address) } /// Determines if the capture opening resolves into an Error @@ -659,30 +682,40 @@ mod tests { let result1 = get_traffic_direction( &"172.20.10.9".to_string(), &"99.88.77.00".to_string(), + Some(99), + Some(99), &address_vec, ); assert_eq!(result1, TrafficDirection::Outgoing); let result2 = get_traffic_direction( &"172.20.10.10".to_string(), &"172.20.10.9".to_string(), + Some(99), + Some(99), &address_vec, ); assert_eq!(result2, TrafficDirection::Incoming); let result3 = get_traffic_direction( &"172.20.10.9".to_string(), &"0.0.0.0".to_string(), + Some(99), + Some(99), &address_vec, ); assert_eq!(result3, TrafficDirection::Outgoing); let result4 = get_traffic_direction( &"0.0.0.0".to_string(), &"172.20.10.9".to_string(), + Some(99), + Some(99), &address_vec, ); assert_eq!(result4, TrafficDirection::Incoming); let result4 = get_traffic_direction( &"0.0.0.0".to_string(), &"172.20.10.10".to_string(), + Some(99), + Some(99), &address_vec, ); assert_eq!(result4, TrafficDirection::Outgoing); diff --git a/src/networking/types/data_info_host.rs b/src/networking/types/data_info_host.rs index b129978f..68b54d04 100644 --- a/src/networking/types/data_info_host.rs +++ b/src/networking/types/data_info_host.rs @@ -10,6 +10,8 @@ pub struct DataInfoHost { pub data_info: DataInfo, /// Determine if this host is one of the favorites pub is_favorite: bool, + /// Determine if the connection is loopback (the "remote" is loopback) + pub is_loopback: bool, /// Determine if the connection with this host is local pub is_local: bool, /// Determine if the connection with this host is unicast, multicast, or broadcast diff --git a/src/report/get_report_entries.rs b/src/report/get_report_entries.rs index aa0f2480..0010df1a 100644 --- a/src/report/get_report_entries.rs +++ b/src/report/get_report_entries.rs @@ -120,8 +120,7 @@ pub fn get_searched_entries(sniffer: &Sniffer) -> (Vec, usize) { let flag = get_flag_tooltip( host.country, FLAGS_WIDTH_SMALL, - host_info.is_local, - host_info.traffic_type, + host_info, language, style.get_extension().font, ); From 6eb68c33f681d8811baeac5c329b39946e696e3b Mon Sep 17 00:00:00 2001 From: Giuliano Bellini s294739 Date: Mon, 1 Jan 2024 17:13:43 +0100 Subject: [PATCH 14/16] minor fixes --- src/gui/pages/notifications_page.rs | 2 +- src/secondary_threads/parse_packets.rs | 255 +++++++++++++------------ src/translations/translations_3.rs | 4 +- 3 files changed, 134 insertions(+), 127 deletions(-) diff --git a/src/gui/pages/notifications_page.rs b/src/gui/pages/notifications_page.rs index 41340237..74a5963e 100644 --- a/src/gui/pages/notifications_page.rs +++ b/src/gui/pages/notifications_page.rs @@ -315,7 +315,7 @@ fn favorite_notification_log( let country = logged_notification.host.country; let asn = &logged_notification.host.asn; - let mut domain_asn_str = logged_notification.host.domain.clone(); + let mut domain_asn_str = logged_notification.host.domain; if !asn.name.is_empty() { domain_asn_str.push_str(&format!(" - {}", asn.name)); } diff --git a/src/secondary_threads/parse_packets.rs b/src/secondary_threads/parse_packets.rs index e75ae433..dfdf1d26 100644 --- a/src/secondary_threads/parse_packets.rs +++ b/src/secondary_threads/parse_packets.rs @@ -50,141 +50,145 @@ pub fn parse_packets( return; } if let Ok(headers) = get_sniffable_headers(&packet, my_link_type) { - let mut exchanged_bytes = 0; - let mut mac_addresses = (None, None); - let mut icmp_type = IcmpType::default(); - let mut packet_filters_fields = PacketFiltersFields::default(); - - let key_option = analyze_headers( - headers, - &mut mac_addresses, - &mut exchanged_bytes, - &mut icmp_type, - &mut packet_filters_fields, - ); - if key_option.is_none() { - continue; - } - - let key = key_option.unwrap(); - let application_protocol = get_app_protocol(key.port1, key.port2); - let mut new_info = InfoAddressPortPair::default(); - - let passed_filters = filters.matches(&packet_filters_fields); - if passed_filters { - new_info = modify_or_insert_in_map( - info_traffic_mutex, - &key, - device, - mac_addresses, - icmp_type, - exchanged_bytes, - application_protocol, + { + let mut exchanged_bytes = 0; + let mut mac_addresses = (None, None); + let mut icmp_type = IcmpType::default(); + let mut packet_filters_fields = PacketFiltersFields::default(); + + let key_option = analyze_headers( + headers, + &mut mac_addresses, + &mut exchanged_bytes, + &mut icmp_type, + &mut packet_filters_fields, ); - } + if key_option.is_none() { + continue; + } - let mut info_traffic = info_traffic_mutex - .lock() - .expect("Error acquiring mutex\n\r"); - //increment number of sniffed packets and bytes - info_traffic.all_packets += 1; - info_traffic.all_bytes += exchanged_bytes; - // update dropped packets number - if let Ok(stats) = cap.stats() { - info_traffic.dropped_packets = stats.dropped; - } + let key = key_option.unwrap(); + let application_protocol = get_app_protocol(key.port1, key.port2); + let mut new_info = InfoAddressPortPair::default(); + + let passed_filters = filters.matches(&packet_filters_fields); + if passed_filters { + new_info = modify_or_insert_in_map( + info_traffic_mutex, + &key, + device, + mac_addresses, + icmp_type, + exchanged_bytes, + application_protocol, + ); + } - if passed_filters { - info_traffic.add_packet(exchanged_bytes, new_info.traffic_direction); - - // check the rDNS status of this address and act accordingly - let address_to_lookup = - get_address_to_lookup(&key, new_info.traffic_direction); - let r_dns_already_resolved = info_traffic - .addresses_resolved - .contains_key(&address_to_lookup); - let mut r_dns_waiting_resolution = false; - if !r_dns_already_resolved { - r_dns_waiting_resolution = info_traffic - .addresses_waiting_resolution - .contains_key(&address_to_lookup); + let mut info_traffic = info_traffic_mutex + .lock() + .expect("Error acquiring mutex\n\r"); + //increment number of sniffed packets and bytes + info_traffic.all_packets += 1; + info_traffic.all_bytes += exchanged_bytes; + // update dropped packets number + if let Ok(stats) = cap.stats() { + info_traffic.dropped_packets = stats.dropped; } - match (r_dns_waiting_resolution, r_dns_already_resolved) { - (false, false) => { - // rDNS not requested yet (first occurrence of this address to lookup) - - // Add this address to the map of addresses waiting for a resolution - // Useful to NOT perform again a rDNS lookup for this entry - info_traffic.addresses_waiting_resolution.insert( - address_to_lookup, - DataInfo::new_with_first_packet( - exchanged_bytes, - new_info.traffic_direction, - ), - ); - - // launch new thread to resolve host name - let key2 = key.clone(); - let info_traffic2 = info_traffic_mutex.clone(); - let device2 = device.clone(); - let country_db_reader_2 = country_mmdb_reader.clone(); - let asn_db_reader_2 = asn_mmdb_reader.clone(); - thread::Builder::new() - .name("thread_reverse_dns_lookup".to_string()) - .spawn(move || { - reverse_dns_lookup( - &info_traffic2, - &key2, - new_info.traffic_direction, - &device2, - &country_db_reader_2, - &asn_db_reader_2, - ); - }) - .unwrap(); - } - (true, false) => { - // waiting for a previously requested rDNS resolution - // update the corresponding waiting address data - info_traffic + if passed_filters { + info_traffic.add_packet(exchanged_bytes, new_info.traffic_direction); + + // check the rDNS status of this address and act accordingly + let address_to_lookup = + get_address_to_lookup(&key, new_info.traffic_direction); + let r_dns_already_resolved = info_traffic + .addresses_resolved + .contains_key(&address_to_lookup); + let mut r_dns_waiting_resolution = false; + if !r_dns_already_resolved { + r_dns_waiting_resolution = info_traffic .addresses_waiting_resolution - .entry(address_to_lookup) - .and_modify(|data_info| { - data_info.add_packet( + .contains_key(&address_to_lookup); + } + + match (r_dns_waiting_resolution, r_dns_already_resolved) { + (false, false) => { + // rDNS not requested yet (first occurrence of this address to lookup) + + // Add this address to the map of addresses waiting for a resolution + // Useful to NOT perform again a rDNS lookup for this entry + info_traffic.addresses_waiting_resolution.insert( + address_to_lookup, + DataInfo::new_with_first_packet( + exchanged_bytes, + new_info.traffic_direction, + ), + ); + + // launch new thread to resolve host name + let key2 = key.clone(); + let info_traffic2 = info_traffic_mutex.clone(); + let device2 = device.clone(); + let country_db_reader_2 = country_mmdb_reader.clone(); + let asn_db_reader_2 = asn_mmdb_reader.clone(); + thread::Builder::new() + .name("thread_reverse_dns_lookup".to_string()) + .spawn(move || { + reverse_dns_lookup( + &info_traffic2, + &key2, + new_info.traffic_direction, + &device2, + &country_db_reader_2, + &asn_db_reader_2, + ); + }) + .unwrap(); + } + (true, false) => { + // waiting for a previously requested rDNS resolution + // update the corresponding waiting address data + info_traffic + .addresses_waiting_resolution + .entry(address_to_lookup) + .and_modify(|data_info| { + data_info.add_packet( + exchanged_bytes, + new_info.traffic_direction, + ); + }); + } + (_, true) => { + // rDNS already resolved + // update the corresponding host's data info + let host = info_traffic + .addresses_resolved + .get(&address_to_lookup) + .unwrap() + .1 + .clone(); + info_traffic.hosts.entry(host).and_modify(|data_info_host| { + data_info_host.data_info.add_packet( exchanged_bytes, new_info.traffic_direction, ); }); + } } - (_, true) => { - // rDNS already resolved - // update the corresponding host's data info - let host = info_traffic - .addresses_resolved - .get(&address_to_lookup) - .unwrap() - .1 - .clone(); - info_traffic.hosts.entry(host).and_modify(|data_info_host| { - data_info_host - .data_info + + //increment the packet count for the sniffed app protocol + info_traffic + .app_protocols + .entry(application_protocol) + .and_modify(|data_info| { + data_info .add_packet(exchanged_bytes, new_info.traffic_direction); - }); - } + }) + .or_insert(DataInfo::new_with_first_packet( + exchanged_bytes, + new_info.traffic_direction, + )); } - - //increment the packet count for the sniffed app protocol - info_traffic - .app_protocols - .entry(application_protocol) - .and_modify(|data_info| { - data_info.add_packet(exchanged_bytes, new_info.traffic_direction); - }) - .or_insert(DataInfo::new_with_first_packet( - exchanged_bytes, - new_info.traffic_direction, - )); } } } @@ -197,16 +201,19 @@ fn get_sniffable_headers<'a>( my_link_type: MyLinkType, ) -> Result, ReadError> { match my_link_type { + MyLinkType::Ethernet(_) => PacketHeaders::from_ethernet_slice(packet), MyLinkType::RawIp(_) | MyLinkType::IPv4(_) | MyLinkType::IPv6(_) => { PacketHeaders::from_ip_slice(packet) } MyLinkType::Null(_) | MyLinkType::Loop(_) => from_null_slice(packet), - _ => PacketHeaders::from_ethernet_slice(packet), + MyLinkType::Unsupported(_) | MyLinkType::NotYetAssigned => { + PacketHeaders::from_ethernet_slice(packet) + } } } fn from_null_slice(packet: &[u8]) -> Result { - if packet.len() < 4 { + if packet.len() <= 4 { return Err(ReadError::UnexpectedEndOfSlice(packet.len())); } diff --git a/src/translations/translations_3.rs b/src/translations/translations_3.rs index 0c726cdd..b4caa682 100644 --- a/src/translations/translations_3.rs +++ b/src/translations/translations_3.rs @@ -98,9 +98,9 @@ pub fn unsupported_link_type_translation( adapter: &str, ) -> Text<'static, Renderer> { let mut string = match language { - Language::EN => "The link type associated to this adapter is not supported by Sniffnet yet...", + Language::EN => "The link type associated with this adapter is not supported by Sniffnet yet...", Language::IT => "Il tipo di collegamento associato a questo adattatore di rete non è ancora supportato da Sniffnet...", - _ => "The link type associated to this adapter is not supported by Sniffnet yet...", + _ => "The link type associated with this adapter is not supported by Sniffnet yet...", }.to_string(); let network_adapter_translation = network_adapter_translation(language); From 6fd1b976ed16d8814c240e04be545af1a7226dbd Mon Sep 17 00:00:00 2001 From: Giuliano Bellini s294739 Date: Mon, 1 Jan 2024 17:33:22 +0100 Subject: [PATCH 15/16] moved link_type field from RunTimeData to MyDevice struct --- src/chart/manage_chart_data.rs | 2 - src/configs/types/config_device.rs | 3 + src/gui/pages/overview_page.rs | 12 +- src/gui/types/runtime_data.rs | 4 - src/gui/types/sniffer.rs | 3 +- src/networking/types/my_device.rs | 2 + src/secondary_threads/parse_packets.rs | 248 ++++++++++++------------- 7 files changed, 133 insertions(+), 141 deletions(-) diff --git a/src/chart/manage_chart_data.rs b/src/chart/manage_chart_data.rs index d8f35691..fe874efd 100644 --- a/src/chart/manage_chart_data.rs +++ b/src/chart/manage_chart_data.rs @@ -84,7 +84,6 @@ mod tests { use std::collections::VecDeque; use crate::chart::manage_chart_data::{get_max, get_min, update_charts_data}; - use crate::networking::types::my_link_type::MyLinkType; use crate::{ChartType, Language, RunTimeData, StyleType, TrafficChart}; #[test] @@ -168,7 +167,6 @@ mod tests { style: StyleType::default(), }; let mut runtime_data = RunTimeData { - link_type: MyLinkType::NotYetAssigned, all_bytes: 0, all_packets: 0, tot_sent_bytes: tot_sent + 1111, diff --git a/src/configs/types/config_device.rs b/src/configs/types/config_device.rs index 3e89852b..a01f891a 100644 --- a/src/configs/types/config_device.rs +++ b/src/configs/types/config_device.rs @@ -7,6 +7,7 @@ use pcap::{Device, DeviceFlags}; use serde::{Deserialize, Serialize}; use crate::networking::types::my_device::MyDevice; +use crate::networking::types::my_link_type::MyLinkType; #[cfg(not(test))] use crate::SNIFFNET_LOWERCASE; @@ -57,6 +58,7 @@ impl ConfigDevice { name: device.name, desc: device.desc, addresses: Arc::new(Mutex::new(device.addresses)), + link_type: MyLinkType::NotYetAssigned, }; } } @@ -70,6 +72,7 @@ impl ConfigDevice { name: standard_device.name, desc: standard_device.desc, addresses: Arc::new(Mutex::new(standard_device.addresses)), + link_type: MyLinkType::NotYetAssigned, } } } diff --git a/src/gui/pages/overview_page.rs b/src/gui/pages/overview_page.rs index 3471aef8..ae6064c9 100644 --- a/src/gui/pages/overview_page.rs +++ b/src/gui/pages/overview_page.rs @@ -28,7 +28,6 @@ use crate::networking::types::data_info::DataInfo; use crate::networking::types::filters::Filters; use crate::networking::types::host::Host; use crate::networking::types::my_device::MyDevice; -use crate::networking::types::my_link_type::MyLinkType; use crate::networking::types::search_parameters::SearchParameters; use crate::report::get_report_entries::{get_app_entries, get_host_entries}; use crate::translations::translations::{ @@ -67,13 +66,11 @@ pub fn overview_page(sniffer: &Sniffer) -> Container { //no packets observed at all - body = - body_no_packets(&sniffer.device, font, language, &sniffer.waiting, link_type); + body = body_no_packets(&sniffer.device, font, language, &sniffer.waiting); } (observed, 0) => { //no packets have been filtered but some have been observed @@ -143,8 +140,8 @@ fn body_no_packets( font: Font, language: Language, waiting: &str, - link_type: MyLinkType, ) -> Column<'static, Message, Renderer> { + let link_type = device.link_type; let mut adapter_info = device.name.clone(); adapter_info.push_str(&format!("\n{}", link_type.full_print_on_one_line(language))); let (icon_text, nothing_to_see_text) = if !link_type.is_supported() { @@ -431,9 +428,8 @@ fn lazy_col_info( style, language, .. } = sniffer.configs.lock().unwrap().settings; let font = style.get_extension().font; - let link_type = sniffer.runtime_data.link_type; - let col_device = col_device(language, font, &sniffer.device, link_type); + let col_device = col_device(language, font, &sniffer.device); let col_data_representation = col_data_representation(language, font, sniffer.traffic_chart.chart_type); @@ -513,8 +509,8 @@ fn col_device( language: Language, font: Font, device: &MyDevice, - link_type: MyLinkType, ) -> Column<'static, Message, Renderer> { + let link_type = device.link_type; #[cfg(not(target_os = "windows"))] let adapter_info = &device.name; #[cfg(target_os = "windows")] diff --git a/src/gui/types/runtime_data.rs b/src/gui/types/runtime_data.rs index 1de478db..ddd1426b 100644 --- a/src/gui/types/runtime_data.rs +++ b/src/gui/types/runtime_data.rs @@ -1,14 +1,11 @@ //! Module defining the `RunTimeData` struct, useful to to generate chart and to display statistics about network traffic -use crate::networking::types::my_link_type::MyLinkType; use std::collections::VecDeque; use crate::notifications::types::logged_notification::LoggedNotification; /// Struct containing useful data to display statistics about network traffic and the relative notifications pub struct RunTimeData { - /// Link type of the current capture (e.g., ethernet) - pub link_type: MyLinkType, /// Total number of bytes (filtered and not filtered) pub all_bytes: u128, /// Total number of packets (filtered and not filtered) @@ -41,7 +38,6 @@ impl RunTimeData { /// Constructs a new `ChartsData` element. pub fn new() -> Self { RunTimeData { - link_type: MyLinkType::NotYetAssigned, all_bytes: 0, all_packets: 0, tot_sent_bytes: 0, diff --git a/src/gui/types/sniffer.rs b/src/gui/types/sniffer.rs index 8e944377..7465108a 100644 --- a/src/gui/types/sniffer.rs +++ b/src/gui/types/sniffer.rs @@ -370,7 +370,7 @@ impl Sniffer { let filters = self.filters.clone(); let country_mmdb_reader = self.country_mmdb_reader.clone(); let asn_mmdb_reader = self.asn_mmdb_reader.clone(); - self.runtime_data.link_type = MyLinkType::from_pcap_link_type(cap.get_datalink()); + self.device.link_type = MyLinkType::from_pcap_link_type(cap.get_datalink()); thread::Builder::new() .name("thread_parse_packets".to_string()) .spawn(move || { @@ -409,6 +409,7 @@ impl Sniffer { name: dev.name, desc: dev.desc, addresses: self.device.addresses.clone(), + link_type: MyLinkType::NotYetAssigned, }; break; } diff --git a/src/networking/types/my_device.rs b/src/networking/types/my_device.rs index fad26d35..6170ec69 100644 --- a/src/networking/types/my_device.rs +++ b/src/networking/types/my_device.rs @@ -1,5 +1,6 @@ use std::sync::{Arc, Mutex}; +use crate::networking::types::my_link_type::MyLinkType; use pcap::{Address, Device, DeviceFlags}; /// Represents the current inspected device. @@ -10,6 +11,7 @@ pub struct MyDevice { pub name: String, pub desc: Option, pub addresses: Arc>>, + pub link_type: MyLinkType, } impl MyDevice { diff --git a/src/secondary_threads/parse_packets.rs b/src/secondary_threads/parse_packets.rs index dfdf1d26..338ca49e 100644 --- a/src/secondary_threads/parse_packets.rs +++ b/src/secondary_threads/parse_packets.rs @@ -50,145 +50,141 @@ pub fn parse_packets( return; } if let Ok(headers) = get_sniffable_headers(&packet, my_link_type) { - { - let mut exchanged_bytes = 0; - let mut mac_addresses = (None, None); - let mut icmp_type = IcmpType::default(); - let mut packet_filters_fields = PacketFiltersFields::default(); - - let key_option = analyze_headers( - headers, - &mut mac_addresses, - &mut exchanged_bytes, - &mut icmp_type, - &mut packet_filters_fields, - ); - if key_option.is_none() { - continue; - } - - let key = key_option.unwrap(); - let application_protocol = get_app_protocol(key.port1, key.port2); - let mut new_info = InfoAddressPortPair::default(); - - let passed_filters = filters.matches(&packet_filters_fields); - if passed_filters { - new_info = modify_or_insert_in_map( - info_traffic_mutex, - &key, - device, - mac_addresses, - icmp_type, - exchanged_bytes, - application_protocol, - ); - } + let mut exchanged_bytes = 0; + let mut mac_addresses = (None, None); + let mut icmp_type = IcmpType::default(); + let mut packet_filters_fields = PacketFiltersFields::default(); + + let key_option = analyze_headers( + headers, + &mut mac_addresses, + &mut exchanged_bytes, + &mut icmp_type, + &mut packet_filters_fields, + ); + if key_option.is_none() { + continue; + } - let mut info_traffic = info_traffic_mutex - .lock() - .expect("Error acquiring mutex\n\r"); - //increment number of sniffed packets and bytes - info_traffic.all_packets += 1; - info_traffic.all_bytes += exchanged_bytes; - // update dropped packets number - if let Ok(stats) = cap.stats() { - info_traffic.dropped_packets = stats.dropped; - } + let key = key_option.unwrap(); + let application_protocol = get_app_protocol(key.port1, key.port2); + let mut new_info = InfoAddressPortPair::default(); + + let passed_filters = filters.matches(&packet_filters_fields); + if passed_filters { + new_info = modify_or_insert_in_map( + info_traffic_mutex, + &key, + device, + mac_addresses, + icmp_type, + exchanged_bytes, + application_protocol, + ); + } - if passed_filters { - info_traffic.add_packet(exchanged_bytes, new_info.traffic_direction); + let mut info_traffic = info_traffic_mutex + .lock() + .expect("Error acquiring mutex\n\r"); + //increment number of sniffed packets and bytes + info_traffic.all_packets += 1; + info_traffic.all_bytes += exchanged_bytes; + // update dropped packets number + if let Ok(stats) = cap.stats() { + info_traffic.dropped_packets = stats.dropped; + } - // check the rDNS status of this address and act accordingly - let address_to_lookup = - get_address_to_lookup(&key, new_info.traffic_direction); - let r_dns_already_resolved = info_traffic - .addresses_resolved + if passed_filters { + info_traffic.add_packet(exchanged_bytes, new_info.traffic_direction); + + // check the rDNS status of this address and act accordingly + let address_to_lookup = + get_address_to_lookup(&key, new_info.traffic_direction); + let r_dns_already_resolved = info_traffic + .addresses_resolved + .contains_key(&address_to_lookup); + let mut r_dns_waiting_resolution = false; + if !r_dns_already_resolved { + r_dns_waiting_resolution = info_traffic + .addresses_waiting_resolution .contains_key(&address_to_lookup); - let mut r_dns_waiting_resolution = false; - if !r_dns_already_resolved { - r_dns_waiting_resolution = info_traffic - .addresses_waiting_resolution - .contains_key(&address_to_lookup); - } - - match (r_dns_waiting_resolution, r_dns_already_resolved) { - (false, false) => { - // rDNS not requested yet (first occurrence of this address to lookup) + } - // Add this address to the map of addresses waiting for a resolution - // Useful to NOT perform again a rDNS lookup for this entry - info_traffic.addresses_waiting_resolution.insert( - address_to_lookup, - DataInfo::new_with_first_packet( - exchanged_bytes, + match (r_dns_waiting_resolution, r_dns_already_resolved) { + (false, false) => { + // rDNS not requested yet (first occurrence of this address to lookup) + + // Add this address to the map of addresses waiting for a resolution + // Useful to NOT perform again a rDNS lookup for this entry + info_traffic.addresses_waiting_resolution.insert( + address_to_lookup, + DataInfo::new_with_first_packet( + exchanged_bytes, + new_info.traffic_direction, + ), + ); + + // launch new thread to resolve host name + let key2 = key.clone(); + let info_traffic2 = info_traffic_mutex.clone(); + let device2 = device.clone(); + let country_db_reader_2 = country_mmdb_reader.clone(); + let asn_db_reader_2 = asn_mmdb_reader.clone(); + thread::Builder::new() + .name("thread_reverse_dns_lookup".to_string()) + .spawn(move || { + reverse_dns_lookup( + &info_traffic2, + &key2, new_info.traffic_direction, - ), - ); - - // launch new thread to resolve host name - let key2 = key.clone(); - let info_traffic2 = info_traffic_mutex.clone(); - let device2 = device.clone(); - let country_db_reader_2 = country_mmdb_reader.clone(); - let asn_db_reader_2 = asn_mmdb_reader.clone(); - thread::Builder::new() - .name("thread_reverse_dns_lookup".to_string()) - .spawn(move || { - reverse_dns_lookup( - &info_traffic2, - &key2, - new_info.traffic_direction, - &device2, - &country_db_reader_2, - &asn_db_reader_2, - ); - }) - .unwrap(); - } - (true, false) => { - // waiting for a previously requested rDNS resolution - // update the corresponding waiting address data - info_traffic - .addresses_waiting_resolution - .entry(address_to_lookup) - .and_modify(|data_info| { - data_info.add_packet( - exchanged_bytes, - new_info.traffic_direction, - ); - }); - } - (_, true) => { - // rDNS already resolved - // update the corresponding host's data info - let host = info_traffic - .addresses_resolved - .get(&address_to_lookup) - .unwrap() - .1 - .clone(); - info_traffic.hosts.entry(host).and_modify(|data_info_host| { - data_info_host.data_info.add_packet( + &device2, + &country_db_reader_2, + &asn_db_reader_2, + ); + }) + .unwrap(); + } + (true, false) => { + // waiting for a previously requested rDNS resolution + // update the corresponding waiting address data + info_traffic + .addresses_waiting_resolution + .entry(address_to_lookup) + .and_modify(|data_info| { + data_info.add_packet( exchanged_bytes, new_info.traffic_direction, ); }); - } } - - //increment the packet count for the sniffed app protocol - info_traffic - .app_protocols - .entry(application_protocol) - .and_modify(|data_info| { - data_info + (_, true) => { + // rDNS already resolved + // update the corresponding host's data info + let host = info_traffic + .addresses_resolved + .get(&address_to_lookup) + .unwrap() + .1 + .clone(); + info_traffic.hosts.entry(host).and_modify(|data_info_host| { + data_info_host + .data_info .add_packet(exchanged_bytes, new_info.traffic_direction); - }) - .or_insert(DataInfo::new_with_first_packet( - exchanged_bytes, - new_info.traffic_direction, - )); + }); + } } + + //increment the packet count for the sniffed app protocol + info_traffic + .app_protocols + .entry(application_protocol) + .and_modify(|data_info| { + data_info.add_packet(exchanged_bytes, new_info.traffic_direction); + }) + .or_insert(DataInfo::new_with_first_packet( + exchanged_bytes, + new_info.traffic_direction, + )); } } } From e38c20257eb1dee0b7210c0e8732bdaf02cde95e Mon Sep 17 00:00:00 2001 From: Giuliano Bellini s294739 Date: Mon, 1 Jan 2024 17:42:37 +0100 Subject: [PATCH 16/16] updated deps and CHANGELOG; optimized imports --- CHANGELOG.md | 1 + Cargo.lock | 60 ++++++++++++++-------------- src/networking/types/my_device.rs | 3 +- src/networking/types/my_link_type.rs | 7 ++-- src/translations/translations_3.rs | 5 ++- 5 files changed, 40 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e008d2a..bf83a6a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All Sniffnet releases with the relative changes are documented in this file. - Introduced new filtering capabilities to allow users specify custom values of ports and IP addresses ([#414](https://github.com/GyulyVGC/sniffnet/pull/414)) - The size of text and widgets can now be customised by setting a proper zoom value (fixes [#202](https://github.com/GyulyVGC/sniffnet/issues/202) and [#344](https://github.com/GyulyVGC/sniffnet/issues/344)) - Added possibility to totally customize the app's theme via styles defined in TOML files ([#286](https://github.com/GyulyVGC/sniffnet/pull/286) and [#419](https://github.com/GyulyVGC/sniffnet/pull/419)) +- Added support for more link types in addition to Ethernet: raw IP packets and null/loopback packets are now correctly parsed ([#421](https://github.com/GyulyVGC/sniffnet/pull/421)) - IP addresses can now be copied to clipboard from the popup related to a given entry of the connections table, and a new search parameter has been introduced in Inspect page to allow users filter their connections based on IP address values ([#409](https://github.com/GyulyVGC/sniffnet/pull/409)) - Added Japanese translation 🇯🇵 ([#343](https://github.com/GyulyVGC/sniffnet/pull/343)) - Added Uzbek translation 🇺🇿 ([#385](https://github.com/GyulyVGC/sniffnet/pull/385)) diff --git a/Cargo.lock b/Cargo.lock index c04f6e3f..2c0b0b9f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -201,7 +201,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.43", + "syn 2.0.44", ] [[package]] @@ -279,7 +279,7 @@ checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.44", ] [[package]] @@ -353,13 +353,13 @@ dependencies = [ [[package]] name = "clang-sys" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" +checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" dependencies = [ "glob", "libc", - "libloading 0.7.4", + "libloading 0.8.1", ] [[package]] @@ -942,7 +942,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.44", ] [[package]] @@ -2118,7 +2118,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.44", ] [[package]] @@ -2247,7 +2247,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.44", ] [[package]] @@ -2298,7 +2298,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.44", ] [[package]] @@ -2330,7 +2330,7 @@ checksum = "b7db010ec5ff3d4385e4f133916faacd9dad0f6a09394c92d825b3aed310fa0a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.44", ] [[package]] @@ -2438,7 +2438,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.44", ] [[package]] @@ -2560,9 +2560,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.71" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8" +checksum = "2dd5e8a1f1029c43224ad5898e50140c2aebb1705f19e67c918ebf5b9e797fe1" dependencies = [ "unicode-ident", ] @@ -2584,9 +2584,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "22a37c9326af5ed140c86a46655b5278de879853be5573c01df185b6f49a580a" dependencies = [ "proc-macro2", ] @@ -2851,7 +2851,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.43", + "syn 2.0.44", "unicode-ident", ] @@ -3058,14 +3058,14 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.44", ] [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "cb0652c533506ad7a2e353cce269330d6afd8bdfb6d75e0ace5b35aacbd7b9e9" dependencies = [ "itoa", "ryu", @@ -3122,7 +3122,7 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.44", ] [[package]] @@ -3394,9 +3394,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.43" +version = "2.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53" +checksum = "92d27c2c202598d05175a6dd3af46824b7f747f8d8e9b14c623f19fa5069735d" dependencies = [ "proc-macro2", "quote", @@ -3457,22 +3457,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.52" +version = "1.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a48fd946b02c0a526b2e9481c8e2a17755e47039164a86c4070446e3a4614d" +checksum = "b2cd5904763bad08ad5513ddbb12cf2ae273ca53fa9f68e843e236ec6dfccc09" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.52" +version = "1.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7fbe9b594d6568a6a1443250a7e67d80b74e1e96f6d1715e1e21cc1888291d3" +checksum = "3dcf4a824cce0aeacd6f38ae6f24234c8e80d68632338ebaa1443b5df9e29e19" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.44", ] [[package]] @@ -3922,7 +3922,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.44", "wasm-bindgen-shared", ] @@ -3956,7 +3956,7 @@ checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.44", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4719,5 +4719,5 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.44", ] diff --git a/src/networking/types/my_device.rs b/src/networking/types/my_device.rs index 6170ec69..3e347d15 100644 --- a/src/networking/types/my_device.rs +++ b/src/networking/types/my_device.rs @@ -1,8 +1,9 @@ use std::sync::{Arc, Mutex}; -use crate::networking::types::my_link_type::MyLinkType; use pcap::{Address, Device, DeviceFlags}; +use crate::networking::types::my_link_type::MyLinkType; + /// Represents the current inspected device. /// Used to keep in sync the device addresses in case of changes /// (e.g., device not connected to the internet acquires new IP address) diff --git a/src/networking/types/my_link_type.rs b/src/networking/types/my_link_type.rs index 9e1e667c..24d2750c 100644 --- a/src/networking/types/my_link_type.rs +++ b/src/networking/types/my_link_type.rs @@ -1,10 +1,11 @@ +use iced::widget::Column; +use iced::{Font, Renderer}; +use pcap::Linktype; + use crate::gui::styles::text::TextType; use crate::gui::types::message::Message; use crate::translations::translations_3::link_type_translation; use crate::{Language, StyleType}; -use iced::widget::Column; -use iced::{Font, Renderer}; -use pcap::Linktype; /// Currently supported link types #[derive(Copy, Clone)] diff --git a/src/translations/translations_3.rs b/src/translations/translations_3.rs index b4caa682..163af584 100644 --- a/src/translations/translations_3.rs +++ b/src/translations/translations_3.rs @@ -1,10 +1,11 @@ #![allow(clippy::match_same_arms)] -use crate::translations::translations::network_adapter_translation; -use crate::{Language, StyleType}; use iced::widget::Text; use iced::Renderer; +use crate::translations::translations::network_adapter_translation; +use crate::{Language, StyleType}; + // This is referred to settings (General settings) pub fn general_translation(language: Language) -> &'static str { match language {