From d1d4bc02ca1329a7d0d50cd8b5ba1ec9290c39fb Mon Sep 17 00:00:00 2001 From: Luke Else Date: Sun, 9 Apr 2023 10:07:15 +0100 Subject: [PATCH] Added function to convert CIDR to subnet mask --- src/main.rs | 2 +- src/networking/mod.rs | 62 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index 1a2a658..a28a8cb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ use std::{io}; + mod networking; #[allow(unused_variables, unused_mut, unused_assignments)] @@ -22,6 +23,5 @@ fn main() { break; } - println!("IP: {}, CIDR: {}", ip_and_cidr.0.to_string(), ip_and_cidr.1); } diff --git a/src/networking/mod.rs b/src/networking/mod.rs index d35a756..0497185 100644 --- a/src/networking/mod.rs +++ b/src/networking/mod.rs @@ -1,6 +1,8 @@ use std::{str::FromStr}; use ip::IpAddr; +use self::ip::InvalidIPErr; + pub mod ip; #[allow(unused)] @@ -11,8 +13,52 @@ pub struct Network { } impl Network { -// pub fn generate_subnets(self) -> Vec {} -// fn get_net_id(self) -> u8 {} + // pub fn new(given_address: IpAddr, CIDR: u8) -> Network { + // //Generate subnet Mask + // } + + + #[allow(non_snake_case)] + /// 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); + /// + /// >> IpAddr::V4(255, 255, 252, 0) + /// ``` + pub fn gen_subnet_mask(mut CIDR: u8) -> Result { + if CIDR > 32 { + return Err(InvalidIPErr) + } + + let mut oct: [u8; 4] = [0; 4]; + + for octet in oct.iter_mut() { + *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() { + count += u8::pow(2, u32::from(i)); + } + CIDR = 0; + count + } + } + + Ok(IpAddr::V4(oct[0], oct[1], oct[2], oct[3])) + } + //pub fn generate_subnets(self) -> Vec {} + //fn get_net_id(self) -> u8 {} +} + +enum NetworkClassBits { + A = 8, + B = 16, + C = 24 } /// Function that takes in a string reference and returns the result of splitting a string into @@ -44,7 +90,6 @@ pub fn ip_and_cidr_from_string(ip_and_cidr: &String) -> Result<(IpAddr, u8), ip: Ok(cidr) => cidr } }; - println!("CIDR: {:?}", cidr); } let ip_address: IpAddr = match IpAddr::from_str(&ip.trim()) { @@ -69,4 +114,15 @@ mod tests { assert_eq!(result.0, IpAddr::V4(127, 0, 0, 1)); assert_eq!(result.1, 8); } + + #[test] + fn cidr_to_ip_test() { + use super::*; + + assert_eq!(Network::gen_subnet_mask(22).unwrap(), IpAddr::V4(255, 255, 252, 0)); + 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(), InvalidIPErr); + } } \ No newline at end of file