From 6bd5160d5631e8c847dc84fa5da592d4dee80d2d Mon Sep 17 00:00:00 2001 From: Giuliano Bellini s294739 Date: Fri, 19 Aug 2022 00:20:29 +0200 Subject: [PATCH] added function to parse IPv6 addresses and relative tests --- src/address_port.rs | 9 +- src/thread_parse_packets_functions.rs | 203 ++++++++++++++++++++++++-- 2 files changed, 201 insertions(+), 11 deletions(-) diff --git a/src/address_port.rs b/src/address_port.rs index 870d9781..69782d89 100644 --- a/src/address_port.rs +++ b/src/address_port.rs @@ -43,8 +43,15 @@ impl fmt::Display for AddressPort { "".to_string() }; - write!(f, "{}:{}{}", self.address, self.port, my_interface_string) + let display_string; + if self.address.contains(":") { // IPv6 address is enclosed in [brackets] + display_string = write!(f, "[{}]:{}{}", self.address, self.port, my_interface_string); + } + else { + display_string = write!(f, "{}:{}{}", self.address, self.port, my_interface_string); + } + return display_string; } } diff --git a/src/thread_parse_packets_functions.rs b/src/thread_parse_packets_functions.rs index e35fcc3c..188d64cd 100644 --- a/src/thread_parse_packets_functions.rs +++ b/src/thread_parse_packets_functions.rs @@ -164,16 +164,8 @@ fn analyze_network_header(network_header: Option, exchanged_bytes: &mu } Some(IpHeader::Version6(ipv6header, _)) => { *network_layer = "ipv6".to_string(); - *address1 = format!("{:?}", ipv6header.source) - .replace("[", "") - .replace("]", "") - .replace(",", ".") - .replace(" ", ""); - *address2 = format!("{:?}", ipv6header.destination) - .replace("[", "") - .replace("]", "") - .replace(",", ".") - .replace(" ", ""); + *address1 = ipv6_from_long_dec_to_short_hex(ipv6header.source); + *address2 = ipv6_from_long_dec_to_short_hex(ipv6header.destination); *exchanged_bytes = ipv6header.payload_length as u32; } _ => { @@ -378,4 +370,195 @@ fn from_port_to_application_protocol(port: u16) -> Option { 5353 => {Option::Some(AppProtocol::mDNS)}, _ => {None} } +} + + +// Test for this function at the end of this file (run with cargo test) +/// Function to convert a long decimal ipv6 address to a +/// shorter compressed ipv6 address +/// +/// # Arguments +/// +/// * `ipv6_long` - Contains the 16 integer composing the not compressed decimal ipv6 address +/// +/// # Example +/// +/// ``` +/// let result = ipv6_from_long_dec_to_short_hex([255,10,10,255,0,0,0,0,28,4,4,28,255,1,0,0]); +/// assert_eq!(result, "ff0a:aff::1c04:41c:ff01:0".to_string()); +/// ``` +pub fn ipv6_from_long_dec_to_short_hex(ipv6_long: [u8;16]) -> String { + + //from hex to dec, paying attention to the correct number of digits + let mut ipv6_hex = "".to_string(); + for i in 0..=15 { + //pari: primo byte del gruppo + if i % 2 == 0 { + if *ipv6_long.get(i).unwrap() == 0 { + continue; + } + ipv6_hex.push_str(&format!("{:x}", ipv6_long.get(i).unwrap())); + } + + //dispari: secondo byte del gruppo + else { + if *ipv6_long.get(i-1).unwrap() == 0 { + ipv6_hex.push_str(&format!("{:x}:", ipv6_long.get(i).unwrap())); + } + else { + ipv6_hex.push_str(&format!("{:02x}:", ipv6_long.get(i).unwrap())); + } + } + } + ipv6_hex.pop(); + + // search for the longest zero sequence in the ipv6 address + let mut to_compress: Vec<&str> = ipv6_hex.split(':').collect(); + let mut longest_zero_sequence = 0; // max number of consecutive zeros + let mut longest_zero_sequence_start = 0; // first index of the longest sequence of zeros + let mut current_zero_sequence = 0; + let mut current_zero_sequence_start = 0; + let mut i = 0; + for s in to_compress.clone() { + if s.eq("0") { + if current_zero_sequence == 0 { + current_zero_sequence_start = i; + } + current_zero_sequence += 1; + } + else { + if current_zero_sequence != 0 { + if current_zero_sequence > longest_zero_sequence { + longest_zero_sequence = current_zero_sequence; + longest_zero_sequence_start = current_zero_sequence_start; + } + current_zero_sequence = 0; + } + } + i += 1; + } + if current_zero_sequence != 0 { // to catch consecutive zeros at the end + if current_zero_sequence > longest_zero_sequence { + longest_zero_sequence = current_zero_sequence; + longest_zero_sequence_start = current_zero_sequence_start; + } + current_zero_sequence = 0; + } + if longest_zero_sequence < 2 { // no compression needed + return ipv6_hex; + } + + //from longest sequence of consecutive zeros to '::' + let mut ipv6_hex_compressed = "".to_string(); + for _ in 0..longest_zero_sequence { + to_compress.remove(longest_zero_sequence_start); + } + i = 0; + if longest_zero_sequence_start == 0 { + ipv6_hex_compressed.push_str("::"); + } + for s in to_compress { + ipv6_hex_compressed.push_str(s); + ipv6_hex_compressed.push(':'); + i += 1; + if i == longest_zero_sequence_start { + ipv6_hex_compressed.push(':'); + } + } + if ipv6_hex_compressed.ends_with("::") { + return ipv6_hex_compressed; + } + ipv6_hex_compressed.pop(); + + ipv6_hex_compressed +} + + +#[cfg(test)] +mod ipv6_format_tests { + use crate::thread_parse_packets_functions::ipv6_from_long_dec_to_short_hex; + + #[test] + fn simple_test() { + let result = ipv6_from_long_dec_to_short_hex([255,10,10,255,255,10,10,255,255,10,10,255,255,10,10,255,]); + assert_eq!(result, "ff0a:aff:ff0a:aff:ff0a:aff:ff0a:aff".to_string()); + } + + #[test] + fn zeros_in_the_middle() { + let result = ipv6_from_long_dec_to_short_hex([255,10,10,255,0,0,0,0,28,4,4,28,255,1,0,0]); + assert_eq!(result, "ff0a:aff::1c04:41c:ff01:0".to_string()); + } + + #[test] + fn leading_zeros() { + let result = ipv6_from_long_dec_to_short_hex([0,0,0,0,0,0,0,0,28,4,4,28,255,1,0,10]); + assert_eq!(result, "::1c04:41c:ff01:a".to_string()); + } + + #[test] + fn tail_one_after_zeros() { + let result = ipv6_from_long_dec_to_short_hex([28,4,4,28,255,1,0,10,0,0,0,0,0,0,0,1]); + assert_eq!(result, "1c04:41c:ff01:a::1".to_string()); + } + + #[test] + fn tail_zeros() { + let result = ipv6_from_long_dec_to_short_hex([28,4,4,28,255,1,0,10,0,0,0,0,0,0,0,0]); + assert_eq!(result, "1c04:41c:ff01:a::".to_string()); + } + + #[test] + fn multiple_zero_sequences_first_longer() { + let result = ipv6_from_long_dec_to_short_hex([32,0,0,0,0,0,0,0,1,1,0,0,0,0,0,1]); + assert_eq!(result, "2000::101:0:0:1".to_string()); + } + + #[test] + fn multiple_zero_sequences_first_longer_head() { + let result = ipv6_from_long_dec_to_short_hex([0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,1]); + assert_eq!(result, "::101:0:0:1".to_string()); + } + + #[test] + fn multiple_zero_sequences_second_longer() { + let result = ipv6_from_long_dec_to_short_hex([1,0,0,0,0,0,0,1,0,0,0,0,0,0,3,118]); + assert_eq!(result, "100:0:0:1::376".to_string()); + } + + #[test] + fn multiple_zero_sequences_second_longer_tail() { + let result = ipv6_from_long_dec_to_short_hex([32,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0]); + assert_eq!(result, "2000:0:0:1:101::".to_string()); + } + + #[test] + fn multiple_zero_sequences_equal_length() { + let result = ipv6_from_long_dec_to_short_hex([118,3,0,0,0,0,0,1,1,1,0,0,0,0,0,1]); + assert_eq!(result, "7603::1:101:0:0:1".to_string()); + } + + #[test] + fn all_zeros() { + let result = ipv6_from_long_dec_to_short_hex([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]); + assert_eq!(result, "::".to_string()); + } + + #[test] + fn x_all_zeros() { + let result = ipv6_from_long_dec_to_short_hex([161,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]); + assert_eq!(result, "a100::".to_string()); + } + + #[test] + fn all_zeros_x() { + let result = ipv6_from_long_dec_to_short_hex([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,176]); + assert_eq!(result, "::b0".to_string()); + } + + #[test] + fn many_zeros_but_no_compression() { + let result = 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()); + } } \ No newline at end of file