Removed create_subnet function because of incorrect implementation, required network class to be take into account. Added network class and relevant tests

This commit is contained in:
Luke Else 2023-04-25 21:45:43 +01:00
parent 44bafbd0e6
commit d0da5f587f
2 changed files with 43 additions and 54 deletions

View File

@ -7,6 +7,11 @@ mod networking;
#[allow(unused_variables, unused_mut, unused_assignments)] #[allow(unused_variables, unused_mut, unused_assignments)]
fn main() { fn main() {
let networks = Network::create_subnet(&networking::ip::IpAddr::V4(127, 0, 0, 1), 23);
if networks.is_err() {
println!("Hello!");
}
println!("Enter the IP and cidr for your given network"); println!("Enter the IP and cidr for your given network");
let ip_and_cidr: (networking::ip::IpAddr, u8); let ip_and_cidr: (networking::ip::IpAddr, u8);

View File

@ -1,6 +1,8 @@
use std::str::FromStr; use std::{str::FromStr, f32::consts::E};
use ip::IpAddr; use ip::IpAddr;
use self::ip::InvalidIPErr;
pub mod ip; pub mod ip;
#[allow(dead_code)] #[allow(dead_code)]
@ -13,6 +15,7 @@ pub enum NetworkingErr {
} }
/// enum to allow the identification of the class of the network /// enum to allow the identification of the class of the network
#[derive(Debug, Eq, PartialEq)]
enum NetworkClass { enum NetworkClass {
A = 8, A = 8,
B = 16, B = 16,
@ -54,63 +57,31 @@ impl Network {
let subnet_mask = Network::gen_subnet_mask(cidr)?.to_arr()?; let subnet_mask = Network::gen_subnet_mask(cidr)?.to_arr()?;
let network_address = network_address.to_arr()?; let network_address = network_address.to_arr()?;
let mut network_bits: u8 = Default::default(); // Determine the network class that the given address is in.
let mut host_bits: u8 = Default::default();
//Get first address of each network let networks = vec![];
//Need to get the most significant octet
//Get number of bits available for host in specific octet
let mut most_sig_octet: usize = Default::default();
for (i, oct) in subnet_mask.iter().enumerate(){
if *oct == 0 {
most_sig_octet = i-1;
break;
}
if *oct < 255 {
most_sig_octet = i;
network_bits = oct.count_ones() as u8;
break;
}
//There is no significant octet
if i >= 4 {
return Err(NetworkingErr::InvalidSubnetMask);
}
}
host_bits = subnet_mask[most_sig_octet].count_zeros() as u8;
//Determine the number of networks needed for the subnet.
network_bits = subnet_mask.map(|o| o.count_zeros() as u8).iter().sum();
network_bits -= host_bits;
//Determine Spacing -> Incorrect
let network_spacing = u8::pow(2, subnet_mask[most_sig_octet].count_zeros()+1);
//Determine number of networks in the subnet
let mut num_networks: u8 = 0;
for i in 1..=host_bits {
num_networks += u8::pow(2, u32::from(i));
}
//Generate base address
let mut base_address = network_address;
base_address[most_sig_octet] = 255 - num_networks;
for i in most_sig_octet+1..4 {
base_address[i] = 0;
}
//Use Class constructor to generate each network.
let mut networks = vec![];
for i in 0..num_networks {
let mut new_ip = base_address;
new_ip[most_sig_octet] += i * network_spacing;
let new_network = Network::new(&IpAddr::from_arr(&new_ip)?, &IpAddr::from_arr(&subnet_mask)?);
networks.push(new_network);
}
Ok(networks) Ok(networks)
} }
/// Function that is used to determine the class of network that an IP is in.
///
/// ```
/// let network_class = Network::get_network_class(&[127, 0, 0, 1])?;
/// >>> NetworkClass::A
/// ```
fn get_network_class(network_address: &[u8; 4]) -> Result<NetworkClass, NetworkingErr> {
if network_address[0] > 224 {
return Err(NetworkingErr::InvalidIPErr)
}else if network_address[0] >= 192 {
return Ok(NetworkClass::C)
}else if network_address[0] >= 128 {
return Ok(NetworkClass::B)
}else if network_address[0] >= 1 {
return Ok(NetworkClass::A);
}
return Err(NetworkingErr::InvalidIPErr)
}
/// Function that takes in a u8 CIDR and converts it to an IP address. /// Function that takes in a u8 CIDR and converts it to an IP address.
/// ///
/// ``` /// ```
@ -210,4 +181,17 @@ mod tests {
assert_eq!(Network::gen_subnet_mask(4).unwrap(), IpAddr::V4(240, 0, 0, 0)); assert_eq!(Network::gen_subnet_mask(4).unwrap(), IpAddr::V4(240, 0, 0, 0));
assert_eq!(Network::gen_subnet_mask(35).unwrap_err(), NetworkingErr::InvalidCIDRErr); assert_eq!(Network::gen_subnet_mask(35).unwrap_err(), NetworkingErr::InvalidCIDRErr);
} }
#[test]
fn test_network_class() {
use super::*;
assert_eq!(Network::get_network_class(&IpAddr::V4(127, 0, 0, 1).to_arr().unwrap()).unwrap(), NetworkClass::A);
assert_eq!(Network::get_network_class(&IpAddr::V4(172, 6, 8, 10).to_arr().unwrap()).unwrap(), NetworkClass::B);
assert_eq!(Network::get_network_class(&IpAddr::V4(192, 168, 0, 1).to_arr().unwrap()).unwrap(), NetworkClass::C);
assert_eq!(Network::get_network_class(&IpAddr::V4(10, 6, 8, 10).to_arr().unwrap()).unwrap(), NetworkClass::A);
assert_eq!(Network::get_network_class(&IpAddr::V4(225, 255, 255, 255).to_arr().unwrap()).unwrap_err(), NetworkingErr::InvalidIPErr);
assert_eq!(Network::get_network_class(&IpAddr::V4(225, 0, 0, 0).to_arr().unwrap()).unwrap_err(), NetworkingErr::InvalidIPErr);
assert_eq!(Network::get_network_class(&IpAddr::V4(0, 0, 0, 0).to_arr().unwrap()).unwrap_err(), NetworkingErr::InvalidIPErr);
assert_eq!(Network::get_network_class(&IpAddr::V4(0, 0, 0, 1).to_arr().unwrap()).unwrap_err(), NetworkingErr::InvalidIPErr);
}
} }