mirror of
https://github.com/GyulyVGC/sniffnet.git
synced 2025-12-23 22:29:01 -05:00
feat: local addresses identification and directed broadcast support
This commit is contained in:
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="800px" height="600px" viewBox="0 0 800 600" version="1.1">
|
||||
<g id="surface1">
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 412.941406 485.992188 L 374.300781 485.992188 C 347.089844 485.992188 324.972656 502.578125 324.972656 522.988281 L 324.972656 563.003906 C 324.972656 583.414062 347.089844 600 374.300781 600 L 412.941406 600 C 440.152344 600 462.265625 583.414062 462.265625 563.003906 L 462.265625 522.988281 C 462.265625 502.519531 440.152344 485.992188 412.941406 485.992188 Z M 412.941406 485.992188 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 140.492188 176.21875 L 211.769531 182.878906 C 234.375 184.976562 255.832031 175.234375 263.972656 159.265625 C 274.25 139.101562 288.554688 123.195312 306.886719 111.601562 C 332.867188 95.199219 365.175781 86.9375 403.816406 86.9375 C 443.851562 86.9375 475.75 94.832031 499.425781 110.554688 C 523.101562 126.339844 534.859375 145.207031 534.859375 167.339844 C 534.859375 183.25 528.199219 197.800781 514.882812 210.996094 C 506.25 219.382812 479.695312 237.015625 435.382812 263.960938 C 390.988281 290.90625 361.476562 315.199219 346.679688 336.777344 C 331.550781 358.851562 326.289062 383.332031 324.976562 407.871094 C 323.824219 428.898438 346.183594 446.410156 374.300781 446.410156 L 414.585938 446.410156 C 440.234375 446.410156 461.445312 431.671875 463.746094 412.558594 C 465.390625 398.808594 468.433594 388.386719 473.039062 381.296875 C 480.765625 369.148438 500.742188 353.117188 532.804688 333.140625 C 594.875 294.605469 635.320312 264.144531 654.3125 241.703125 C 673.222656 219.320312 682.757812 195.582031 682.757812 170.484375 C 682.757812 125.167969 657.027344 85.398438 605.480469 51.238281 C 554.015625 17.078125 484.628906 0 397.484375 0 C 314.617188 0 247.777344 16.832031 196.808594 50.558594 C 153.398438 79.292969 127.007812 113.328125 117.71875 152.605469 C 114.839844 164.074219 125.28125 174.800781 140.492188 176.21875 Z M 140.492188 176.21875 "/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.1 KiB |
13
resources/countries_flags/4x3/zz-broadcast.svg
Normal file
13
resources/countries_flags/4x3/zz-broadcast.svg
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="48" height="48" fill="white" fill-opacity="0.01"/>
|
||||
<path d="M24 15C26.7614 15 29 12.7614 29 10C29 7.23858 26.7614 5 24 5C21.2386 5 19 7.23858 19 10C19 12.7614 21.2386 15 24 15Z" fill="#2F88FF" stroke="#000000" stroke-width="4"/>
|
||||
<path d="M24 15V23" stroke="#000000" stroke-width="4" stroke-linecap="round"/>
|
||||
<path d="M30 23V33" stroke="#000000" stroke-width="4" stroke-linecap="round"/>
|
||||
<path d="M18 23V33" stroke="#000000" stroke-width="4" stroke-linecap="round"/>
|
||||
<path d="M7 33V23L41 23.0128V33" stroke="#000000" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M41 41V42" stroke="#000000" stroke-width="5" stroke-linecap="round"/>
|
||||
<path d="M7 41V42" stroke="#000000" stroke-width="5" stroke-linecap="round"/>
|
||||
<path d="M18 41V42" stroke="#000000" stroke-width="5" stroke-linecap="round"/>
|
||||
<path d="M30 41V42" stroke="#000000" stroke-width="5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
16
resources/countries_flags/4x3/zz-home.svg
Normal file
16
resources/countries_flags/4x3/zz-home.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg fill="#000000" height="800px" width="800px" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
viewBox="0 0 26.39 26.39" xml:space="preserve">
|
||||
<g>
|
||||
<g id="c14_house">
|
||||
<path d="M3.588,24.297c0,0-0.024,0.59,0.553,0.59c0.718,0,6.652-0.008,6.652-0.008l0.01-5.451c0,0-0.094-0.898,0.777-0.898h2.761
|
||||
c1.031,0,0.968,0.898,0.968,0.898l-0.012,5.434c0,0,5.628,0,6.512,0c0.732,0,0.699-0.734,0.699-0.734V14.076L13.33,5.913
|
||||
l-9.742,8.164C3.588,14.077,3.588,24.297,3.588,24.297z"/>
|
||||
<path d="M0,13.317c0,0,0.826,1.524,2.631,0l10.781-9.121l10.107,9.064c2.088,1.506,2.871,0,2.871,0L13.412,1.504L0,13.317z"/>
|
||||
<polygon points="23.273,4.175 20.674,4.175 20.685,7.328 23.273,9.525 "/>
|
||||
</g>
|
||||
<g id="Capa_1_216_">
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 923 B |
11
resources/countries_flags/4x3/zz-multicast.svg
Normal file
11
resources/countries_flags/4x3/zz-multicast.svg
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="48" height="48" fill="white" fill-opacity="0.01"/>
|
||||
<path d="M24 15C26.7614 15 29 12.7614 29 10C29 7.23858 26.7614 5 24 5C21.2386 5 19 7.23858 19 10C19 12.7614 21.2386 15 24 15Z" fill="#2F88FF" stroke="#000000" stroke-width="4"/>
|
||||
<path d="M24 15V23" stroke="#000000" stroke-width="4" stroke-linecap="round"/>
|
||||
<path d="M18 33V23L41 23.0128V33" stroke="#000000" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M41 41V42" stroke="#000000" stroke-width="5" stroke-linecap="round"/>
|
||||
<path d="M7 41V42" stroke="#000000" stroke-width="5" stroke-linecap="round"/>
|
||||
<path d="M18 41V42" stroke="#000000" stroke-width="5" stroke-linecap="round"/>
|
||||
<path d="M30 41V42" stroke="#000000" stroke-width="5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 989 B |
17
resources/countries_flags/4x3/zz-unknown.svg
Normal file
17
resources/countries_flags/4x3/zz-unknown.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg fill="#000000" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="800px" height="800px" viewBox="0 0 973.1 973.1" xml:space="preserve"
|
||||
>
|
||||
<g>
|
||||
<path d="M502.29,788.199h-47c-33.1,0-60,26.9-60,60v64.9c0,33.1,26.9,60,60,60h47c33.101,0,60-26.9,60-60v-64.9
|
||||
C562.29,815,535.391,788.199,502.29,788.199z"/>
|
||||
<path d="M170.89,285.8l86.7,10.8c27.5,3.4,53.6-12.4,63.5-38.3c12.5-32.7,29.9-58.5,52.2-77.3c31.601-26.6,70.9-40,117.9-40
|
||||
c48.7,0,87.5,12.8,116.3,38.3c28.8,25.6,43.1,56.2,43.1,92.1c0,25.8-8.1,49.4-24.3,70.8c-10.5,13.6-42.8,42.2-96.7,85.9
|
||||
c-54,43.7-89.899,83.099-107.899,118.099c-18.4,35.801-24.8,75.5-26.4,115.301c-1.399,34.1,25.8,62.5,60,62.5h49
|
||||
c31.2,0,57-23.9,59.8-54.9c2-22.299,5.7-39.199,11.301-50.699c9.399-19.701,33.699-45.701,72.699-78.1
|
||||
C723.59,477.8,772.79,428.4,795.891,392c23-36.3,34.6-74.8,34.6-115.5c0-73.5-31.3-138-94-193.4c-62.6-55.4-147-83.1-253-83.1
|
||||
c-100.8,0-182.1,27.3-244.1,82c-52.8,46.6-84.9,101.8-96.2,165.5C139.69,266.1,152.39,283.5,170.89,285.8z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -5,7 +5,7 @@
|
||||
use crate::gui::styles::types::style_tuple::StyleTuple;
|
||||
use crate::gui::types::message::Message;
|
||||
use crate::report::get_report_entries::get_searched_entries;
|
||||
use crate::utils::countries::{get_flag_from_country_code, FLAGS_WIDTH_SMALL};
|
||||
use crate::utils::countries::{get_flag_tooltip, FLAGS_WIDTH_SMALL};
|
||||
use crate::utils::formatted_strings::{get_connection_color, get_open_report_tooltip};
|
||||
use crate::{Language, RunningPage, Sniffer, StyleType};
|
||||
use iced::widget::{Button, Column, Container, Row, Scrollable, Text, Tooltip};
|
||||
@@ -66,33 +66,27 @@ pub fn inspect_page(sniffer: &Sniffer) -> Container<Message> {
|
||||
for index in &search_results {
|
||||
let info_traffic_lock = sniffer.info_traffic.lock().unwrap();
|
||||
let key_val = info_traffic_lock.map.get_index(*index).unwrap();
|
||||
let entry_color = get_connection_color(key_val.1.traffic_type, sniffer.style);
|
||||
let mut entry_row = Row::new().align_items(Alignment::Center).push(
|
||||
Text::new(format!(
|
||||
" {}{}",
|
||||
key_val.0.print_gui(),
|
||||
key_val.1.print_gui()
|
||||
))
|
||||
.style(iced::theme::Text::Color(entry_color))
|
||||
.font(SARASA_MONO_SC_BOLD),
|
||||
);
|
||||
if key_val.1.country.is_empty() {
|
||||
entry_row = entry_row
|
||||
.push(
|
||||
Text::new("?")
|
||||
.width(Length::Fixed(FLAGS_WIDTH_SMALL))
|
||||
.style(iced::theme::Text::Color(entry_color))
|
||||
.font(SARASA_MONO_SC_BOLD),
|
||||
)
|
||||
.push(Text::new(" "));
|
||||
} else {
|
||||
entry_row = entry_row
|
||||
.push(get_flag_from_country_code(
|
||||
&key_val.1.country,
|
||||
FLAGS_WIDTH_SMALL,
|
||||
let entry_color = get_connection_color(key_val.1.traffic_direction, sniffer.style);
|
||||
let entry_row = Row::new()
|
||||
.align_items(Alignment::Center)
|
||||
.push(
|
||||
Text::new(format!(
|
||||
" {}{}",
|
||||
key_val.0.print_gui(),
|
||||
key_val.1.print_gui()
|
||||
))
|
||||
.push(Text::new(" "));
|
||||
}
|
||||
.style(iced::theme::Text::Color(entry_color))
|
||||
.font(SARASA_MONO_SC_BOLD),
|
||||
)
|
||||
.push(get_flag_tooltip(
|
||||
&key_val.1.country,
|
||||
FLAGS_WIDTH_SMALL,
|
||||
key_val.1.is_local,
|
||||
key_val.1.traffic_type,
|
||||
sniffer.language,
|
||||
sniffer.style,
|
||||
))
|
||||
.push(Text::new(" "));
|
||||
|
||||
scroll_report = scroll_report.push(
|
||||
button(entry_row)
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
packets_exceeded_translation, packets_exceeded_value_translation, per_second_translation,
|
||||
threshold_translation,
|
||||
};
|
||||
use crate::utils::countries::{get_flag_from_country_code, FLAGS_WIDTH_BIG};
|
||||
use crate::utils::countries::{get_flag_tooltip, FLAGS_WIDTH_BIG};
|
||||
use crate::utils::formatted_strings::get_formatted_bytes_string;
|
||||
use crate::{Language, RunningPage, Sniffer, StyleType};
|
||||
|
||||
@@ -187,9 +187,8 @@ fn packets_notification_log(
|
||||
Tooltip::new(
|
||||
Text::new("e").font(ICONS).size(80),
|
||||
packets_exceeded_translation(language),
|
||||
Position::Left,
|
||||
Position::FollowCursor,
|
||||
)
|
||||
.gap(5)
|
||||
.font(font)
|
||||
.style(<StyleTuple as Into<iced::theme::Container>>::into(
|
||||
StyleTuple(style, ElementType::Tooltip),
|
||||
@@ -266,9 +265,8 @@ fn bytes_notification_log(
|
||||
Tooltip::new(
|
||||
Text::new("f").font(ICONS).size(80),
|
||||
bytes_exceeded_translation(language),
|
||||
Position::Left,
|
||||
Position::FollowCursor,
|
||||
)
|
||||
.gap(5)
|
||||
.font(font)
|
||||
.style(<StyleTuple as Into<iced::theme::Container>>::into(
|
||||
StyleTuple(style, ElementType::Tooltip),
|
||||
@@ -323,8 +321,14 @@ fn favorite_notification_log(
|
||||
let details_str = format!("{domain} - {}", asn.name);
|
||||
let mut row_flag_details = Row::new().align_items(Alignment::Center).spacing(5);
|
||||
if !country.is_empty() {
|
||||
row_flag_details =
|
||||
row_flag_details.push(get_flag_from_country_code(&country, FLAGS_WIDTH_BIG));
|
||||
row_flag_details = row_flag_details.push(get_flag_tooltip(
|
||||
&country,
|
||||
FLAGS_WIDTH_BIG,
|
||||
logged_notification.data_info_host.is_local,
|
||||
logged_notification.data_info_host.traffic_type,
|
||||
language,
|
||||
style,
|
||||
));
|
||||
}
|
||||
row_flag_details = row_flag_details.push(Text::new(details_str).font(font));
|
||||
let content = Row::new()
|
||||
@@ -335,9 +339,8 @@ fn favorite_notification_log(
|
||||
Tooltip::new(
|
||||
Text::new("g").font(ICONS).size(80),
|
||||
favorite_transmitted_translation(language),
|
||||
Position::Left,
|
||||
Position::FollowCursor,
|
||||
)
|
||||
.gap(5)
|
||||
.font(font)
|
||||
.style(<StyleTuple as Into<iced::theme::Container>>::into(
|
||||
StyleTuple(style, ElementType::Tooltip),
|
||||
|
||||
@@ -32,9 +32,9 @@
|
||||
};
|
||||
use crate::translations::translations_2::{
|
||||
data_representation_translation, dropped_packets_translation, host_translation,
|
||||
of_total_translation, only_top_30_hosts,
|
||||
of_total_translation, only_top_30_hosts_translation,
|
||||
};
|
||||
use crate::utils::countries::{get_flag_from_country_code, FLAGS_WIDTH_BIG};
|
||||
use crate::utils::countries::{get_flag_tooltip, FLAGS_WIDTH_BIG};
|
||||
use crate::utils::formatted_strings::{
|
||||
get_active_filters_string, get_formatted_bytes_string, get_percentage_string,
|
||||
};
|
||||
@@ -402,12 +402,12 @@ fn col_host(width: f32, sniffer: &Sniffer) -> Column<'static, Message> {
|
||||
.align_items(Alignment::Center);
|
||||
let entries = get_host_entries(&sniffer.info_traffic, chart_type);
|
||||
|
||||
for (host, (data_info, is_favorite)) in &entries {
|
||||
for (host, data_info_host) in &entries {
|
||||
let (mut incoming_bar_len, mut outgoing_bar_len) = get_bars_length(
|
||||
width * 0.86,
|
||||
chart_type,
|
||||
entries.get(0).unwrap().1 .0.clone(),
|
||||
data_info,
|
||||
entries.get(0).unwrap().1.data_info.clone(),
|
||||
&data_info_host.data_info,
|
||||
);
|
||||
|
||||
let star_button = button(
|
||||
@@ -423,7 +423,7 @@ fn col_host(width: f32, sniffer: &Sniffer) -> Column<'static, Message> {
|
||||
.style(
|
||||
StyleTuple(
|
||||
sniffer.style,
|
||||
if *is_favorite {
|
||||
if data_info_host.is_favorite {
|
||||
ElementType::Starred
|
||||
} else {
|
||||
ElementType::NotStarred
|
||||
@@ -431,7 +431,10 @@ fn col_host(width: f32, sniffer: &Sniffer) -> Column<'static, Message> {
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
.on_press(Message::AddOrRemoveFavorite(host.clone(), !*is_favorite));
|
||||
.on_press(Message::AddOrRemoveFavorite(
|
||||
host.clone(),
|
||||
!data_info_host.is_favorite,
|
||||
));
|
||||
|
||||
// normalize smaller values
|
||||
if incoming_bar_len > 0.0 && incoming_bar_len < 3.0 {
|
||||
@@ -454,10 +457,11 @@ fn col_host(width: f32, sniffer: &Sniffer) -> Column<'static, Message> {
|
||||
}))
|
||||
.push(horizontal_space(Length::FillPortion(1)))
|
||||
.push(Text::new(if chart_type.eq(&ChartType::Packets) {
|
||||
data_info.tot_packets().to_string()
|
||||
data_info_host.data_info.tot_packets().to_string()
|
||||
} else {
|
||||
let mut bytes_string =
|
||||
get_formatted_bytes_string(data_info.tot_bytes()).replace(" ", " ");
|
||||
get_formatted_bytes_string(data_info_host.data_info.tot_bytes())
|
||||
.replace(" ", " ");
|
||||
bytes_string.push('B');
|
||||
bytes_string
|
||||
})),
|
||||
@@ -490,7 +494,14 @@ fn col_host(width: f32, sniffer: &Sniffer) -> Column<'static, Message> {
|
||||
.align_items(Alignment::Center)
|
||||
.spacing(5)
|
||||
.push(star_button)
|
||||
.push(get_flag_from_country_code(&host.country, FLAGS_WIDTH_BIG))
|
||||
.push(get_flag_tooltip(
|
||||
&host.country,
|
||||
FLAGS_WIDTH_BIG,
|
||||
data_info_host.is_local,
|
||||
data_info_host.traffic_type,
|
||||
sniffer.language,
|
||||
sniffer.style,
|
||||
))
|
||||
.push(host_bar);
|
||||
|
||||
scroll_host = scroll_host.push(
|
||||
@@ -508,7 +519,7 @@ fn col_host(width: f32, sniffer: &Sniffer) -> Column<'static, Message> {
|
||||
|
||||
if entries.len() == 30 {
|
||||
scroll_host = scroll_host.push(vertical_space(Length::Fixed(25.0))).push(
|
||||
Text::new(only_top_30_hosts(sniffer.language))
|
||||
Text::new(only_top_30_hosts_translation(sniffer.language))
|
||||
.horizontal_alignment(Horizontal::Center)
|
||||
.font(font),
|
||||
);
|
||||
|
||||
@@ -379,7 +379,7 @@ fn add_or_remove_favorite(&mut self, host: Host, add: bool) {
|
||||
info_traffic.favorite_hosts.remove(&host);
|
||||
}
|
||||
if let Some(host_info) = info_traffic.hosts.get_mut(&host) {
|
||||
host_info.1 = add;
|
||||
host_info.is_favorite = add;
|
||||
}
|
||||
drop(info_traffic);
|
||||
}
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
use std::net::{IpAddr, Ipv4Addr};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use chrono::Local;
|
||||
use dns_lookup::lookup_addr;
|
||||
use etherparse::{Ethernet2Header, IpHeader, TransportHeader};
|
||||
use maxminddb::Reader;
|
||||
use pcap::{Active, Capture, Device};
|
||||
use pcap::{Active, Address, Capture, Device};
|
||||
|
||||
use crate::networking::types::address_port_pair::AddressPortPair;
|
||||
use crate::networking::types::app_protocol::from_port_to_application_protocol;
|
||||
use crate::networking::types::asn::Asn;
|
||||
use crate::networking::types::data_info::DataInfo;
|
||||
use crate::networking::types::data_info_host::DataInfoHost;
|
||||
use crate::networking::types::info_address_port_pair::InfoAddressPortPair;
|
||||
use crate::networking::types::traffic_direction::TrafficDirection;
|
||||
use crate::networking::types::traffic_type::TrafficType;
|
||||
use crate::utils::asn::get_asn;
|
||||
use crate::utils::countries::get_country_code;
|
||||
use crate::IpVersion::{IPv4, IPv6};
|
||||
use crate::{AppProtocol, InfoTraffic, IpVersion, TransProtocol};
|
||||
|
||||
/// This function analyzes the data link layer header passed as parameter and updates variables
|
||||
@@ -111,26 +115,40 @@ pub fn analyze_transport_header(
|
||||
pub fn modify_or_insert_in_map(
|
||||
info_traffic_mutex: &Arc<Mutex<InfoTraffic>>,
|
||||
key: AddressPortPair,
|
||||
my_interface_addresses: &Vec<Address>,
|
||||
mac_address1: String,
|
||||
mac_address2: String,
|
||||
exchanged_bytes: u128,
|
||||
traffic_type: TrafficType,
|
||||
application_protocol: AppProtocol,
|
||||
country_db_reader: &Reader<&[u8]>,
|
||||
asn_db_reader: &Reader<&[u8]>,
|
||||
) -> InfoAddressPortPair {
|
||||
let now = Local::now();
|
||||
let very_long_address = key.address1.len() > 25 || key.address2.len() > 25;
|
||||
let mut traffic_direction = TrafficDirection::default();
|
||||
let source_ip = &key.address1.clone();
|
||||
let destination_ip = &key.address2.clone();
|
||||
let very_long_address = source_ip.len() > 25 || destination_ip.len() > 25;
|
||||
let mut is_local = false;
|
||||
let mut traffic_type = TrafficType::default();
|
||||
|
||||
let mut info_traffic = info_traffic_mutex
|
||||
.lock()
|
||||
.expect("Error acquiring mutex\n\r");
|
||||
let len = info_traffic.map.len();
|
||||
let index = info_traffic.map.get_index_of(&key).unwrap_or(len);
|
||||
let (country, asn) = if index == len {
|
||||
// first occurrence of key => retrieve country code and asn
|
||||
// first occurrence of key => retrieve traffic type, country code and asn
|
||||
traffic_type = get_traffic_type(destination_ip, my_interface_addresses);
|
||||
traffic_direction = get_traffic_direction(source_ip, my_interface_addresses);
|
||||
is_local = is_local_connection(
|
||||
source_ip,
|
||||
destination_ip,
|
||||
traffic_direction,
|
||||
my_interface_addresses,
|
||||
);
|
||||
(
|
||||
get_country_code(traffic_type, &key, country_db_reader),
|
||||
get_asn(traffic_type, &key, asn_db_reader),
|
||||
get_country_code(traffic_direction, &key, country_db_reader),
|
||||
get_asn(traffic_direction, &key, asn_db_reader),
|
||||
)
|
||||
} else {
|
||||
// this key already occurred
|
||||
@@ -154,11 +172,13 @@ pub fn modify_or_insert_in_map(
|
||||
final_timestamp: now,
|
||||
app_protocol: application_protocol,
|
||||
very_long_address,
|
||||
traffic_direction,
|
||||
traffic_type,
|
||||
country,
|
||||
asn,
|
||||
r_dns: None,
|
||||
index,
|
||||
is_local,
|
||||
})
|
||||
.clone();
|
||||
|
||||
@@ -175,10 +195,10 @@ pub fn modify_or_insert_in_map(
|
||||
pub fn reverse_dns_lookup(
|
||||
info_traffic: Arc<Mutex<InfoTraffic>>,
|
||||
key: AddressPortPair,
|
||||
traffic_type: TrafficType,
|
||||
traffic_direction: TrafficDirection,
|
||||
) {
|
||||
let address_to_lookup = match traffic_type {
|
||||
TrafficType::Outgoing => key.address2.clone(),
|
||||
let address_to_lookup = match traffic_direction {
|
||||
TrafficDirection::Outgoing => key.address2.clone(),
|
||||
_ => key.address1.clone(),
|
||||
};
|
||||
|
||||
@@ -213,40 +233,74 @@ pub fn reverse_dns_lookup(
|
||||
info_traffic_lock
|
||||
.hosts
|
||||
.entry(new_info.get_host())
|
||||
.and_modify(|(data_info, _)| {
|
||||
if new_info.traffic_type == TrafficType::Outgoing {
|
||||
data_info.outgoing_packets += new_info.transmitted_packets;
|
||||
data_info.outgoing_bytes += new_info.transmitted_bytes;
|
||||
.and_modify(|data_info_host| {
|
||||
if new_info.traffic_direction == TrafficDirection::Outgoing {
|
||||
data_info_host.data_info.outgoing_packets += new_info.transmitted_packets;
|
||||
data_info_host.data_info.outgoing_bytes += new_info.transmitted_bytes;
|
||||
} else {
|
||||
data_info.incoming_packets += new_info.transmitted_packets;
|
||||
data_info.incoming_bytes += new_info.transmitted_bytes;
|
||||
data_info_host.data_info.incoming_packets += new_info.transmitted_packets;
|
||||
data_info_host.data_info.incoming_bytes += new_info.transmitted_bytes;
|
||||
}
|
||||
})
|
||||
.or_insert(if new_info.traffic_type == TrafficType::Outgoing {
|
||||
(
|
||||
DataInfo {
|
||||
incoming_packets: 0,
|
||||
outgoing_packets: new_info.transmitted_packets,
|
||||
incoming_bytes: 0,
|
||||
outgoing_bytes: new_info.transmitted_bytes,
|
||||
},
|
||||
false,
|
||||
)
|
||||
} else {
|
||||
(
|
||||
DataInfo {
|
||||
incoming_packets: new_info.transmitted_packets,
|
||||
outgoing_packets: 0,
|
||||
incoming_bytes: new_info.transmitted_bytes,
|
||||
outgoing_bytes: 0,
|
||||
},
|
||||
false,
|
||||
)
|
||||
});
|
||||
.or_insert(
|
||||
if new_info.traffic_direction == TrafficDirection::Outgoing {
|
||||
DataInfoHost {
|
||||
data_info: DataInfo {
|
||||
incoming_packets: 0,
|
||||
outgoing_packets: new_info.transmitted_packets,
|
||||
incoming_bytes: 0,
|
||||
outgoing_bytes: new_info.transmitted_bytes,
|
||||
},
|
||||
is_favorite: false,
|
||||
is_local: new_info.is_local,
|
||||
traffic_type: new_info.traffic_type,
|
||||
}
|
||||
} else {
|
||||
DataInfoHost {
|
||||
data_info: DataInfo {
|
||||
incoming_packets: new_info.transmitted_packets,
|
||||
outgoing_packets: 0,
|
||||
incoming_bytes: new_info.transmitted_bytes,
|
||||
outgoing_bytes: 0,
|
||||
},
|
||||
is_favorite: false,
|
||||
is_local: new_info.is_local,
|
||||
traffic_type: new_info.traffic_type,
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
drop(info_traffic_lock);
|
||||
}
|
||||
|
||||
/// Returns the traffic direction observed (incoming or outgoing)
|
||||
fn get_traffic_direction(
|
||||
source_ip: &String,
|
||||
my_interface_addresses: &Vec<Address>,
|
||||
) -> TrafficDirection {
|
||||
let my_interface_addresses_string: Vec<String> = my_interface_addresses
|
||||
.iter()
|
||||
.map(|address| address.addr.to_string())
|
||||
.collect();
|
||||
|
||||
if my_interface_addresses_string.contains(source_ip) {
|
||||
TrafficDirection::Outgoing
|
||||
} else {
|
||||
TrafficDirection::Incoming
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the traffic type observed (unicast, multicast or broadcast)
|
||||
fn get_traffic_type(destination_ip: &String, my_interface_addresses: &Vec<Address>) -> TrafficType {
|
||||
if is_multicast_address(destination_ip) {
|
||||
TrafficType::Multicast
|
||||
} else if is_broadcast_address(destination_ip, my_interface_addresses) {
|
||||
TrafficType::Broadcast
|
||||
} else {
|
||||
TrafficType::Unicast
|
||||
}
|
||||
}
|
||||
|
||||
/// Determines if the input address is a multicast address or not.
|
||||
///
|
||||
/// # Arguments
|
||||
@@ -280,8 +334,23 @@ pub fn is_multicast_address(address: &str) -> bool {
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `address` - string representing an IPv4 or IPv6 network address.
|
||||
pub fn is_broadcast_address(address: &str) -> bool {
|
||||
pub fn is_broadcast_address(address: &str, my_interface_addresses: &Vec<Address>) -> bool {
|
||||
let mut ret_val = false;
|
||||
|
||||
// check if directed broadcast
|
||||
let my_broadcast_addresses: Vec<String> = my_interface_addresses
|
||||
.iter()
|
||||
.map(|address| {
|
||||
address
|
||||
.broadcast_addr
|
||||
.unwrap_or("255.255.255.255".parse().unwrap())
|
||||
.to_string()
|
||||
})
|
||||
.collect();
|
||||
if my_broadcast_addresses.contains(&address.to_string()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if !address.contains(':') {
|
||||
//IPv4 address
|
||||
let groups: Vec<u8> = address
|
||||
@@ -295,11 +364,82 @@ pub fn is_broadcast_address(address: &str) -> bool {
|
||||
{
|
||||
ret_val = true;
|
||||
}
|
||||
// still missing a check for directed broadcast!
|
||||
}
|
||||
ret_val
|
||||
}
|
||||
|
||||
/// Determines if the connection is local
|
||||
fn is_local_connection(
|
||||
source_ip: &String,
|
||||
destination_ip: &String,
|
||||
traffic_direction: TrafficDirection,
|
||||
my_interface_addresses: &Vec<Address>,
|
||||
) -> bool {
|
||||
let mut ret_val = false;
|
||||
|
||||
let address_to_lookup = match traffic_direction {
|
||||
TrafficDirection::Outgoing => destination_ip,
|
||||
_ => source_ip,
|
||||
};
|
||||
let address_to_lookup_type = if address_to_lookup.contains(":") {
|
||||
IPv6
|
||||
} else {
|
||||
IPv4
|
||||
};
|
||||
|
||||
for address in my_interface_addresses {
|
||||
match address.addr {
|
||||
IpAddr::V4(local_addr) if address_to_lookup_type.eq(&IPv4) => {
|
||||
// check if the two IPv4 addresses are in the same subnet
|
||||
let address_to_lookup_parsed: Ipv4Addr =
|
||||
address_to_lookup.parse().unwrap_or(Ipv4Addr::from(0));
|
||||
// remote is link local?
|
||||
if address_to_lookup_parsed.is_link_local() {
|
||||
ret_val = true;
|
||||
}
|
||||
// is the same subnet?
|
||||
else if let Some(IpAddr::V4(netmask)) = address.netmask {
|
||||
let mut local_subnet = Vec::new();
|
||||
let mut remote_subnet = Vec::new();
|
||||
let netmask_digits = netmask.octets();
|
||||
let local_addr_digits = local_addr.octets();
|
||||
let remote_addr_digits = address_to_lookup_parsed.octets();
|
||||
for (i, netmask_digit) in netmask_digits.iter().enumerate() {
|
||||
local_subnet.push(netmask_digit & local_addr_digits[i]);
|
||||
remote_subnet.push(netmask_digit & remote_addr_digits[i]);
|
||||
}
|
||||
if local_subnet == remote_subnet {
|
||||
ret_val = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
IpAddr::V6(local_addr) if address_to_lookup_type.eq(&IPv6) => {
|
||||
// check if the two IPv6 addresses are in the same subnet
|
||||
// remote is link local?
|
||||
if address_to_lookup.starts_with("fe80") {
|
||||
ret_val = true;
|
||||
}
|
||||
// is the same subnet?
|
||||
else if let Some(IpAddr::V6(netmask)) = address.netmask {
|
||||
let netmask_len = netmask.to_string().len();
|
||||
let local_address_string = local_addr.to_string();
|
||||
let local_subnet = local_address_string.get(0..netmask_len).unwrap_or("");
|
||||
let remote_subnet = address_to_lookup.get(0..netmask_len).unwrap_or("");
|
||||
if !local_subnet.is_empty()
|
||||
&& !remote_subnet.is_empty()
|
||||
&& local_subnet == remote_subnet
|
||||
{
|
||||
ret_val = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
ret_val
|
||||
}
|
||||
|
||||
/// Determines if the capture opening resolves into an Error
|
||||
pub fn get_capture_result(device: &Device) -> (Option<String>, Option<Capture<Active>>) {
|
||||
let cap_result = Capture::from_device(&*device.name)
|
||||
@@ -420,7 +560,12 @@ pub fn get_capture_result(device: &Device) -> (Option<String>, Option<Capture<Ac
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::networking::manage_packets::{ipv6_from_long_dec_to_short_hex, mac_from_dec_to_hex};
|
||||
use crate::networking::manage_packets::{
|
||||
ipv6_from_long_dec_to_short_hex, is_local_connection, mac_from_dec_to_hex,
|
||||
};
|
||||
use crate::networking::types::traffic_direction::TrafficDirection;
|
||||
use pcap::Address;
|
||||
use std::net::{IpAddr, Ipv4Addr};
|
||||
|
||||
#[test]
|
||||
fn mac_simple_test() {
|
||||
@@ -533,4 +678,60 @@ fn ipv6_many_zeros_but_no_compression() {
|
||||
ipv6_from_long_dec_to_short_hex([0, 16, 16, 0, 0, 1, 7, 0, 0, 2, 216, 0, 1, 0, 0, 1]);
|
||||
assert_eq!(result, "10:1000:1:700:2:d800:100:1".to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_local_connection_ipv4_test() {
|
||||
let mut address_vec: Vec<Address> = Vec::new();
|
||||
let my_address = Address {
|
||||
addr: IpAddr::V4("172.20.10.9".parse().unwrap()),
|
||||
netmask: Some(IpAddr::V4("255.255.255.240".parse().unwrap())),
|
||||
broadcast_addr: None,
|
||||
dst_addr: None,
|
||||
};
|
||||
address_vec.push(my_address);
|
||||
|
||||
let result1 = is_local_connection(
|
||||
&"172.20.10.9".to_string(),
|
||||
&"104.18.43.158".to_string(),
|
||||
TrafficDirection::Outgoing,
|
||||
&address_vec,
|
||||
);
|
||||
assert_eq!(result1, false);
|
||||
|
||||
let result2 = is_local_connection(
|
||||
&"172.20.10.9".to_string(),
|
||||
&"172.20.10.15".to_string(),
|
||||
TrafficDirection::Outgoing,
|
||||
&address_vec,
|
||||
);
|
||||
assert_eq!(result2, true);
|
||||
|
||||
let result3 = is_local_connection(
|
||||
&"172.20.10.9".to_string(),
|
||||
&"172.20.10.16".to_string(),
|
||||
TrafficDirection::Outgoing,
|
||||
&address_vec,
|
||||
);
|
||||
assert_eq!(result3, false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_local_connection_ipv4_multicast_test() {
|
||||
let mut address_vec: Vec<Address> = Vec::new();
|
||||
let my_address = Address {
|
||||
addr: IpAddr::V4("172.20.10.9".parse().unwrap()),
|
||||
netmask: Some(IpAddr::V4("255.255.255.240".parse().unwrap())),
|
||||
broadcast_addr: None,
|
||||
dst_addr: None,
|
||||
};
|
||||
address_vec.push(my_address);
|
||||
|
||||
let result1 = is_local_connection(
|
||||
&"172.20.10.9".to_string(),
|
||||
&"224.0.0.251".to_string(),
|
||||
TrafficDirection::Outgoing,
|
||||
&address_vec,
|
||||
);
|
||||
assert_eq!(result1, false);
|
||||
}
|
||||
}
|
||||
|
||||
17
src/networking/types/data_info_host.rs
Normal file
17
src/networking/types/data_info_host.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
//! Module defining the `DataInfoHost` struct related to hosts.
|
||||
|
||||
use crate::networking::types::data_info::DataInfo;
|
||||
use crate::networking::types::traffic_type::TrafficType;
|
||||
|
||||
/// Host-related information.
|
||||
#[derive(Clone, Default)]
|
||||
pub struct DataInfoHost {
|
||||
/// Incoming and outgoing packets and bytes
|
||||
pub data_info: DataInfo,
|
||||
/// Determine if this host is one of the favorites
|
||||
pub is_favorite: bool,
|
||||
/// Determine if the connection with this host is local
|
||||
pub is_local: bool,
|
||||
/// Determine if the connection with this host is multicast or broadcast
|
||||
pub traffic_type: TrafficType,
|
||||
}
|
||||
@@ -3,12 +3,12 @@
|
||||
|
||||
use std::fmt;
|
||||
use std::net::IpAddr;
|
||||
use std::ops::Add;
|
||||
|
||||
use chrono::{DateTime, Local};
|
||||
|
||||
use crate::networking::types::asn::Asn;
|
||||
use crate::networking::types::host::Host;
|
||||
use crate::networking::types::traffic_direction::TrafficDirection;
|
||||
use crate::networking::types::traffic_type::TrafficType;
|
||||
use crate::utils::formatted_strings::get_formatted_bytes_string;
|
||||
use crate::AppProtocol;
|
||||
@@ -34,8 +34,6 @@ pub struct InfoAddressPortPair {
|
||||
pub app_protocol: AppProtocol,
|
||||
/// Check if source or destination is an IPv6 address longer than 25 bytes (used for Display
|
||||
pub very_long_address: bool,
|
||||
/// Flag to determine which of the address is that of the sniffed adapter or remote
|
||||
pub traffic_type: TrafficType,
|
||||
/// Country of the remote IP address
|
||||
pub country: String,
|
||||
/// Autonomous System of the remote IP address
|
||||
@@ -44,6 +42,12 @@ pub struct InfoAddressPortPair {
|
||||
pub r_dns: Option<String>,
|
||||
/// Integer corresponding to the index inside the connections map
|
||||
pub index: usize,
|
||||
/// Determines if the connection is incoming or outgoing
|
||||
pub traffic_direction: TrafficDirection,
|
||||
/// Determines if the connection is unicast, multicast or broadcast
|
||||
pub traffic_type: TrafficType,
|
||||
/// Determines if the connection is local
|
||||
pub is_local: bool,
|
||||
}
|
||||
|
||||
impl Default for InfoAddressPortPair {
|
||||
@@ -57,11 +61,13 @@ fn default() -> Self {
|
||||
final_timestamp: Default::default(),
|
||||
app_protocol: AppProtocol::Other,
|
||||
very_long_address: false,
|
||||
traffic_type: TrafficType::Other,
|
||||
traffic_direction: TrafficDirection::default(),
|
||||
traffic_type: TrafficType::default(),
|
||||
country: String::new(),
|
||||
asn: Default::default(),
|
||||
r_dns: None,
|
||||
index: 0,
|
||||
is_local: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -73,7 +79,6 @@ pub fn print_gui(&self) -> String {
|
||||
.unwrap()
|
||||
.to_string()
|
||||
.replace('|', "")
|
||||
.add(&*format!(" {} ", &self.country))
|
||||
}
|
||||
|
||||
pub fn get_host(&self) -> Host {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
use crate::networking::types::address_port_pair::AddressPortPair;
|
||||
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::AppProtocol;
|
||||
@@ -38,7 +39,7 @@ pub struct InfoTraffic {
|
||||
/// Map of the application layer protocols with their data info
|
||||
pub app_protocols: HashMap<AppProtocol, DataInfo>,
|
||||
/// Map of the hosts with their data info
|
||||
pub hosts: HashMap<Host, (DataInfo, bool)>,
|
||||
pub hosts: HashMap<Host, DataInfoHost>,
|
||||
}
|
||||
|
||||
impl InfoTraffic {
|
||||
|
||||
@@ -3,11 +3,13 @@
|
||||
pub mod asn;
|
||||
pub mod byte_multiple;
|
||||
pub mod data_info;
|
||||
pub mod data_info_host;
|
||||
pub mod filters;
|
||||
pub mod host;
|
||||
pub mod info_address_port_pair;
|
||||
pub mod info_traffic;
|
||||
pub mod ip_version;
|
||||
pub mod search_parameters;
|
||||
pub mod traffic_direction;
|
||||
pub mod traffic_type;
|
||||
pub mod trans_protocol;
|
||||
|
||||
14
src/networking/types/traffic_direction.rs
Normal file
14
src/networking/types/traffic_direction.rs
Normal file
@@ -0,0 +1,14 @@
|
||||
/// Enum representing the possible traffic direction (incoming or outgoing).
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
pub enum TrafficDirection {
|
||||
/// Incoming traffic (from remote address to local interface)
|
||||
Incoming,
|
||||
/// Outgoing traffic (from local interface to remote address)
|
||||
Outgoing,
|
||||
}
|
||||
|
||||
impl Default for TrafficDirection {
|
||||
fn default() -> Self {
|
||||
Self::Incoming
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,16 @@
|
||||
/// Enum representing the possible traffic type (incoming, outgoing or multicast).
|
||||
/// Enum representing the possible traffic type (unicast, multicast or broadcast).
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
pub enum TrafficType {
|
||||
/// Incoming traffic (from remote address to local interface)
|
||||
Incoming,
|
||||
/// Outgoing traffic (from local interface to remote address)
|
||||
Outgoing,
|
||||
/// Multicast traffic (from remote address to multicast address)
|
||||
/// Unicast traffic
|
||||
Unicast,
|
||||
/// Multicast traffic (destination is a multicast address)
|
||||
Multicast,
|
||||
/// Multicast traffic (from remote address to broadcast address)
|
||||
/// Broadcast traffic (destination is a broadcast address)
|
||||
Broadcast,
|
||||
/// Not identified
|
||||
Other,
|
||||
}
|
||||
|
||||
impl Default for TrafficType {
|
||||
fn default() -> Self {
|
||||
Self::Unicast
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,6 +100,7 @@ pub fn notify_and_log(
|
||||
.push_front(LoggedNotification::FavoriteTransmitted(
|
||||
FavoriteTransmitted {
|
||||
host: host.clone(),
|
||||
data_info_host: info_traffic_lock.hosts.get(host).unwrap().clone(),
|
||||
timestamp: Local::now().to_string().get(11..19).unwrap().to_string(),
|
||||
},
|
||||
));
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::networking::types::data_info_host::DataInfoHost;
|
||||
use crate::networking::types::host::Host;
|
||||
use crate::ByteMultiple;
|
||||
|
||||
@@ -31,5 +32,6 @@ pub struct BytesThresholdExceeded {
|
||||
#[derive(Clone)]
|
||||
pub struct FavoriteTransmitted {
|
||||
pub(crate) host: Host,
|
||||
pub(crate) data_info_host: DataInfoHost,
|
||||
pub(crate) timestamp: String,
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use std::cmp::{min, Ordering};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use crate::networking::types::address_port_pair::AddressPortPair;
|
||||
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::search_parameters::SearchParameters;
|
||||
use crate::{AppProtocol, ChartType, InfoTraffic};
|
||||
@@ -102,13 +102,13 @@ pub fn get_searched_entries(
|
||||
pub fn get_host_entries(
|
||||
info_traffic: &Arc<Mutex<InfoTraffic>>,
|
||||
chart_type: ChartType,
|
||||
) -> Vec<(Host, (DataInfo, bool))> {
|
||||
) -> Vec<(Host, DataInfoHost)> {
|
||||
let info_traffic_lock = info_traffic.lock().unwrap();
|
||||
let mut sorted_vec: Vec<(&Host, &(DataInfo, bool))> = info_traffic_lock.hosts.iter().collect();
|
||||
let mut sorted_vec: Vec<(&Host, &DataInfoHost)> = info_traffic_lock.hosts.iter().collect();
|
||||
|
||||
sorted_vec.sort_by(|&(_, (a, _)), &(_, (b, _))| match chart_type {
|
||||
ChartType::Packets => b.tot_packets().cmp(&a.tot_packets()),
|
||||
ChartType::Bytes => b.tot_bytes().cmp(&a.tot_bytes()),
|
||||
sorted_vec.sort_by(|&(_, a), &(_, b)| match chart_type {
|
||||
ChartType::Packets => b.data_info.tot_packets().cmp(&a.data_info.tot_packets()),
|
||||
ChartType::Bytes => b.data_info.tot_bytes().cmp(&a.data_info.tot_bytes()),
|
||||
});
|
||||
|
||||
let n_entry = min(sorted_vec.len(), 30);
|
||||
|
||||
@@ -8,14 +8,15 @@
|
||||
use pcap::{Active, Capture, Device};
|
||||
|
||||
use crate::networking::manage_packets::{
|
||||
analyze_link_header, analyze_network_header, analyze_transport_header, is_broadcast_address,
|
||||
is_multicast_address, modify_or_insert_in_map, reverse_dns_lookup,
|
||||
analyze_link_header, analyze_network_header, analyze_transport_header, modify_or_insert_in_map,
|
||||
reverse_dns_lookup,
|
||||
};
|
||||
use crate::networking::types::address_port_pair::AddressPortPair;
|
||||
use crate::networking::types::data_info::DataInfo;
|
||||
use crate::networking::types::data_info_host::DataInfoHost;
|
||||
use crate::networking::types::filters::Filters;
|
||||
use crate::networking::types::info_address_port_pair::InfoAddressPortPair;
|
||||
use crate::networking::types::traffic_type::TrafficType;
|
||||
use crate::networking::types::traffic_direction::TrafficDirection;
|
||||
use crate::utils::countries::COUNTRY_MMDB;
|
||||
use crate::{AppProtocol, InfoTraffic, IpVersion, TransProtocol};
|
||||
|
||||
@@ -32,11 +33,6 @@ pub fn parse_packets(
|
||||
) {
|
||||
let capture_id = *current_capture_id.lock().unwrap();
|
||||
|
||||
let mut my_interface_addresses = Vec::new();
|
||||
for address in device.addresses {
|
||||
my_interface_addresses.push(address.addr.to_string());
|
||||
}
|
||||
|
||||
let network_layer_filter = filters.ip;
|
||||
let transport_layer_filter = filters.transport;
|
||||
let app_layer_filter = filters.application;
|
||||
@@ -47,7 +43,6 @@ pub fn parse_packets(
|
||||
let mut network_protocol;
|
||||
let mut transport_protocol;
|
||||
let mut application_protocol;
|
||||
let mut traffic_type;
|
||||
let mut skip_packet;
|
||||
let mut reported_packet;
|
||||
|
||||
@@ -78,7 +73,6 @@ pub fn parse_packets(
|
||||
network_protocol = IpVersion::Other;
|
||||
transport_protocol = TransProtocol::Other;
|
||||
application_protocol = AppProtocol::Other;
|
||||
traffic_type = TrafficType::Other;
|
||||
skip_packet = false;
|
||||
reported_packet = false;
|
||||
|
||||
@@ -116,16 +110,6 @@ pub fn parse_packets(
|
||||
continue;
|
||||
}
|
||||
|
||||
if my_interface_addresses.contains(&address1) {
|
||||
traffic_type = TrafficType::Outgoing;
|
||||
} else if my_interface_addresses.contains(&address2) {
|
||||
traffic_type = TrafficType::Incoming;
|
||||
} else if is_multicast_address(&address2) {
|
||||
traffic_type = TrafficType::Multicast;
|
||||
} else if is_broadcast_address(&address2) {
|
||||
traffic_type = TrafficType::Broadcast;
|
||||
}
|
||||
|
||||
let key: AddressPortPair = AddressPortPair::new(
|
||||
address1.clone(),
|
||||
port1,
|
||||
@@ -145,10 +129,10 @@ pub fn parse_packets(
|
||||
new_info = modify_or_insert_in_map(
|
||||
info_traffic_mutex,
|
||||
key.clone(),
|
||||
&device.addresses,
|
||||
mac_address1,
|
||||
mac_address2,
|
||||
exchanged_bytes,
|
||||
traffic_type,
|
||||
application_protocol,
|
||||
&country_db_reader,
|
||||
&asn_db_reader,
|
||||
@@ -168,7 +152,7 @@ pub fn parse_packets(
|
||||
}
|
||||
|
||||
if reported_packet {
|
||||
if traffic_type == TrafficType::Outgoing {
|
||||
if new_info.traffic_direction == TrafficDirection::Outgoing {
|
||||
//increment number of sent packets and bytes
|
||||
info_traffic.tot_sent_packets += 1;
|
||||
info_traffic.tot_sent_bytes += exchanged_bytes;
|
||||
@@ -201,7 +185,7 @@ pub fn parse_packets(
|
||||
reverse_dns_lookup(
|
||||
info_traffic2,
|
||||
key2,
|
||||
new_info.traffic_type,
|
||||
new_info.traffic_direction,
|
||||
);
|
||||
})
|
||||
.unwrap();
|
||||
@@ -216,38 +200,48 @@ pub fn parse_packets(
|
||||
info_traffic
|
||||
.hosts
|
||||
.entry(new_info.get_host())
|
||||
.and_modify(|(data_info, _)| {
|
||||
if traffic_type == TrafficType::Outgoing {
|
||||
data_info.outgoing_packets += 1;
|
||||
data_info.outgoing_bytes += exchanged_bytes;
|
||||
.and_modify(|data_info_host| {
|
||||
if new_info.traffic_direction
|
||||
== TrafficDirection::Outgoing
|
||||
{
|
||||
data_info_host.data_info.outgoing_packets += 1;
|
||||
data_info_host.data_info.outgoing_bytes +=
|
||||
exchanged_bytes;
|
||||
} else {
|
||||
data_info.incoming_packets += 1;
|
||||
data_info.incoming_bytes += exchanged_bytes;
|
||||
data_info_host.data_info.incoming_packets += 1;
|
||||
data_info_host.data_info.incoming_bytes +=
|
||||
exchanged_bytes;
|
||||
}
|
||||
})
|
||||
.or_insert(
|
||||
if new_info.traffic_type == TrafficType::Outgoing {
|
||||
(
|
||||
DataInfo {
|
||||
if new_info.traffic_direction
|
||||
== TrafficDirection::Outgoing
|
||||
{
|
||||
DataInfoHost {
|
||||
data_info: DataInfo {
|
||||
incoming_packets: 0,
|
||||
outgoing_packets: new_info
|
||||
.transmitted_packets,
|
||||
incoming_bytes: 0,
|
||||
outgoing_bytes: new_info.transmitted_bytes,
|
||||
},
|
||||
false,
|
||||
)
|
||||
is_favorite: false,
|
||||
is_local: new_info.is_local,
|
||||
traffic_type: new_info.traffic_type,
|
||||
}
|
||||
} else {
|
||||
(
|
||||
DataInfo {
|
||||
DataInfoHost {
|
||||
data_info: DataInfo {
|
||||
incoming_packets: new_info
|
||||
.transmitted_packets,
|
||||
outgoing_packets: 0,
|
||||
incoming_bytes: new_info.transmitted_bytes,
|
||||
outgoing_bytes: 0,
|
||||
},
|
||||
false,
|
||||
)
|
||||
is_favorite: false,
|
||||
is_local: new_info.is_local,
|
||||
traffic_type: new_info.traffic_type,
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -258,7 +252,7 @@ pub fn parse_packets(
|
||||
.app_protocols
|
||||
.entry(application_protocol)
|
||||
.and_modify(|data_info| {
|
||||
if traffic_type == TrafficType::Outgoing {
|
||||
if new_info.traffic_direction == TrafficDirection::Outgoing {
|
||||
data_info.outgoing_packets += 1;
|
||||
data_info.outgoing_bytes += exchanged_bytes;
|
||||
} else {
|
||||
@@ -266,21 +260,23 @@ pub fn parse_packets(
|
||||
data_info.incoming_bytes += exchanged_bytes;
|
||||
}
|
||||
})
|
||||
.or_insert(if traffic_type == TrafficType::Outgoing {
|
||||
DataInfo {
|
||||
incoming_packets: 0,
|
||||
outgoing_packets: 1,
|
||||
incoming_bytes: 0,
|
||||
outgoing_bytes: exchanged_bytes,
|
||||
}
|
||||
} else {
|
||||
DataInfo {
|
||||
incoming_packets: 1,
|
||||
outgoing_packets: 0,
|
||||
incoming_bytes: exchanged_bytes,
|
||||
outgoing_bytes: 0,
|
||||
}
|
||||
});
|
||||
.or_insert(
|
||||
if new_info.traffic_direction == TrafficDirection::Outgoing {
|
||||
DataInfo {
|
||||
incoming_packets: 0,
|
||||
outgoing_packets: 1,
|
||||
incoming_bytes: 0,
|
||||
outgoing_bytes: exchanged_bytes,
|
||||
}
|
||||
} else {
|
||||
DataInfo {
|
||||
incoming_packets: 1,
|
||||
outgoing_packets: 0,
|
||||
incoming_bytes: exchanged_bytes,
|
||||
outgoing_bytes: 0,
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,10 +67,28 @@ pub fn host_translation(language: Language) -> &'static str {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn only_top_30_hosts(language: Language) -> &'static str {
|
||||
pub fn only_top_30_hosts_translation(language: Language) -> &'static str {
|
||||
match language {
|
||||
Language::EN => "Only the top 30 hosts are displayed here",
|
||||
Language::IT => "Solo i maggiori 30 host sono mostrati qui",
|
||||
_ => "Only the top 30 hosts are displayed here",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn local_translation(language: Language) -> String {
|
||||
match language {
|
||||
Language::EN => "Local",
|
||||
Language::IT => "Locale",
|
||||
_ => "Local",
|
||||
}
|
||||
.to_string()
|
||||
}
|
||||
|
||||
pub fn unknown_translation(language: Language) -> String {
|
||||
match language {
|
||||
Language::EN => "Unknown",
|
||||
Language::IT => "Sconosciuto",
|
||||
_ => "Unknown",
|
||||
}
|
||||
.to_string()
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
use crate::networking::types::address_port_pair::AddressPortPair;
|
||||
use crate::networking::types::asn::Asn;
|
||||
use crate::networking::types::traffic_type::TrafficType;
|
||||
use crate::networking::types::traffic_direction::TrafficDirection;
|
||||
use maxminddb::{geoip2, MaxMindDBError, Reader};
|
||||
|
||||
pub const ASN_MMDB: &[u8] = include_bytes!("../../resources/DB/GeoLite2-ASN.mmdb");
|
||||
|
||||
pub fn get_asn(
|
||||
traffic_type: TrafficType,
|
||||
traffic_direction: TrafficDirection,
|
||||
key: &AddressPortPair,
|
||||
asn_db_reader: &Reader<&[u8]>,
|
||||
) -> Asn {
|
||||
let address_to_lookup = match traffic_type {
|
||||
TrafficType::Outgoing => &key.address2,
|
||||
let address_to_lookup = match traffic_direction {
|
||||
TrafficDirection::Outgoing => &key.address2,
|
||||
_ => &key.address1,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,19 +1,26 @@
|
||||
use iced::widget::{svg::Handle, Svg};
|
||||
use crate::gui::styles::types::element_type::ElementType;
|
||||
use crate::gui::styles::types::style_tuple::StyleTuple;
|
||||
use crate::gui::types::message::Message;
|
||||
use crate::{Language, StyleType};
|
||||
use iced::widget::{svg::Handle, Svg, Tooltip};
|
||||
use iced::{Length, Renderer};
|
||||
use iced_native::widget::tooltip::Position;
|
||||
use maxminddb::{geoip2, MaxMindDBError, Reader};
|
||||
|
||||
use crate::networking::types::address_port_pair::AddressPortPair;
|
||||
use crate::networking::types::traffic_direction::TrafficDirection;
|
||||
use crate::networking::types::traffic_type::TrafficType;
|
||||
use crate::translations::translations_2::{local_translation, unknown_translation};
|
||||
|
||||
pub const COUNTRY_MMDB: &[u8] = include_bytes!("../../resources/DB/GeoLite2-Country.mmdb");
|
||||
|
||||
pub fn get_country_code(
|
||||
traffic_type: TrafficType,
|
||||
traffic_direction: TrafficDirection,
|
||||
key: &AddressPortPair,
|
||||
country_db_reader: &Reader<&[u8]>,
|
||||
) -> String {
|
||||
let address_to_lookup = match traffic_type {
|
||||
TrafficType::Outgoing => &key.address2,
|
||||
let address_to_lookup = match traffic_direction {
|
||||
TrafficDirection::Outgoing => &key.address2,
|
||||
_ => &key.address1,
|
||||
};
|
||||
|
||||
@@ -29,7 +36,7 @@ pub fn get_country_code(
|
||||
String::new()
|
||||
}
|
||||
|
||||
pub const FLAGS_WIDTH_SMALL: f32 = 15.0;
|
||||
pub const FLAGS_WIDTH_SMALL: f32 = 20.0;
|
||||
pub const FLAGS_WIDTH_BIG: f32 = 37.5;
|
||||
|
||||
pub const AD: &[u8] = include_bytes!("../../resources/countries_flags/4x3/ad.svg");
|
||||
@@ -281,8 +288,10 @@ pub fn get_country_code(
|
||||
pub const ZA: &[u8] = include_bytes!("../../resources/countries_flags/4x3/za.svg");
|
||||
pub const ZM: &[u8] = include_bytes!("../../resources/countries_flags/4x3/zm.svg");
|
||||
pub const ZW: &[u8] = include_bytes!("../../resources/countries_flags/4x3/zw.svg");
|
||||
pub const UNKNOWN: &[u8] =
|
||||
include_bytes!("../../resources/countries_flags/4x3/question-mark-svgrepo-com.svg");
|
||||
pub const HOME: &[u8] = include_bytes!("../../resources/countries_flags/4x3/zz-home.svg");
|
||||
pub const MULTICAST: &[u8] = include_bytes!("../../resources/countries_flags/4x3/zz-multicast.svg");
|
||||
pub const BROADCAST: &[u8] = include_bytes!("../../resources/countries_flags/4x3/zz-broadcast.svg");
|
||||
pub const UNKNOWN: &[u8] = include_bytes!("../../resources/countries_flags/4x3/zz-unknown.svg");
|
||||
|
||||
pub fn get_flag_from_language_code(language: &str) -> Svg<Renderer> {
|
||||
Svg::new(Handle::from_memory(Vec::from(match language {
|
||||
@@ -306,9 +315,16 @@ pub fn get_flag_from_language_code(language: &str) -> Svg<Renderer> {
|
||||
.width(Length::Fixed(FLAGS_WIDTH_SMALL))
|
||||
}
|
||||
|
||||
pub fn get_flag_from_country_code(country: &str, width: f32) -> Svg<Renderer> {
|
||||
fn get_flag_from_country_code(
|
||||
country: &str,
|
||||
width: f32,
|
||||
is_local: bool,
|
||||
traffic_type: TrafficType,
|
||||
language: Language,
|
||||
) -> (Svg<Renderer>, String) {
|
||||
#![allow(clippy::too_many_lines)]
|
||||
Svg::new(Handle::from_memory(Vec::from(match country {
|
||||
let mut tooltip = country.to_string();
|
||||
let svg = Svg::new(Handle::from_memory(Vec::from(match country {
|
||||
"AD" => AD,
|
||||
"AE" => AE,
|
||||
"AF" => AF,
|
||||
@@ -558,7 +574,49 @@ pub fn get_flag_from_country_code(country: &str, width: f32) -> Svg<Renderer> {
|
||||
"ZA" => ZA,
|
||||
"ZM" => ZM,
|
||||
"ZW" => ZW,
|
||||
_ => UNKNOWN,
|
||||
_ => {
|
||||
if is_local {
|
||||
tooltip = local_translation(language);
|
||||
HOME
|
||||
} else if traffic_type.eq(&TrafficType::Multicast) {
|
||||
tooltip = "Multicast".to_string();
|
||||
MULTICAST
|
||||
} else if traffic_type.eq(&TrafficType::Broadcast) {
|
||||
tooltip = "Broadcast".to_string();
|
||||
BROADCAST
|
||||
} else {
|
||||
tooltip = unknown_translation(language);
|
||||
UNKNOWN
|
||||
}
|
||||
}
|
||||
})))
|
||||
.width(Length::Fixed(width))
|
||||
.height(Length::Fixed(width * 0.75));
|
||||
|
||||
(svg, tooltip)
|
||||
}
|
||||
|
||||
pub fn get_flag_tooltip(
|
||||
country: &str,
|
||||
width: f32,
|
||||
is_local: bool,
|
||||
traffic_type: TrafficType,
|
||||
language: Language,
|
||||
style: StyleType,
|
||||
) -> Tooltip<'static, Message> {
|
||||
let (content, tooltip) =
|
||||
get_flag_from_country_code(country, width, is_local, traffic_type, language);
|
||||
let mut position = Position::FollowCursor;
|
||||
let mut snap = true;
|
||||
|
||||
if width == FLAGS_WIDTH_SMALL {
|
||||
position = Position::Right;
|
||||
snap = false;
|
||||
}
|
||||
|
||||
Tooltip::new(content, tooltip, position)
|
||||
.snap_within_viewport(snap)
|
||||
.style(<StyleTuple as Into<iced::theme::Container>>::into(
|
||||
StyleTuple(style, ElementType::Tooltip),
|
||||
))
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
use iced::Color;
|
||||
|
||||
use crate::networking::types::filters::Filters;
|
||||
use crate::networking::types::traffic_type::TrafficType;
|
||||
use crate::networking::types::traffic_direction::TrafficDirection;
|
||||
use crate::translations::translations::{
|
||||
active_filters_translation, none_translation, open_report_translation,
|
||||
};
|
||||
@@ -55,8 +55,8 @@ pub fn get_active_filters_string(filters: &Filters, language: Language) -> Strin
|
||||
}
|
||||
|
||||
/// Returns the color to be used for a specific connection of the relevant connections table in gui run page
|
||||
pub fn get_connection_color(traffic_type: TrafficType, style: StyleType) -> Color {
|
||||
if traffic_type == TrafficType::Outgoing {
|
||||
pub fn get_connection_color(traffic_direction: TrafficDirection, style: StyleType) -> Color {
|
||||
if traffic_direction == TrafficDirection::Outgoing {
|
||||
get_colors(style).outgoing
|
||||
} else {
|
||||
get_colors(style).incoming
|
||||
|
||||
Reference in New Issue
Block a user