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.

@@ -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();
+// });
+// }
// }