added function to parse IPv6 addresses and relative tests

This commit is contained in:
Giuliano Bellini s294739 2022-08-19 00:20:29 +02:00
parent 8fbc77f0fd
commit 6bd5160d56
2 changed files with 201 additions and 11 deletions

View file

@ -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;
}
}

View file

@ -164,16 +164,8 @@ fn analyze_network_header(network_header: Option<IpHeader>, 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<AppProtocol> {
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());
}
}