Added new functionality to Network and changed error handling to be a single enum. create_subnet() is still WIP
This commit is contained in:
		@@ -1,4 +1,5 @@
 | 
			
		||||
use std::str::FromStr;
 | 
			
		||||
use super::NetworkingErr;
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, PartialEq, Eq)]
 | 
			
		||||
pub struct InvalidIPErr;
 | 
			
		||||
@@ -12,7 +13,7 @@ pub struct InvalidIPErr;
 | 
			
		||||
/// IpAddr::V6(String::from("::1"))
 | 
			
		||||
/// ```
 | 
			
		||||
#[allow(unused)]
 | 
			
		||||
#[derive(Debug, PartialEq, Eq)]
 | 
			
		||||
#[derive(Debug, PartialEq, Eq, Clone)]
 | 
			
		||||
pub enum IpAddr {
 | 
			
		||||
    V4(u8, u8, u8, u8),
 | 
			
		||||
    V6(String)
 | 
			
		||||
@@ -30,7 +31,7 @@ impl ToString for IpAddr {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
impl FromStr for IpAddr {
 | 
			
		||||
    type Err = InvalidIPErr;
 | 
			
		||||
    type Err = NetworkingErr;
 | 
			
		||||
    /// Function that generates a IpAddr / Err from a string
 | 
			
		||||
    /// 
 | 
			
		||||
    /// # Limitation
 | 
			
		||||
@@ -46,18 +47,18 @@ impl FromStr for IpAddr {
 | 
			
		||||
        let split_ip = s.split('.');
 | 
			
		||||
        if split_ip.clone().count() != 4 {
 | 
			
		||||
            //Invalid IP address entered
 | 
			
		||||
            return Err(InvalidIPErr)
 | 
			
		||||
            return Err(super::NetworkingErr::InvalidIPErr)
 | 
			
		||||
        }
 | 
			
		||||
        let mut ip: [u8; 4] = Default::default();
 | 
			
		||||
        //Go through each octet and ensure it can be parsed;
 | 
			
		||||
        for (i, oct) in split_ip.into_iter().enumerate() {
 | 
			
		||||
            if i > ip.len() {
 | 
			
		||||
                //Ip string is out of the range of the 4 octets in an IPv4 Address
 | 
			
		||||
                return Err(InvalidIPErr)
 | 
			
		||||
                return Err(NetworkingErr::InvalidIPErr)
 | 
			
		||||
            }
 | 
			
		||||
            match oct.parse::<u8>() {
 | 
			
		||||
                Ok(parsed_oct) => ip[i] = parsed_oct,
 | 
			
		||||
                Err(_) => return Err(InvalidIPErr)
 | 
			
		||||
                Err(_) => return Err(NetworkingErr::InvalidIPErr)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        Ok(IpAddr::V4(ip[0],ip[1],ip[2],ip[3]))
 | 
			
		||||
@@ -106,6 +107,6 @@ mod tests {
 | 
			
		||||
        use super::*;
 | 
			
		||||
        let ip = "127.0.0.0.1";
 | 
			
		||||
        IpAddr::from_str(ip).unwrap();
 | 
			
		||||
        assert_eq!(IpAddr::from_str(ip), Err(InvalidIPErr))
 | 
			
		||||
        assert_eq!(IpAddr::from_str(ip), Err(NetworkingErr::InvalidIPErr))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user