diff --git a/README.md b/README.md index 6a839616..b8494da0 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,9 @@ Sniffnet generates a graphical representation of the filtered traffic's intensit - [Graphical report structure](#graphical-report-structure) -- [Textual report structure](#textual-report-structure) +- [Textual report structure (concise mode)](#textual-report-structure-(concise-mode)) + +- [Textual report structure (verbose mode)](#textual-report-structure-(verbose-mode)) - [Supported application layer protocols](#supported-application-layer-protocols) @@ -101,6 +103,9 @@ specifies the name of the output folder to contain textual and graphical reports - **-t, --trans**: filters packets on the basis of the provided transport layer protocol (TCP or UDP). +- **-v, --verbose**: +generates a more self-explainable textual report, as the one shown in the pictures above. + ## User interactions during application execution @@ -133,15 +138,33 @@ in case of intermittent traffic, you can consider using a lower time interval. -## Textual report structure +## Textual report structure (concise mode)
See details +By default, the report is represented in the form of a textual csv file containing the traffic statistics. + +Each line of the report is relative to one single [address:port] pair. + + + +If you would like to see a more formatted and aesthetically pleasing textual report, use the option `-v` (see next section). + +
+ +## Textual report structure (verbose mode) + +
+ + See details + +This textual representation can be activated launching the application with the `-v` option. + ### Report header -The first section of the textual report contains a header summarizing different useful information. +The first section of the verbose textual report contains a header summarizing different useful information. ![report_part_1](https://user-images.githubusercontent.com/100347457/187227230-b7984a13-d9df-4852-9b8d-e295cd7cfa35.png) @@ -161,7 +184,7 @@ observed application layer protocols with the respective packets count. ### Report addresses list -The second section of the textual report is dedicated to the packets stream analysis for each [address:port] pair. +The second section of the verbose textual report is dedicated to the packets stream analysis for each [address:port] pair. This analysis results in a list in which each element represents an [address:port] pair with the relative statistics. diff --git a/src/args.rs b/src/args.rs index 2efefd98..2dcb5122 100644 --- a/src/args.rs +++ b/src/args.rs @@ -18,6 +18,12 @@ pub struct Args { #[clap(long="app", value_parser, default_value = "no filter")] pub application_layer_filter: String, + /// Prints textual report with a verbose format. + /// + /// This option does not need to be followed by a value. + #[clap(short, long)] + pub verbose: bool, + /// Prints list of the available network interfaces. /// /// Immediately terminates the program. diff --git a/src/main.rs b/src/main.rs index 7d02345d..3f88f008 100644 --- a/src/main.rs +++ b/src/main.rs @@ -57,6 +57,7 @@ fn main() { // parse arguments let args = Args::parse(); let mut adapter: String = args.adapter; + let verbose: bool = args.verbose; let output_folder: String = args.output_folder; let lowest_port = args.lowest_port; let highest_port = args.highest_port; @@ -143,7 +144,7 @@ fn main() { // Thread 1: updates textual report let thread_write_report = thread::spawn(move || { - sleep_and_write_report_loop(lowest_port, highest_port, interval, min_packets, + sleep_and_write_report_loop(verbose,lowest_port, highest_port, interval, min_packets, device_name, network_layer, transport_layer, app_layer.unwrap(), output_folder, mutex_map2, status_pair3); diff --git a/src/thread_write_report_functions.rs b/src/thread_write_report_functions.rs index 0f23eae3..0c807b5a 100644 --- a/src/thread_write_report_functions.rs +++ b/src/thread_write_report_functions.rs @@ -27,6 +27,9 @@ use plotters::style::full_palette::{GREEN_800, GREY}; /// /// # Arguments /// +/// /// * `verbose` - Flag: if true textual report is verbose. +/// Specified by the user through the ```-v``` option. +/// /// * `lowest_port` - The lowest port number to be considered in the report. Specified by the user /// through the ```-l``` option. /// @@ -57,7 +60,7 @@ use plotters::style::full_palette::{GREEN_800, GREY}; /// * `info_traffic_mutex` - Struct with all the relevant info on the network traffic analyzed. /// /// * `status_pair` - Shared variable to check the application current status. -pub fn sleep_and_write_report_loop(lowest_port: u16, highest_port: u16, interval: u64, min_packets: u128, +pub fn sleep_and_write_report_loop(verbose: bool, lowest_port: u16, highest_port: u16, interval: u64, min_packets: u128, device_name: String, network_layer: String, transport_layer: String, app_layer: AppProtocol, output_folder: String, info_traffic_mutex: Arc>, status_pair: Arc<(Mutex, Condvar)>) { @@ -118,12 +121,18 @@ pub fn sleep_and_write_report_loop(lowest_port: u16, highest_port: u16, interval let mut output = BufWriter::new(File::create(text_path.clone()).expect("Error creating output file\n\r")); - write_report_file_header(output.get_mut().try_clone().expect("Error cloning file handler\n\r"), - device_name.clone(), first_timestamp.clone(), - lowest_port, highest_port, min_packets, - network_layer.clone(), transport_layer.clone(), app_layer, - info_traffic.map.len(), all_packets, - tot_received_packets+tot_sent_packets, info_traffic.app_protocols.clone()); + if !verbose { + write!(output, "To see a better formatted textual report, launch sniffnet with the '-v' option\n\n").expect("Error writing output file\n\r"); + writeln!(output,"IP_src, port_src, IP_dest, port_dest, packets, bytes, layer4, layer7, first_timestamp, last_timestamp").expect("Error writing output file\n\r"); + } + else { + write_report_file_header(output.get_mut().try_clone().expect("Error cloning file handler\n\r"), + device_name.clone(), first_timestamp.clone(), + lowest_port, highest_port, min_packets, + network_layer.clone(), transport_layer.clone(), app_layer, + info_traffic.map.len(), all_packets, + tot_received_packets+tot_sent_packets, info_traffic.app_protocols.clone()); + } _time_header = start.elapsed().as_millis(); @@ -135,7 +144,16 @@ pub fn sleep_and_write_report_loop(lowest_port: u16, highest_port: u16, interval for (key, val) in sorted_vec.iter() { if val.transmitted_packets >= min_packets { - write!(output, "{}\n{}\n\n", key, val).expect("Error writing output file\n\r"); + if !verbose { // concise + write!(output, "{}, {}, {}, {}, {}, {}, {:?}, {:?}, {}, {}\n", + key.address1, key.port1, key.address2, key.port2, + val.transmitted_packets, val.transmitted_bytes, + val.trans_protocols, val.app_protocol, + val.initial_timestamp, val.final_timestamp).expect("Error writing output file\n\r"); + } + else { // verbose + write!(output, "{}\n{}\n\n", key, val).expect("Error writing output file\n\r"); + } } } @@ -309,7 +327,7 @@ pub fn sleep_and_write_report_loop(lowest_port: u16, highest_port: u16, interval // use crate::{AppProtocol, TransProtocol}; // // #[bench] -// fn bench_print_one_report_entry(b: &mut Bencher) { +// fn bench_print_verbose(b: &mut Bencher) { // let mut bench_vec: Vec<(&AddressPortPair, &InfoAddressPortPair)> = vec![]; // let key = AddressPortPair::new // ("255.255.255.255".to_string(), @@ -339,6 +357,42 @@ pub fn sleep_and_write_report_loop(lowest_port: u16, highest_port: u16, interval // bench_output.flush().unwrap(); // }); // } +// +// #[bench] +// fn bench_print_concise(b: &mut Bencher) { +// let mut bench_vec: Vec<(&AddressPortPair, &InfoAddressPortPair)> = vec![]; +// let key = AddressPortPair::new +// ("255.255.255.255".to_string(), +// 443, +// "245.78.32.123".to_string(), +// 40900, +// TrafficType::Outgoing +// ); +// let now_ugly: DateTime = Local::now(); +// let now = now_ugly.format("%d/%m/%Y %H:%M:%S").to_string(); +// let val = InfoAddressPortPair { +// transmitted_bytes: 5002222896, +// transmitted_packets: 89394742, +// initial_timestamp: now.clone(), +// final_timestamp: now.clone(), +// trans_protocols: HashSet::from([TransProtocol::TCP]), +// app_protocol: AppProtocol::HTTPS +// }; +// for _ in 0..3500 { +// bench_vec.push((&key, &val)); +// } +// let mut bench_output = BufWriter::new(File::create("bench.txt").expect("Error creating output file\n\r")); +// b.iter(|| { +// for (key, val) in bench_vec.iter() { +// write!(bench_output, "{}, {}, {}, {}, {}, {}, {:?}, {:?}, {}, {}\n", +// key.address1, key.port1, key.address2, key.port2, +// val.transmitted_packets, val.transmitted_bytes, +// val.trans_protocols, val.app_protocol, +// val.initial_timestamp, val.final_timestamp).expect("Error writing output file\n\r"); +// } +// bench_output.flush().unwrap(); +// }); +// } // }