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();