mirror of
https://github.com/GyulyVGC/sniffnet.git
synced 2025-12-23 22:29:01 -05:00
add checkbox for setting capture filters
This commit is contained in:
@@ -4,15 +4,6 @@
|
||||
|
||||
use std::fmt::Write;
|
||||
|
||||
use iced::Length::FillPortion;
|
||||
use iced::widget::scrollable::Direction;
|
||||
use iced::widget::tooltip::Position;
|
||||
use iced::widget::{
|
||||
Button, Checkbox, Column, Container, Row, Rule, Scrollable, Space, Text, TextInput, Tooltip,
|
||||
button, center,
|
||||
};
|
||||
use iced::{Alignment, Font, Length, Padding, alignment};
|
||||
|
||||
use crate::gui::components::button::button_open_file;
|
||||
use crate::gui::sniffer::Sniffer;
|
||||
use crate::gui::styles::button::ButtonType;
|
||||
@@ -20,9 +11,9 @@
|
||||
use crate::gui::styles::scrollbar::ScrollbarType;
|
||||
use crate::gui::styles::style_constants::{FONT_SIZE_SUBTITLE, FONT_SIZE_TITLE};
|
||||
use crate::gui::styles::text::TextType;
|
||||
use crate::gui::styles::text_input::TextInputType;
|
||||
use crate::gui::styles::types::gradient_type::GradientType;
|
||||
use crate::gui::types::export_pcap::ExportPcap;
|
||||
use crate::gui::types::filters::Filters;
|
||||
use crate::gui::types::message::Message;
|
||||
use crate::networking::types::capture_context::CaptureSource;
|
||||
use crate::translations::translations::{
|
||||
@@ -33,10 +24,19 @@
|
||||
directory_translation, export_capture_translation, file_name_translation,
|
||||
};
|
||||
use crate::translations::translations_4::import_capture_translation;
|
||||
use crate::translations::translations_5::filter_traffic_translation;
|
||||
use crate::utils::formatted_strings::get_path_termination_string;
|
||||
use crate::utils::types::file_info::FileInfo;
|
||||
use crate::utils::types::icon::Icon;
|
||||
use crate::{ConfigSettings, Language, StyleType};
|
||||
use iced::Length::FillPortion;
|
||||
use iced::widget::scrollable::Direction;
|
||||
use iced::widget::tooltip::Position;
|
||||
use iced::widget::{
|
||||
Button, Checkbox, Column, Container, Row, Rule, Scrollable, Space, Text, TextInput, Tooltip,
|
||||
button, center,
|
||||
};
|
||||
use iced::{Alignment, Font, Length, Padding, alignment};
|
||||
|
||||
/// Computes the body of gui initial page
|
||||
pub fn initial_page(sniffer: &Sniffer) -> Container<'_, Message, StyleType> {
|
||||
@@ -57,8 +57,6 @@ pub fn initial_page(sniffer: &Sniffer) -> Container<'_, Message, StyleType> {
|
||||
);
|
||||
let col_capture_source = Column::new().push(col_adapter).push(col_import_pcap);
|
||||
|
||||
let col_bpf_filter = col_bpf_input(&sniffer.bpf_filter, font);
|
||||
|
||||
let filters_pane = Column::new()
|
||||
.width(FillPortion(6))
|
||||
.padding(10)
|
||||
@@ -69,7 +67,7 @@ pub fn initial_page(sniffer: &Sniffer) -> Container<'_, Message, StyleType> {
|
||||
.class(TextType::Title)
|
||||
.size(FONT_SIZE_TITLE),
|
||||
)
|
||||
.push(col_bpf_filter)
|
||||
.push(get_filters_group(&sniffer.filters, font, language))
|
||||
.push(Rule::horizontal(40))
|
||||
.push(get_export_pcap_group(
|
||||
&sniffer.capture_source,
|
||||
@@ -95,27 +93,6 @@ pub fn initial_page(sniffer: &Sniffer) -> Container<'_, Message, StyleType> {
|
||||
Container::new(body).height(Length::Fill)
|
||||
}
|
||||
|
||||
fn col_bpf_input(value: &str, font: Font) -> Column<'_, Message, StyleType> {
|
||||
let input_row = Row::new().padding(Padding::ZERO.left(5)).push(
|
||||
TextInput::new("Berkeley Packet Filter (BPF)", value)
|
||||
.padding([3, 5])
|
||||
.on_input(Message::BpfFilter)
|
||||
.font(font)
|
||||
.class(TextInputType::Standard),
|
||||
);
|
||||
|
||||
Column::new()
|
||||
.width(Length::Fill)
|
||||
.spacing(7)
|
||||
.push(
|
||||
Text::new("Berkeley Packet Filter (BPF)")
|
||||
.font(font)
|
||||
.class(TextType::Subtitle)
|
||||
.size(FONT_SIZE_SUBTITLE),
|
||||
)
|
||||
.push(input_row)
|
||||
}
|
||||
|
||||
fn button_start<'a>(
|
||||
font: Font,
|
||||
language: Language,
|
||||
@@ -298,6 +275,50 @@ fn get_col_import_pcap<'a>(
|
||||
.push(button)
|
||||
}
|
||||
|
||||
fn get_filters_group<'a>(
|
||||
filters: &Filters,
|
||||
font: Font,
|
||||
language: Language,
|
||||
) -> Container<'a, Message, StyleType> {
|
||||
let expanded = filters.expanded();
|
||||
let bpf = filters.bpf();
|
||||
|
||||
let caption = filter_traffic_translation(language);
|
||||
let checkbox = Checkbox::new(caption, expanded)
|
||||
.on_toggle(move |_| Message::ToggleFilters)
|
||||
.size(18)
|
||||
.font(font);
|
||||
|
||||
let mut ret_val = Column::new().spacing(10).push(checkbox);
|
||||
|
||||
if expanded {
|
||||
let input = TextInput::new("", bpf)
|
||||
.on_input(Message::BpfFilter)
|
||||
.padding([2, 5])
|
||||
.font(font);
|
||||
let inner_col = Column::new()
|
||||
.spacing(10)
|
||||
.padding(Padding::ZERO.left(45))
|
||||
.push(
|
||||
Row::new()
|
||||
.align_y(Alignment::Center)
|
||||
.spacing(5)
|
||||
.push(Text::new("BPF:").font(font))
|
||||
.push(input),
|
||||
);
|
||||
ret_val = ret_val.push(inner_col);
|
||||
}
|
||||
|
||||
Container::new(
|
||||
Container::new(ret_val)
|
||||
.padding(10)
|
||||
.width(Length::Fill)
|
||||
.class(ContainerType::BorderedRound),
|
||||
)
|
||||
.height(Length::Fill)
|
||||
.align_y(Alignment::Start)
|
||||
}
|
||||
|
||||
fn get_export_pcap_group<'a>(
|
||||
cs: &CaptureSource,
|
||||
export_pcap: &ExportPcap,
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
use crate::gui::styles::types::custom_palette::{CustomPalette, ExtraStyles};
|
||||
use crate::gui::styles::types::palette::Palette;
|
||||
use crate::gui::types::export_pcap::ExportPcap;
|
||||
use crate::gui::types::filters::Filters;
|
||||
use crate::gui::types::message::Message;
|
||||
use crate::gui::types::timing_events::TimingEvents;
|
||||
use crate::mmdb::asn::ASN_MMDB;
|
||||
@@ -92,7 +93,7 @@ pub struct Sniffer {
|
||||
/// List of network devices
|
||||
pub my_devices: Vec<MyDevice>,
|
||||
/// BPF filter program to be applied to the capture
|
||||
pub bpf_filter: String,
|
||||
pub filters: Filters,
|
||||
/// Signals if a pcap error occurred
|
||||
pub pcap_error: Option<String>,
|
||||
/// Messages status
|
||||
@@ -155,7 +156,7 @@ pub fn new(configs: Configs) -> Self {
|
||||
newer_release_available: None,
|
||||
capture_source: CaptureSource::Device(device),
|
||||
my_devices: Vec::new(),
|
||||
bpf_filter: String::new(),
|
||||
filters: Filters::default(),
|
||||
pcap_error: None,
|
||||
dots_pulse: (".".to_string(), 0),
|
||||
traffic_chart: TrafficChart::new(style, language),
|
||||
@@ -276,8 +277,11 @@ pub fn update(&mut self, message: Message) -> Task<Message> {
|
||||
}
|
||||
}
|
||||
Message::DeviceSelection(name) => self.set_device(&name),
|
||||
Message::ToggleFilters => {
|
||||
self.filters.toggle();
|
||||
}
|
||||
Message::BpfFilter(value) => {
|
||||
self.bpf_filter = value;
|
||||
self.filters.set_bpf(value);
|
||||
}
|
||||
Message::DataReprSelection(unit) => self.traffic_chart.change_kind(unit),
|
||||
Message::ReportSortSelection(sort) => {
|
||||
@@ -716,7 +720,7 @@ fn start(&mut self) -> Task<Message> {
|
||||
}
|
||||
let pcap_path = self.export_pcap.full_path();
|
||||
let capture_context =
|
||||
CaptureContext::new(&self.capture_source, pcap_path.as_ref(), &self.bpf_filter);
|
||||
CaptureContext::new(&self.capture_source, pcap_path.as_ref(), &self.filters);
|
||||
self.pcap_error = capture_context.error().map(ToString::to_string);
|
||||
self.running_page = RunningPage::Overview;
|
||||
|
||||
|
||||
84
src/gui/types/filters.rs
Normal file
84
src/gui/types/filters.rs
Normal file
@@ -0,0 +1,84 @@
|
||||
#[derive(Default)]
|
||||
pub struct Filters {
|
||||
expanded: bool,
|
||||
bpf: String,
|
||||
}
|
||||
|
||||
impl Filters {
|
||||
pub fn toggle(&mut self) {
|
||||
self.expanded = !self.expanded;
|
||||
}
|
||||
|
||||
pub fn set_bpf(&mut self, bpf: String) {
|
||||
self.bpf = bpf;
|
||||
}
|
||||
|
||||
pub fn expanded(&self) -> bool {
|
||||
self.expanded
|
||||
}
|
||||
|
||||
pub fn bpf(&self) -> &str {
|
||||
&self.bpf
|
||||
}
|
||||
|
||||
pub fn is_some_filter_active(&self) -> bool {
|
||||
self.expanded && !self.bpf.trim().is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_default() {
|
||||
let filters = Filters::default();
|
||||
assert_eq!(filters.expanded(), false);
|
||||
assert_eq!(filters.bpf(), "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_toggle() {
|
||||
let mut filters = Filters::default();
|
||||
assert_eq!(filters.expanded(), false);
|
||||
|
||||
filters.toggle();
|
||||
assert_eq!(filters.expanded(), true);
|
||||
|
||||
filters.toggle();
|
||||
assert_eq!(filters.expanded(), false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_bpf() {
|
||||
let mut filters = Filters::default();
|
||||
assert_eq!(filters.bpf(), "");
|
||||
|
||||
filters.set_bpf("tcp port 80".to_string());
|
||||
assert_eq!(filters.bpf(), "tcp port 80");
|
||||
|
||||
filters.set_bpf(" udp port 53 ".to_string());
|
||||
assert_eq!(filters.bpf(), " udp port 53 ");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_some_filter_active() {
|
||||
let mut filters = Filters::default();
|
||||
assert_eq!(filters.is_some_filter_active(), false);
|
||||
|
||||
filters.toggle();
|
||||
assert_eq!(filters.is_some_filter_active(), false);
|
||||
|
||||
filters.set_bpf("tcp port 80".to_string());
|
||||
assert_eq!(filters.is_some_filter_active(), true);
|
||||
|
||||
filters.toggle();
|
||||
assert_eq!(filters.is_some_filter_active(), false);
|
||||
|
||||
filters.toggle();
|
||||
assert_eq!(filters.is_some_filter_active(), true);
|
||||
|
||||
filters.set_bpf(" \t \n ".to_string());
|
||||
assert_eq!(filters.is_some_filter_active(), false);
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,9 @@ pub enum Message {
|
||||
TickRun(usize, InfoTraffic, Vec<HostMessage>, bool),
|
||||
/// Select network device
|
||||
DeviceSelection(String),
|
||||
/// Changed BPF filter
|
||||
/// Toggle BPF filter checkbox
|
||||
ToggleFilters,
|
||||
/// Change BPF filter string
|
||||
BpfFilter(String),
|
||||
/// Select data representation to use
|
||||
DataReprSelection(DataRepr),
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
pub mod export_pcap;
|
||||
pub mod filters;
|
||||
pub mod message;
|
||||
pub mod timing_events;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use pcap::{Active, Address, Capture, Error, Packet, Savefile, Stat};
|
||||
|
||||
use crate::gui::types::filters::Filters;
|
||||
use crate::networking::types::my_device::MyDevice;
|
||||
use crate::networking::types::my_link_type::MyLinkType;
|
||||
use crate::translations::translations::network_adapter_translation;
|
||||
use crate::translations::translations_3::file_name_translation;
|
||||
use crate::translations::types::language::Language;
|
||||
use pcap::{Active, Address, Capture, Error, Packet, Savefile, Stat};
|
||||
|
||||
pub enum CaptureContext {
|
||||
Live(Live),
|
||||
@@ -14,13 +14,16 @@ pub enum CaptureContext {
|
||||
}
|
||||
|
||||
impl CaptureContext {
|
||||
pub fn new(source: &CaptureSource, pcap_out_path: Option<&String>, bpf: &str) -> Self {
|
||||
pub fn new(source: &CaptureSource, pcap_out_path: Option<&String>, filters: &Filters) -> Self {
|
||||
let mut cap_type = match CaptureType::from_source(source, pcap_out_path) {
|
||||
Ok(c) => c,
|
||||
Err(e) => return Self::Error(e.to_string()),
|
||||
};
|
||||
|
||||
if let Err(e) = cap_type.set_bpf(bpf) {
|
||||
// only apply BPF filter if it is active, and return an error if it fails to apply
|
||||
if filters.is_some_filter_active()
|
||||
&& let Err(e) = cap_type.set_bpf(filters.bpf())
|
||||
{
|
||||
return Self::Error(e.to_string());
|
||||
}
|
||||
|
||||
|
||||
@@ -3,4 +3,5 @@
|
||||
pub mod translations_2;
|
||||
pub mod translations_3;
|
||||
pub mod translations_4;
|
||||
pub mod translations_5;
|
||||
pub mod types;
|
||||
|
||||
12
src/translations/translations_5.rs
Normal file
12
src/translations/translations_5.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
#![allow(clippy::match_same_arms)]
|
||||
|
||||
use crate::translations::types::language::Language;
|
||||
|
||||
pub fn filter_traffic_translation(language: Language) -> String {
|
||||
match language {
|
||||
Language::EN => "Filter traffic",
|
||||
Language::IT => "Filtra il traffico",
|
||||
_ => "Filter traffic",
|
||||
}
|
||||
.to_string()
|
||||
}
|
||||
Reference in New Issue
Block a user