Added new functionality to Network and changed error handling to be a single enum. create_subnet() is still WIP

This commit is contained in:
2023-04-17 17:24:35 +01:00
parent a067a3e349
commit e1a978cb1f
2 changed files with 78 additions and 27 deletions

View File

@ -3,49 +3,95 @@ use ip::IpAddr;
pub mod ip;
#[derive(Debug, PartialEq, Eq)]
pub struct InvalidCIDRErr;
#[allow(dead_code)]
#[derive(Debug, Eq, PartialEq)]
pub enum NetworkingErr {
InvalidCIDRErr,
InvalidSubnetMask,
InvalidNetwork,
InvalidIPErr
}
#[allow(unused)]
pub struct Network {
network_address: IpAddr,
broadcast_addr: IpAddr,
num_hosts: u32,
subnet_mask: Option<IpAddr>
}
impl Network {
// pub fn new(given_address: &IpAddr, CIDR: u8) -> Network {
// }
#[allow(non_snake_case)]
#[allow(unused)]
/// Function that constucts a network struct.
///
/// ```
/// let network = Network::new(&IpAddr::V4(127, 0, 0, 1), 32);
/// ```
pub fn new(given_address: &IpAddr, subnet_mask: &IpAddr) -> Network {
Network {
network_address: given_address.clone(),
broadcast_addr: given_address.clone(),
num_hosts: 0,
subnet_mask: Some(subnet_mask.clone())
}
}
/// Function that constucts a subnet, returning a vector of all subnets included
///
/// ```
/// let networks = Network::create_subnet(&IpAddr::V4(127, 0, 0, 1), 32);
/// ```
pub fn create_subnet(network_address: &IpAddr, cidr: u8) -> Result<Vec<Network>, NetworkingErr> {
//Get number of host and network bits.
let subnet_mask = match Network::gen_subnet_mask(cidr) {
Ok(ip) => ip,
Err(_) => return Err(NetworkingErr::InvalidCIDRErr)
};
let network_bits = match subnet_mask {
IpAddr::V4(oct1, oct2, oct3, oct4) => {
oct1.count_zeros() + oct2.count_zeros() + oct3.count_zeros() + oct4.count_zeros()
},
IpAddr::V6(_) => return Err(NetworkingErr::InvalidIPErr)
};
//Determine the number of networks needed for the subnet.
let num_networks = get_num_networks(network_bits);
//Get first address of each network
//Use Class constructor to generate each network.
Ok(vec![Network::new(&IpAddr::V4(0, 0, 0, 0), &IpAddr::V4(0, 0, 0, 0))])
}
/// Function that takes in a u8 CIDR and converts it to an IP address.
///
/// ```
/// let CIDR: u8 = 22
/// let subnet_mask: [u8; 4] = gen_subnet_mask(CIDR);
/// let cidr: u8 = 22
/// let subnet_mask: [u8; 4] = gen_subnet_mask(cidr);
///
/// >> IpAddr::V4(255, 255, 252, 0)
/// ```
pub fn gen_subnet_mask(mut CIDR: u8) -> Result<IpAddr, InvalidCIDRErr> {
if CIDR > 32 {
return Err(InvalidCIDRErr)
fn gen_subnet_mask(mut cidr: u8) -> Result<IpAddr, NetworkingErr> {
if cidr > 32 {
return Err(NetworkingErr::InvalidCIDRErr)
}
let mut oct: [u8; 4] = [0; 4];
for octet in oct.iter_mut() {
*octet = if usize::from(CIDR) >= 8 {
CIDR -= 8;
*octet = if usize::from(cidr) >= 8 {
cidr -= 8;
u8::MAX
}else{
// Count the number of remaining 1s and convert to binary
let mut count: u8 = 0;
for i in ((8-CIDR)..8).rev() {
for i in ((8-cidr)..8).rev() {
count += u8::pow(2, u32::from(i));
}
CIDR = 0;
cidr = 0;
count
}
}
@ -55,10 +101,14 @@ impl Network {
//pub fn generate_subnets(self) -> Vec<Network> {}
}
enum NetworkClassBits {
A = 8,
B = 16,
C = 24
fn get_num_networks(mut network_bits: u8) -> u8 {
for _ in 0..4 {
if (network_bits / 8) > 1 {
network_bits -= 8;
continue;
}
};
network_bits
}
/// Function that takes in a string reference and returns the result of splitting a string into
@ -123,6 +173,6 @@ mod tests {
assert_eq!(Network::gen_subnet_mask(24).unwrap(), IpAddr::V4(255, 255, 255, 0));
assert_eq!(Network::gen_subnet_mask(0).unwrap(), IpAddr::V4(0, 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(), InvalidCIDRErr);
assert_eq!(Network::gen_subnet_mask(35).unwrap_err(), NetworkingErr::InvalidCIDRErr);
}
}